Decompiled source of ShieldsMod v1.0.0

ShieldsMod.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using InfoOverhaul.Delta;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using ShieldsMod.Cards;
using ShieldsMod.Networking;
using ShieldsMod.Poison;
using ShieldsMod.Shield;
using UnboundLib;
using UnboundLib.Cards;
using UnboundLib.GameModes;
using UnboundLib.Networking;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyCompany("ShieldsMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+661a91535814621160b5d94d61679bade4fe1c2d")]
[assembly: AssemblyProduct("Shields Mod for ROUNDS")]
[assembly: AssemblyTitle("ShieldsMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ShieldsMod
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("ShieldsMod", "Shields Mod for ROUNDS", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private void Awake()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			SLog.Section("Plugin Awake");
			new Harmony("ShieldsMod").PatchAll();
			((Component)this).gameObject.AddComponent<ShieldManager>();
			((Component)this).gameObject.AddComponent<PoisonResistanceManager>();
			ShieldCardRegistrar.RegisterAll();
			PoisonCardRegistrar.RegisterAll();
			SLog.Line("Plugin ShieldsMod loaded.");
		}
	}
	internal static class SLog
	{
		private const string Sep = "=====================";

		public static void Section(string title)
		{
			Plugin.Logger.LogInfo((object)"=====================");
			Plugin.Logger.LogInfo((object)("[ShieldsMod] " + title));
			Plugin.Logger.LogInfo((object)"=====================");
		}

		public static void Line(string message)
		{
			Plugin.Logger.LogInfo((object)("[ShieldsMod] " + message));
		}

		public static void Warn(string message)
		{
			Plugin.Logger.LogWarning((object)("[ShieldsMod] " + message));
		}

		public static void Error(string message)
		{
			Plugin.Logger.LogError((object)("[ShieldsMod] " + message));
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "ShieldsMod";

		public const string PLUGIN_NAME = "Shields Mod for ROUNDS";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace ShieldsMod.Shield
{
	internal static class ShieldHandRebuild
	{
		private static Dictionary<string, float> _multiplierByCardName;

		internal static void RegisterTier(CardInfo card, float multiplier)
		{
			if (!((Object)(object)card == (Object)null) && !string.IsNullOrEmpty(card.cardName))
			{
				if (_multiplierByCardName == null)
				{
					_multiplierByCardName = new Dictionary<string, float>(StringComparer.Ordinal);
				}
				_multiplierByCardName[card.cardName] = multiplier;
			}
		}

		internal static void RebuildForPlayer(int playerID)
		{
			if ((Object)(object)ShieldManager.instance == (Object)null || (Object)(object)PlayerManager.instance == (Object)null)
			{
				return;
			}
			Player val = PlayerManager.instance.players.Find((Player p) => p.playerID == playerID);
			if (val?.data?.currentCards == null)
			{
				return;
			}
			float num = 100f;
			int num2 = 0;
			if (_multiplierByCardName != null)
			{
				foreach (CardInfo currentCard in val.data.currentCards)
				{
					if (!((Object)(object)currentCard == (Object)null))
					{
						string cardName = currentCard.cardName;
						if (string.IsNullOrEmpty(cardName) && (Object)(object)currentCard.sourceCard != (Object)null)
						{
							cardName = currentCard.sourceCard.cardName;
						}
						if (!string.IsNullOrEmpty(cardName) && _multiplierByCardName.TryGetValue(cardName, out var value))
						{
							num *= value;
							num2++;
						}
					}
				}
			}
			ShieldState orCreateShield = ShieldManager.instance.GetOrCreateShield(playerID);
			float max = orCreateShield.Max;
			orCreateShield.Max = num;
			orCreateShield.Current = Mathf.Min(orCreateShield.Current, orCreateShield.Max);
			ShieldManager.instance.RefreshVisual(playerID);
			SLog.Line($"ShieldHandRebuild player={playerID} tiers={num2} max {max:F0} -> {orCreateShield.Max:F0} current={orCreateShield.Current:F0}");
		}
	}
	public class ShieldManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnBattleStart>d__8 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <OnBattleStart>d__8(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				instance?.ResetAllForBattle();
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <OnGameStart>d__10 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <OnGameStart>d__10(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				instance?.CleanupOrphanedAttachments();
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <OnPointEnd>d__9 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <OnPointEnd>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				instance?.CleanupOrphanedAttachments();
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static ShieldManager instance;

		private readonly Dictionary<int, ShieldState> _shields = new Dictionary<int, ShieldState>();

		private readonly Dictionary<int, ShieldVisual> _visuals = new Dictionary<int, ShieldVisual>();

		private readonly Dictionary<int, ShieldParryTrigger> _parryTriggers = new Dictionary<int, ShieldParryTrigger>();

		private readonly Dictionary<int, float> _poisonDrainBlockedUntil = new Dictionary<int, float>();

		private const float PoisonDrainBlockDuration = 4f;

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			SLog.Section("ShieldManager — Awake");
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
			GameModeManager.AddHook("PointEnd", (Func<IGameModeHandler, IEnumerator>)OnPointEnd);
			GameModeManager.AddHook("GameStart", (Func<IGameModeHandler, IEnumerator>)OnGameStart);
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		[IteratorStateMachine(typeof(<OnBattleStart>d__8))]
		private static IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnBattleStart>d__8(0);
		}

		[IteratorStateMachine(typeof(<OnPointEnd>d__9))]
		private static IEnumerator OnPointEnd(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnPointEnd>d__9(0);
		}

		[IteratorStateMachine(typeof(<OnGameStart>d__10))]
		private static IEnumerator OnGameStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnGameStart>d__10(0);
		}

		public void ResetAllForBattle()
		{
			_poisonDrainBlockedUntil.Clear();
			SLog.Section("ShieldManager — ResetAllForBattle");
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				SLog.Warn("PlayerManager.instance is null.");
				return;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				if (!((Object)(object)player == (Object)null))
				{
					ShieldState orCreateShield = GetOrCreateShield(player.playerID);
					orCreateShield.ResetToFull();
					EnsureAttachments(player, orCreateShield);
					RefreshVisual(player.playerID);
					SLog.Line($"player={player.playerID} shield={orCreateShield.Current}/{orCreateShield.Max}");
				}
			}
		}

		public ShieldState GetOrCreateShield(int playerID)
		{
			if (!_shields.TryGetValue(playerID, out var value))
			{
				value = new ShieldState();
				_shields[playerID] = value;
			}
			return value;
		}

		public ShieldState GetShield(int playerID)
		{
			return GetOrCreateShield(playerID);
		}

		public bool TryAbsorbFull(int playerID, float damageAmount, out bool depleted)
		{
			depleted = false;
			ShieldState orCreateShield = GetOrCreateShield(playerID);
			if (!orCreateShield.IsActive || damageAmount <= 0f)
			{
				return false;
			}
			if (damageAmount >= orCreateShield.Current)
			{
				orCreateShield.Current = 0f;
				depleted = true;
			}
			else
			{
				orCreateShield.Current -= damageAmount;
			}
			RefreshVisual(playerID);
			return true;
		}

		public void MarkPoisonDepleted(int playerID)
		{
			_poisonDrainBlockedUntil[playerID] = Time.time + 4f;
		}

		public bool IsPoisonDrainBlocked(int playerID)
		{
			if (_poisonDrainBlockedUntil.TryGetValue(playerID, out var value))
			{
				return Time.time < value;
			}
			return false;
		}

		public void RefreshVisual(int playerID)
		{
			if (_visuals.TryGetValue(playerID, out var value) && (Object)(object)value != (Object)null)
			{
				value.Refresh();
			}
			if (_parryTriggers.TryGetValue(playerID, out var value2) && (Object)(object)value2 != (Object)null)
			{
				value2.UpdateEnabled();
			}
		}

		private void EnsureAttachments(Player player, ShieldState state)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			int playerID = player.playerID;
			if (!_visuals.TryGetValue(playerID, out var value) || (Object)(object)value == (Object)null)
			{
				GameObject val = new GameObject($"ShieldVisual_P{playerID}");
				val.transform.SetParent(((Component)player).transform, false);
				value = val.AddComponent<ShieldVisual>();
				value.Init(player, state);
				_visuals[playerID] = value;
			}
			else
			{
				value.SetState(state);
				value.Refresh();
			}
			if (!_parryTriggers.TryGetValue(playerID, out var value2) || (Object)(object)value2 == (Object)null)
			{
				GameObject val2 = new GameObject($"ShieldParry_P{playerID}");
				val2.transform.SetParent(((Component)player).transform, false);
				value2 = val2.AddComponent<ShieldParryTrigger>();
				float radius = ShieldVisual.GetBodyRadius(player) * 1.44f;
				value2.Init(player, state, radius);
				_parryTriggers[playerID] = value2;
			}
			else
			{
				value2.SetState(state);
				value2.UpdateEnabled();
			}
		}

		private void CleanupOrphanedAttachments()
		{
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, ShieldVisual> visual in _visuals)
			{
				if ((Object)(object)visual.Value == (Object)null)
				{
					list.Add(visual.Key);
				}
			}
			foreach (int item in list)
			{
				_visuals.Remove(item);
			}
			List<int> list2 = new List<int>();
			foreach (KeyValuePair<int, ShieldParryTrigger> parryTrigger in _parryTriggers)
			{
				if ((Object)(object)parryTrigger.Value == (Object)null)
				{
					list2.Add(parryTrigger.Key);
				}
			}
			foreach (int item2 in list2)
			{
				_parryTriggers.Remove(item2);
			}
		}
	}
	public class ShieldParryTrigger : MonoBehaviour
	{
		private Player _owner;

		private Block _block;

		private CircleCollider2D _trigger;

		private ShieldState _state;

		private readonly HashSet<int> _recentlyDeflected = new HashSet<int>();

		public void Init(Player owner, ShieldState state, float radius)
		{
			_owner = owner;
			_state = state;
			_block = ((Component)owner).GetComponent<Block>();
			_trigger = ((Component)this).gameObject.AddComponent<CircleCollider2D>();
			((Collider2D)_trigger).isTrigger = true;
			_trigger.radius = radius;
			Rigidbody2D obj = ((Component)this).gameObject.AddComponent<Rigidbody2D>();
			obj.bodyType = (RigidbodyType2D)1;
			obj.simulated = true;
			UpdateEnabled();
		}

		public void SetState(ShieldState state)
		{
			_state = state;
		}

		public void SetRadius(float worldRadius)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_owner == (Object)null) && !((Object)(object)_trigger == (Object)null))
			{
				float num = Mathf.Max(((Component)_owner).transform.localScale.x, 0.01f);
				_trigger.radius = worldRadius / num;
			}
		}

		public void UpdateEnabled()
		{
			if ((Object)(object)_trigger != (Object)null)
			{
				((Behaviour)_trigger).enabled = _state != null && _state.IsActive;
			}
		}

		private void LateUpdate()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_owner == (Object)null))
			{
				((Component)this).transform.position = ((Component)_owner).transform.position;
				float bodyRadius = ShieldVisual.GetBodyRadius(_owner);
				SetRadius(bodyRadius * 1.44f);
				UpdateEnabled();
			}
		}

		private void OnTriggerEnter2D(Collider2D other)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_owner == (Object)null || (Object)(object)_block == (Object)null || _state == null || !_state.IsActive || !_block.IsBlocking())
			{
				return;
			}
			ProjectileHit val = ((Component)other).GetComponent<ProjectileHit>() ?? ((Component)other).GetComponentInParent<ProjectileHit>();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			PhotonView component = ((Component)val).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null || !component.IsMine)
			{
				return;
			}
			int instanceID = ((Object)((Component)val).gameObject).GetInstanceID();
			if (!_recentlyDeflected.Contains(instanceID) && IsEnemyProjectile(val))
			{
				Vector3 position = ((Component)val).transform.position;
				Vector3 val2 = ((Component)val).transform.forward;
				if (((Vector3)(ref val2)).sqrMagnitude < 0.001f)
				{
					Vector3 val3 = position - ((Component)_owner).transform.position;
					val2 = ((Vector3)(ref val3)).normalized;
				}
				_recentlyDeflected.Add(instanceID);
				_block.DoBlock(((Component)val).gameObject, val2, position);
				SLog.Line($"Outer parry player={_owner.playerID} projectile={((Object)((Component)val).gameObject).name}");
			}
		}

		private bool IsEnemyProjectile(ProjectileHit projHit)
		{
			Player val = projHit.ownPlayer;
			if ((Object)(object)val == (Object)null)
			{
				SpawnedAttack component = ((Component)projHit).GetComponent<SpawnedAttack>();
				if ((Object)(object)component != (Object)null)
				{
					val = component.spawner;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (val.playerID != _owner.playerID)
			{
				return (Object)(object)((Component)val).transform.root != (Object)(object)((Component)_owner).transform.root;
			}
			return false;
		}

		private void OnTriggerExit2D(Collider2D other)
		{
			ProjectileHit val = ((Component)other).GetComponent<ProjectileHit>() ?? ((Component)other).GetComponentInParent<ProjectileHit>();
			if ((Object)(object)val != (Object)null)
			{
				_recentlyDeflected.Remove(((Object)((Component)val).gameObject).GetInstanceID());
			}
		}
	}
	public class ShieldState
	{
		public const float DefaultMax = 100f;

		public float Max = 100f;

		public float Current = 100f;

		public const float BubbleAlpha = 0.05f;

		public float Percent
		{
			get
			{
				if (!(Max > 0f))
				{
					return 0f;
				}
				return Current / Max;
			}
		}

		public bool IsActive => Current > 0f;

		public void ResetToFull()
		{
			Current = Max;
		}

		public Color GetBubbleColor(float alpha = 0.05f)
		{
			//IL_005d: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			float percent = Percent;
			Color val = default(Color);
			if (percent > 0.65f)
			{
				((Color)(ref val))..ctor(0.2f, 0.9f, 0.25f);
			}
			else if (percent > 0.35f)
			{
				((Color)(ref val))..ctor(0.95f, 0.85f, 0.15f);
			}
			else
			{
				((Color)(ref val))..ctor(0.95f, 0.2f, 0.15f);
			}
			return new Color(val.r, val.g, val.b, alpha);
		}
	}
	public class ShieldVisual : MonoBehaviour
	{
		public const float SizeMultiplier = 1.44f;

		private const int CircleTexSize = 128;

		private Player _player;

		private SpriteRenderer _sprite;

		private ShieldState _state;

		public static Sprite SharedCircleSprite { get; private set; }

		public void Init(Player player, ShieldState state)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			_player = player;
			_state = state;
			if ((Object)(object)SharedCircleSprite == (Object)null)
			{
				SharedCircleSprite = CreateCircleSprite(128);
			}
			GameObject val = new GameObject("ShieldBubbleSprite");
			val.transform.SetParent(((Component)this).transform, false);
			_sprite = val.AddComponent<SpriteRenderer>();
			_sprite.sprite = SharedCircleSprite;
			((Renderer)_sprite).sortingOrder = -1;
			int num = SortingLayer.NameToID("Player" + (player.playerID + 1));
			if (num != 0)
			{
				((Renderer)_sprite).sortingLayerID = num;
			}
			player.data.SetWobbleObjectChild(((Component)this).transform);
			Refresh();
		}

		public void SetState(ShieldState state)
		{
			_state = state;
		}

		public void Refresh()
		{
			//IL_005c: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_sprite == (Object)null || (Object)(object)_player == (Object)null || _state == null)
			{
				return;
			}
			if (!_state.IsActive)
			{
				((Renderer)_sprite).enabled = false;
				return;
			}
			((Renderer)_sprite).enabled = true;
			_sprite.color = _state.GetBubbleColor();
			float num = GetBodyRadius(_player) * 2f * 1.44f;
			Bounds bounds = _sprite.sprite.bounds;
			float x = ((Bounds)(ref bounds)).size.x;
			if (x > 0.0001f)
			{
				((Component)_sprite).transform.localScale = Vector3.one * (num / x);
			}
		}

		public static float GetBodyRadius(Player player)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return 0.5f;
			}
			CircleCollider2D val = ((Component)player).GetComponent<CircleCollider2D>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)player).GetComponentInChildren<CircleCollider2D>();
			}
			return (((Object)(object)val != (Object)null) ? val.radius : 0.5f) * ((Component)player).transform.localScale.x;
		}

		private void LateUpdate()
		{
			if (_state != null && _state.IsActive)
			{
				Refresh();
			}
		}

		private static Sprite CreateCircleSprite(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)1;
			float num = (float)(size - 1) * 0.5f;
			float num2 = num - 1f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num3 = (float)j - num;
					float num4 = (float)i - num;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
					float num6 = ((num5 <= num2) ? 1f : Mathf.Clamp01(1f - (num5 - num2)));
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num6));
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), (float)size);
		}
	}
}
namespace ShieldsMod.Poison
{
	internal static class PoisonDamageDetector
	{
		public static bool IsPoisonDamage(Color blinkColor, GameObject damagingWeapon)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)damagingWeapon != (Object)null)
			{
				if ((Object)(object)damagingWeapon.GetComponentInChildren<RayHitPoison>() != (Object)null)
				{
					return true;
				}
				Transform root = damagingWeapon.transform.root;
				if ((Object)(object)root != (Object)null && (Object)(object)((Component)root).GetComponentInChildren<RayHitPoison>() != (Object)null)
				{
					return true;
				}
			}
			if (blinkColor.g > 0.35f && blinkColor.g >= blinkColor.r)
			{
				return blinkColor.g >= blinkColor.b;
			}
			return false;
		}
	}
	internal static class PoisonHandRebuild
	{
		private static Dictionary<string, float> _reductionByCardName;

		internal static void RegisterTier(string cardName, float totalReduction)
		{
			if (!string.IsNullOrEmpty(cardName))
			{
				if (_reductionByCardName == null)
				{
					_reductionByCardName = new Dictionary<string, float>(StringComparer.Ordinal);
				}
				_reductionByCardName[cardName] = totalReduction;
			}
		}

		internal static float ComputeReductionFromHand(IEnumerable<CardInfo> cards)
		{
			float num = 0f;
			if (_reductionByCardName == null || cards == null)
			{
				return num;
			}
			foreach (CardInfo card in cards)
			{
				if (!((Object)(object)card == (Object)null))
				{
					string cardName = card.cardName;
					if (string.IsNullOrEmpty(cardName) && (Object)(object)card.sourceCard != (Object)null)
					{
						cardName = card.sourceCard.cardName;
					}
					if (!string.IsNullOrEmpty(cardName) && _reductionByCardName.TryGetValue(cardName, out var value))
					{
						num = Math.Max(num, value);
					}
				}
			}
			return num;
		}

		internal static void RebuildForPlayer(int playerID)
		{
			PoisonResistanceManager.instance?.RebuildForPlayer(playerID);
		}
	}
	public class PoisonResistanceManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnBattleStart>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <OnBattleStart>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				if ((Object)(object)PlayerManager.instance == (Object)null)
				{
					return false;
				}
				foreach (Player player in PlayerManager.instance.players)
				{
					if ((Object)(object)player != (Object)null)
					{
						instance?.RebuildForPlayer(player.playerID);
					}
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static PoisonResistanceManager instance;

		private readonly Dictionary<int, float> _reductionByPlayer = new Dictionary<int, float>();

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
			SLog.Section("PoisonResistanceManager — Awake");
		}

		[IteratorStateMachine(typeof(<OnBattleStart>d__3))]
		private static IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnBattleStart>d__3(0);
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		public float GetReduction(int playerID)
		{
			if (!_reductionByPlayer.TryGetValue(playerID, out var value))
			{
				return 0f;
			}
			return value;
		}

		public float GetReductionPercent(int playerID)
		{
			return GetReduction(playerID) * 100f;
		}

		public void RebuildForPlayer(int playerID)
		{
			if (!((Object)(object)PlayerManager.instance == (Object)null))
			{
				Player val = PlayerManager.instance.players.Find((Player p) => p.playerID == playerID);
				if (val?.data?.currentCards != null)
				{
					float num = PoisonHandRebuild.ComputeReductionFromHand(val.data.currentCards);
					_reductionByPlayer[playerID] = num;
					SLog.Line($"PoisonResistance rebuild player={playerID} reduction={num * 100f:F0}%");
				}
			}
		}

		public float ApplyResistance(int playerID, float rawDamage, out float resistedAmount)
		{
			float reduction = GetReduction(playerID);
			resistedAmount = rawDamage * reduction;
			return rawDamage - resistedAmount;
		}
	}
}
namespace ShieldsMod.Patches
{
	[HarmonyPatch]
	internal static class CardDeleteRebuildPatch
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Rounds2Mod.CardDeleteManager");
			if (!(type == null))
			{
				return AccessTools.Method(type, "URPC_SyncDelete", (Type[])null, (Type[])null);
			}
			return null;
		}

		private static bool Prepare()
		{
			bool num = TargetMethod() != null;
			if (!num)
			{
				SLog.Line("CardDeleteRebuildPatch — Rounds2Mod.CardDeleteManager not found; delete hook skipped.");
			}
			return num;
		}

		private static void Postfix(int playerID)
		{
			ShieldHandRebuild.RebuildForPlayer(playerID);
			PoisonHandRebuild.RebuildForPlayer(playerID);
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "DoDamage")]
	internal static class HealthHandlerDoDamagePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(HealthHandler __instance, ref Vector2 damage, Vector2 position, Color blinkColor, GameObject damagingWeapon, Player damagingPlayer, bool healthRemoval, bool lethal, bool ignoreBlock)
		{
			//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_002f: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			if (damage == Vector2.zero)
			{
				return true;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			float magnitude = ((Vector2)(ref damage)).magnitude;
			float num = magnitude;
			bool flag = PoisonDamageDetector.IsPoisonDamage(blinkColor, damagingWeapon);
			if (flag && (Object)(object)PoisonResistanceManager.instance != (Object)null && PoisonResistanceManager.instance.GetReduction(component.playerID) > 0f)
			{
				num = PoisonResistanceManager.instance.ApplyResistance(component.playerID, magnitude, out var _);
				if (num > 0f)
				{
					damage = ((Vector2)(ref damage)).normalized * num;
				}
				else
				{
					damage = Vector2.zero;
				}
			}
			if (num <= 0f)
			{
				return false;
			}
			if ((Object)(object)ShieldManager.instance == (Object)null)
			{
				if (flag && magnitude > num)
				{
					LogPoisonPlayerDamage(component.playerID, magnitude, num);
				}
				return true;
			}
			if (!ShieldManager.instance.TryAbsorbFull(component.playerID, num, out var depleted))
			{
				if (flag && ShieldManager.instance.IsPoisonDrainBlocked(component.playerID))
				{
					SLog.Line($"[ShieldsMod] Poison tick for player {component.playerID} suppressed — shield already drained this DoT.");
					return false;
				}
				if (flag && magnitude > num)
				{
					LogPoisonPlayerDamage(component.playerID, magnitude, num);
				}
				return true;
			}
			if (flag && depleted)
			{
				ShieldManager.instance.MarkPoisonDepleted(component.playerID);
			}
			if (flag && magnitude > num)
			{
				LogPoisonShieldDamage(component.playerID, magnitude, num, depleted);
			}
			damage = Vector2.zero;
			if ((Object)(object)component.data?.view != (Object)null && component.data.view.IsMine)
			{
				ShieldNetworkSync.BroadcastShieldHealth(component.playerID, ShieldManager.instance.GetShield(component.playerID).Current);
			}
			return false;
		}

		private static void LogPoisonPlayerDamage(int playerID, float rawAmount, float actualAmount)
		{
			SLog.Section("Poison resistance — player");
			SLog.Line($"Player {playerID} would've taken {rawAmount:F1} poison damage but took {actualAmount:F1} instead.");
		}

		private static void LogPoisonShieldDamage(int playerID, float rawAmount, float actualAmount, bool depleted)
		{
			SLog.Section("Poison resistance — shield");
			SLog.Line($"Player {playerID}'s shield would've taken {rawAmount:F1} poison damage but took {actualAmount:F1} instead (depleted={depleted}).");
		}
	}
}
namespace ShieldsMod.Networking
{
	public static class ShieldNetworkSync
	{
		public static void BroadcastShieldHealth(int playerID, float current)
		{
			SLog.Line($"BroadcastShieldHealth player={playerID} current={current:F1}");
			NetworkingManager.RPC(typeof(ShieldNetworkSync), "URPC_SetShieldHealth", new object[2] { playerID, current });
		}

		[UnboundRPC]
		public static void URPC_SetShieldHealth(int playerID, float current)
		{
			if (!((Object)(object)ShieldManager.instance == (Object)null))
			{
				ShieldState orCreateShield = ShieldManager.instance.GetOrCreateShield(playerID);
				orCreateShield.Current = Mathf.Clamp(current, 0f, orCreateShield.Max);
				ShieldManager.instance.RefreshVisual(playerID);
				SLog.Line($"URPC_SetShieldHealth player={playerID} current={orCreateShield.Current:F1}");
			}
		}
	}
}
namespace ShieldsMod.Cards
{
	public static class CardArtLoader
	{
		private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>();

		public static string AssetsDirectory => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "assets");

		public static GameObject Load(string fileName)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: 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_01c7: Unknown result type (might be due to invalid IL or missing references)
			SLog.Section("CardArtLoader.Load — '" + fileName + "'");
			SLog.Line("AssetsDirectory = " + AssetsDirectory);
			if (string.IsNullOrEmpty(fileName))
			{
				SLog.Warn("Load called with empty fileName — returning null.");
				return null;
			}
			if (Cache.TryGetValue(fileName, out var value) && (Object)(object)value != (Object)null)
			{
				SLog.Line("Returning cached art object.");
				return value;
			}
			string text = Path.Combine(AssetsDirectory, fileName);
			SLog.Line("Full path = " + text);
			SLog.Line($"File.Exists = {File.Exists(text)}");
			if (!File.Exists(text))
			{
				SLog.Warn("Card art not found at: " + text);
				return null;
			}
			byte[] array = File.ReadAllBytes(text);
			SLog.Line($"Read {array.Length} bytes.");
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			bool flag = ImageConversion.LoadImage(val, array);
			SLog.Line($"Texture.LoadImage = {flag}, size = {((Texture)val).width}x{((Texture)val).height}");
			if (!flag)
			{
				SLog.Warn("Failed to decode card art: " + text);
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Sprite sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			GameObject val2 = new GameObject("ShieldsCardArt_" + fileName);
			Object.DontDestroyOnLoad((Object)(object)val2);
			RectTransform obj = val2.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			((Transform)obj).localPosition = Vector3.up * 10000f;
			Image obj2 = val2.AddComponent<Image>();
			obj2.sprite = sprite;
			obj2.preserveAspect = true;
			((Graphic)obj2).raycastTarget = false;
			Cache[fileName] = val2;
			SLog.Line("Loaded card art '" + fileName + "' from " + text);
			return val2;
		}
	}
	internal static class PoisonCardDeltaRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("PoisonCardDeltaRegistrar — RegisterAll");
			RegisterTier(PoisonCardRegistry.Lv1, 0.25f);
			RegisterTier(PoisonCardRegistry.Lv2, 0.5f);
			RegisterTier(PoisonCardRegistry.Lv3, 0.75f);
		}

		private static void RegisterTier(CardInfo card, float totalReduction)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			if (!((Object)(object)card == (Object)null))
			{
				PoisonHandRebuild.RegisterTier(card.cardName, totalReduction);
				CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ComputeDelta(player, totalReduction)));
				SLog.Line($"Registered poison delta preview for '{card.cardName}' ({totalReduction * 100f:F0}%).");
			}
		}

		private static IReadOnlyList<(string label, string before, string after)> ComputeDelta(Player player, float tierReduction)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)PoisonResistanceManager.instance == (Object)null)
			{
				return Array.Empty<(string, string, string)>();
			}
			float reductionPercent = PoisonResistanceManager.instance.GetReductionPercent(player.playerID);
			float num = tierReduction * 100f;
			return new(string, string, string)[1] { ("Poison Resistance", $"{reductionPercent:F0}%", $"{num:F0}%") };
		}
	}
	internal static class PoisonCardRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("PoisonCardRegistrar — RegisterAll");
			CustomCard.BuildCard<PoisonResistanceLv3>((Action<CardInfo>)delegate(CardInfo ci)
			{
				PoisonCardRegistry.Lv3 = ci;
			});
			CustomCard.BuildCard<PoisonResistanceLv2>((Action<CardInfo>)delegate(CardInfo ci)
			{
				PoisonCardRegistry.Lv2 = ci;
			});
			CustomCard.BuildCard<PoisonResistanceLv1>((Action<CardInfo>)OnLv1Built);
		}

		private static void OnLv1Built(CardInfo ci)
		{
			PoisonCardRegistry.Lv1 = ci;
			SLog.Line("Registered Poison Resistance LV1: " + ci.cardName);
			PoisonCardRegistry.WireLevelChain();
			RegisterPrerequisites();
			PoisonCardDeltaRegistrar.RegisterAll();
		}

		private static void RegisterPrerequisites()
		{
			SLog.Section("PoisonCardRegistrar — RegisterPrerequisites");
			if (!RtgPrerequisiteBridge.IsAvailable)
			{
				SLog.Warn("RoundsTheGathering not available — poison cards will NOT be unlock-gated.");
				return;
			}
			TryRegister(PoisonCardRegistry.Lv2, PoisonCardRegistry.Lv1);
			TryRegister(PoisonCardRegistry.Lv3, PoisonCardRegistry.Lv2);
		}

		private static void TryRegister(CardInfo card, CardInfo required)
		{
			if (!((Object)(object)card == (Object)null) && !((Object)(object)required == (Object)null))
			{
				bool flag = RtgPrerequisiteBridge.Register(card.cardName, required.cardName);
				SLog.Line($"Prereq: \"{card.cardName}\" requires \"{required.cardName}\" — registered={flag}");
			}
		}
	}
	internal static class PoisonCardRegistry
	{
		internal static CardInfo Lv1;

		internal static CardInfo Lv2;

		internal static CardInfo Lv3;

		internal static void WireLevelChain()
		{
			SetNext<PoisonResistanceLv1>(Lv1, Lv2);
			SetNext<PoisonResistanceLv2>(Lv2, Lv3);
			SLog.Line("Poison card level chain wired (LV1 -> LV3).");
		}

		private static void SetNext<T>(CardInfo from, CardInfo to) where T : PoisonResistanceBase
		{
			if (!((Object)(object)from == (Object)null))
			{
				T component = ((Component)from).GetComponent<T>();
				if ((Object)(object)component != (Object)null)
				{
					component.NextLevelCard = to;
				}
			}
		}
	}
	public abstract class PoisonResistanceBase : CustomCard
	{
		public CardInfo NextLevelCard;

		protected abstract int Level { get; }

		protected abstract float TotalReduction { get; }

		protected abstract string ArtFileName { get; }

		protected abstract Rarity CardRarity { get; }

		protected override string GetTitle()
		{
			return "Poison Resistance " + Roman(Level);
		}

		protected override string GetDescription()
		{
			return "Decrease the effects of Poison on both you and your shield by " + PercentLabel(TotalReduction) + ".";
		}

		protected override CardInfoStat[] GetStats()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_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: Expected O, but got Unknown
			return (CardInfoStat[])(object)new CardInfoStat[1]
			{
				new CardInfoStat
				{
					positive = true,
					amount = PercentLabel(TotalReduction),
					stat = "Poison Resist",
					simepleAmount = (SimpleAmount)0
				}
			};
		}

		protected override Rarity GetRarity()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return CardRarity;
		}

		protected override GameObject GetCardArt()
		{
			return CardArtLoader.Load(ArtFileName);
		}

		protected override CardThemeColorType GetTheme()
		{
			return (CardThemeColorType)5;
		}

		public override string GetModName()
		{
			return "ShieldsMod";
		}

		public override void SetupCard(CardInfo cardInfo, Gun gun, ApplyCardStats cardStats, CharacterStatModifiers statModifiers, Block block)
		{
			cardInfo.allowMultiple = false;
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			if (!((Object)(object)player == (Object)null))
			{
				PoisonResistanceManager.instance?.RebuildForPlayer(player.playerID);
				SLog.Section($"PoisonResistance LV{Level} — OnAddCard");
				SLog.Line($"player={player.playerID} totalReduction={TotalReduction * 100f:F0}%");
				if ((Object)(object)NextLevelCard != (Object)null)
				{
					SLog.Line($"Next tier '{NextLevelCard.cardName}' becomes draftable now that LV{Level} is owned.");
				}
			}
		}

		private static string PercentLabel(float reduction)
		{
			return $"{Mathf.RoundToInt(reduction * 100f)}%";
		}

		private static string Roman(int level)
		{
			return level switch
			{
				1 => "I", 
				2 => "II", 
				3 => "III", 
				_ => level.ToString(), 
			};
		}
	}
	public class PoisonResistanceLv1 : PoisonResistanceBase
	{
		protected override int Level => 1;

		protected override float TotalReduction => 0.25f;

		protected override string ArtFileName => "poison_resistance_lv1.png";

		protected override Rarity CardRarity => (Rarity)0;
	}
	public class PoisonResistanceLv2 : PoisonResistanceBase
	{
		protected override int Level => 2;

		protected override float TotalReduction => 0.5f;

		protected override string ArtFileName => "poison_resistance_lv2.png";

		protected override Rarity CardRarity => (Rarity)2;
	}
	public class PoisonResistanceLv3 : PoisonResistanceBase
	{
		protected override int Level => 3;

		protected override float TotalReduction => 0.75f;

		protected override string ArtFileName => "poison_resistance_lv3.png";

		protected override Rarity CardRarity => (Rarity)2;
	}
	internal static class RtgPrerequisiteBridge
	{
		private static MethodInfo _registerMethod;

		private static bool _resolved;

		public static bool IsAvailable
		{
			get
			{
				Resolve();
				return _registerMethod != null;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "RoundsTheGathering");
				if (assembly == null)
				{
					SLog.Warn("RoundsTheGathering assembly not found — shield unlock chain will not be registered.");
					return;
				}
				Type type = assembly.GetType("RoundsTheGathering.CardPrerequisiteRegistry");
				if (type == null)
				{
					SLog.Warn("RoundsTheGathering.CardPrerequisiteRegistry type not found.");
					return;
				}
				_registerMethod = type.GetMethod("RegisterPrerequisite", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(string),
					typeof(string)
				}, null);
				if (_registerMethod == null)
				{
					SLog.Warn("RegisterPrerequisite(string, string) not found on CardPrerequisiteRegistry.");
				}
			}
			catch (Exception ex)
			{
				SLog.Error("Failed to resolve RoundsTheGathering registry: " + ex.Message);
			}
		}

		internal static bool Register(string cardName, string requiredCardName)
		{
			Resolve();
			if (_registerMethod == null)
			{
				return false;
			}
			try
			{
				_registerMethod.Invoke(null, new object[2] { cardName, requiredCardName });
				return true;
			}
			catch (Exception ex)
			{
				SLog.Error("RegisterPrerequisite invoke failed: " + ex.Message);
				return false;
			}
		}
	}
	internal static class ShieldCardDeltaRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("ShieldCardDeltaRegistrar — RegisterAll");
			RegisterTier(ShieldCardRegistry.Lv1, 1.1f);
			RegisterTier(ShieldCardRegistry.Lv2, 1.25f);
			RegisterTier(ShieldCardRegistry.Lv3, 1.5f);
			RegisterTier(ShieldCardRegistry.Lv4, 2f);
			RegisterTier(ShieldCardRegistry.Lv5, 2.65f);
		}

		private static void RegisterTier(CardInfo card, float multiplier)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			if ((Object)(object)card == (Object)null)
			{
				SLog.Warn("ShieldCardDeltaRegistrar — skipped null card reference.");
				return;
			}
			ShieldHandRebuild.RegisterTier(card, multiplier);
			CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ComputeShieldDelta(player, multiplier)));
			SLog.Line($"Registered stat-delta preview for '{card.cardName}' (x{multiplier:F2}).");
		}

		private static IReadOnlyList<(string label, string before, string after)> ComputeShieldDelta(Player player, float multiplier)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)ShieldManager.instance == (Object)null)
			{
				return Array.Empty<(string, string, string)>();
			}
			float max = ShieldManager.instance.GetShield(player.playerID).Max;
			float num = max * multiplier;
			return new(string, string, string)[1] { ("Shield Max", $"{max:F0}", $"{num:F0}") };
		}
	}
	internal static class ShieldCardRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("ShieldCardRegistrar — RegisterAll");
			CustomCard.BuildCard<UpgradeShieldLv5>((Action<CardInfo>)OnLv5Built);
			CustomCard.BuildCard<UpgradeShieldLv4>((Action<CardInfo>)OnLv4Built);
			CustomCard.BuildCard<UpgradeShieldLv3>((Action<CardInfo>)OnLv3Built);
			CustomCard.BuildCard<UpgradeShieldLv2>((Action<CardInfo>)OnLv2Built);
			CustomCard.BuildCard<UpgradeShieldLv1>((Action<CardInfo>)OnLv1Built);
		}

		private static void OnLv5Built(CardInfo ci)
		{
			ShieldCardRegistry.Lv5 = ci;
			SLog.Line("Registered LV5: " + ci.cardName);
		}

		private static void OnLv4Built(CardInfo ci)
		{
			ShieldCardRegistry.Lv4 = ci;
			SLog.Line("Registered LV4: " + ci.cardName);
		}

		private static void OnLv3Built(CardInfo ci)
		{
			ShieldCardRegistry.Lv3 = ci;
			SLog.Line("Registered LV3: " + ci.cardName);
		}

		private static void OnLv2Built(CardInfo ci)
		{
			ShieldCardRegistry.Lv2 = ci;
			SLog.Line("Registered LV2: " + ci.cardName);
		}

		private static void OnLv1Built(CardInfo ci)
		{
			ShieldCardRegistry.Lv1 = ci;
			SLog.Line("Registered LV1: " + ci.cardName);
			ShieldCardRegistry.WireLevelChain();
			RegisterPrerequisites();
			ShieldCardDeltaRegistrar.RegisterAll();
		}

		private static void RegisterPrerequisites()
		{
			SLog.Section("ShieldCardRegistrar — RegisterPrerequisites");
			if (!RtgPrerequisiteBridge.IsAvailable)
			{
				SLog.Warn("RoundsTheGathering not available — shield cards will NOT be unlock-gated.");
				return;
			}
			TryRegister(ShieldCardRegistry.Lv2, ShieldCardRegistry.Lv1);
			TryRegister(ShieldCardRegistry.Lv3, ShieldCardRegistry.Lv2);
			TryRegister(ShieldCardRegistry.Lv4, ShieldCardRegistry.Lv3);
			TryRegister(ShieldCardRegistry.Lv5, ShieldCardRegistry.Lv4);
		}

		private static void TryRegister(CardInfo card, CardInfo required)
		{
			if ((Object)(object)card == (Object)null || (Object)(object)required == (Object)null)
			{
				SLog.Warn("Skipping prerequisite registration — a card reference was null.");
				return;
			}
			bool flag = RtgPrerequisiteBridge.Register(card.cardName, required.cardName);
			SLog.Line($"Prereq: \"{card.cardName}\" requires \"{required.cardName}\" — registered={flag}");
		}
	}
	internal static class ShieldCardRegistry
	{
		internal static CardInfo Lv1;

		internal static CardInfo Lv2;

		internal static CardInfo Lv3;

		internal static CardInfo Lv4;

		internal static CardInfo Lv5;

		internal static void WireLevelChain()
		{
			SetNext<UpgradeShieldLv1>(Lv1, Lv2);
			SetNext<UpgradeShieldLv2>(Lv2, Lv3);
			SetNext<UpgradeShieldLv3>(Lv3, Lv4);
			SetNext<UpgradeShieldLv4>(Lv4, Lv5);
			SLog.Line("Shield card level chain wired (LV1 -> LV5).");
		}

		private static void SetNext<T>(CardInfo from, CardInfo to) where T : UpgradeShieldHealthBase
		{
			if (!((Object)(object)from == (Object)null))
			{
				T component = ((Component)from).GetComponent<T>();
				if ((Object)(object)component != (Object)null)
				{
					component.NextLevelCard = to;
				}
			}
		}
	}
	public abstract class UpgradeShieldHealthBase : CustomCard
	{
		public CardInfo NextLevelCard;

		protected abstract int Level { get; }

		protected abstract float Multiplier { get; }

		protected abstract string ArtFileName { get; }

		protected abstract Rarity CardRarity { get; }

		protected override string GetTitle()
		{
			return "Upgrade Shield Health " + Roman(Level);
		}

		protected override string GetDescription()
		{
			return "Increases max shield health by " + PercentLabel(Multiplier) + ". Multiplies with other shield upgrades.";
		}

		protected override CardInfoStat[] GetStats()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_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: Expected O, but got Unknown
			return (CardInfoStat[])(object)new CardInfoStat[1]
			{
				new CardInfoStat
				{
					positive = true,
					amount = PercentLabel(Multiplier),
					stat = "Shield Max",
					simepleAmount = (SimpleAmount)0
				}
			};
		}

		protected override Rarity GetRarity()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return CardRarity;
		}

		protected override GameObject GetCardArt()
		{
			return CardArtLoader.Load(ArtFileName);
		}

		protected override CardThemeColorType GetTheme()
		{
			return (CardThemeColorType)2;
		}

		public override string GetModName()
		{
			return "ShieldsMod";
		}

		public override void SetupCard(CardInfo cardInfo, Gun gun, ApplyCardStats cardStats, CharacterStatModifiers statModifiers, Block block)
		{
			cardInfo.allowMultiple = false;
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)ShieldManager.instance == (Object)null))
			{
				int playerID = player.playerID;
				ShieldState orCreateShield = ShieldManager.instance.GetOrCreateShield(playerID);
				float max = orCreateShield.Max;
				orCreateShield.Max *= Multiplier;
				orCreateShield.Current = Mathf.Min(orCreateShield.Current, orCreateShield.Max);
				ShieldManager.instance.RefreshVisual(playerID);
				SLog.Section($"UpgradeShieldHealth LV{Level} — OnAddCard");
				SLog.Line($"player={playerID} multiplier={Multiplier:F2} max {max:F1} -> {orCreateShield.Max:F1}");
				if ((Object)(object)NextLevelCard != (Object)null)
				{
					SLog.Line($"Next tier '{NextLevelCard.cardName}' becomes draftable now that LV{Level} is owned.");
				}
				else
				{
					SLog.Line("This is the final tier (no next level).");
				}
			}
		}

		private static string PercentLabel(float multiplier)
		{
			return $"+{Mathf.RoundToInt((multiplier - 1f) * 100f)}%";
		}

		private static string Roman(int level)
		{
			return level switch
			{
				1 => "I", 
				2 => "II", 
				3 => "III", 
				4 => "IV", 
				5 => "V", 
				_ => level.ToString(), 
			};
		}
	}
	public class UpgradeShieldLv1 : UpgradeShieldHealthBase
	{
		protected override int Level => 1;

		protected override float Multiplier => 1.1f;

		protected override string ArtFileName => "lv1_artwork.png";

		protected override Rarity CardRarity => (Rarity)0;
	}
	public class UpgradeShieldLv2 : UpgradeShieldHealthBase
	{
		protected override int Level => 2;

		protected override float Multiplier => 1.25f;

		protected override string ArtFileName => "lv2_artwork.png";

		protected override Rarity CardRarity => (Rarity)0;
	}
	public class UpgradeShieldLv3 : UpgradeShieldHealthBase
	{
		protected override int Level => 3;

		protected override float Multiplier => 1.5f;

		protected override string ArtFileName => "lv3_artwork.png";

		protected override Rarity CardRarity => (Rarity)1;
	}
	public class UpgradeShieldLv4 : UpgradeShieldHealthBase
	{
		protected override int Level => 4;

		protected override float Multiplier => 2f;

		protected override string ArtFileName => "lv4_artwork.png";

		protected override Rarity CardRarity => (Rarity)1;
	}
	public class UpgradeShieldLv5 : UpgradeShieldHealthBase
	{
		protected override int Level => 5;

		protected override float Multiplier => 2.65f;

		protected override string ArtFileName => "lv5_artwork.png";

		protected override Rarity CardRarity => (Rarity)2;
	}
}