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 RarityLib.Utils; using ShieldsMod.Cards; using ShieldsMod.Lifesteal; using ShieldsMod.Networking; using ShieldsMod.Poison; using ShieldsMod.Resistance; using ShieldsMod.Shield; using ShieldsMod.Stun; 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+146ac727a7fc6b83f382d57f53cce40478349c58")] [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.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("ShieldsMod", "Shields Mod for ROUNDS", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; internal static string PluginDirectory { get; private set; } private void Awake() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? ""; SLog.Section("Plugin Awake"); SLog.Line("PluginDirectory = " + PluginDirectory); new Harmony("ShieldsMod").PatchAll(); ((Component)this).gameObject.AddComponent(); ((Component)this).gameObject.AddComponent(); ((Component)this).gameObject.AddComponent(); ((Component)this).gameObject.AddComponent(); SLog.Line("Plugin ShieldsMod loaded."); } private void Start() { ShieldCardRegistrar.RegisterAll(); PoisonCardRegistrar.RegisterAll(); StunCardRegistrar.RegisterAll(); LifestealCardRegistrar.RegisterAll(); } } 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.Stun { internal static class StunHandRebuild { private static Dictionary _levelByCardName; internal static void RegisterTier(string cardName, int level) { if (!string.IsNullOrEmpty(cardName) && level >= 1 && level <= 3) { if (_levelByCardName == null) { _levelByCardName = new Dictionary(StringComparer.Ordinal); } _levelByCardName[cardName] = level; } } internal static float ComputeReductionFromHand(IEnumerable cards, CardInfo exclude = null) { return ResistanceTierLogic.ComputeFromHand(cards, _levelByCardName, exclude); } internal static void RebuildForPlayer(int playerID) { StunResistanceManager.instance?.RebuildForPlayer(playerID); } } public class StunResistanceManager : MonoBehaviour { [CompilerGenerated] private sealed class d__3 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 StunResistanceManager instance; private readonly Dictionary _reductionByPlayer = new Dictionary(); private void Awake() { instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); GameModeManager.AddHook("BattleStart", (Func)OnBattleStart); SLog.Section("StunResistanceManager — Awake"); } [IteratorStateMachine(typeof(d__3))] private static IEnumerator OnBattleStart(IGameModeHandler gm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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 = StunHandRebuild.ComputeReductionFromHand(val.data.currentCards); _reductionByPlayer[playerID] = num; SLog.Line($"StunResistance rebuild player={playerID} reduction={num * 100f:F0}%"); } } } public float ApplyResistance(int playerID, float rawDuration, out float resistedAmount) { float reduction = GetReduction(playerID); resistedAmount = rawDuration * reduction; return rawDuration - resistedAmount; } } } namespace ShieldsMod.Shield { internal static class ShieldHandRebuild { private readonly struct ShieldTier { public readonly float FirstShieldMax; public readonly float StackMultiplier; public ShieldTier(float firstShieldMax, float stackMultiplier) { FirstShieldMax = firstShieldMax; StackMultiplier = stackMultiplier; } } private static Dictionary _tierByCardName; internal static void RegisterTier(CardInfo card, float firstShieldMax, float stackMultiplier) { if (!((Object)(object)card == (Object)null) && !string.IsNullOrEmpty(card.cardName)) { if (_tierByCardName == null) { _tierByCardName = new Dictionary(StringComparer.Ordinal); } _tierByCardName[card.cardName] = new ShieldTier(firstShieldMax, stackMultiplier); } } internal static float ComputeMaxFromHandExcluding(IEnumerable cards, CardInfo exclude) { return ComputeMaxFromCards(cards, exclude); } 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) { ShieldState orCreateShield = ShieldManager.instance.GetOrCreateShield(playerID); float max = orCreateShield.Max; float num = ComputeMaxFromCards(val.data.currentCards); if (num <= 0f) { orCreateShield.Max = 0f; orCreateShield.Current = 0f; } else { orCreateShield.Max = num; orCreateShield.Current = Mathf.Min(orCreateShield.Current, orCreateShield.Max); } ShieldManager.instance.RefreshVisual(playerID); SLog.Line($"ShieldHandRebuild player={playerID} max {max:F0} -> {orCreateShield.Max:F0} current={orCreateShield.Current:F0}"); } } private static float ComputeMaxFromCards(IEnumerable cards, CardInfo exclude = null) { if (_tierByCardName == null || cards == null) { return 0f; } float num = 0f; bool flag = false; foreach (CardInfo card in cards) { if ((Object)(object)card == (Object)null || ((Object)(object)exclude != (Object)null && ((Object)card).name == ((Object)exclude).name)) { continue; } string cardName = card.cardName; if (string.IsNullOrEmpty(cardName) && (Object)(object)card.sourceCard != (Object)null) { cardName = card.sourceCard.cardName; } if (!string.IsNullOrEmpty(cardName) && _tierByCardName.TryGetValue(cardName, out var value)) { if (!flag) { num = value.FirstShieldMax; flag = true; } else { num *= value.StackMultiplier; } } } if (!flag) { return 0f; } return num; } } public class ShieldManager : MonoBehaviour { [CompilerGenerated] private sealed class d__6 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(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 d__8 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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?.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 d__7 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(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 _shields = new Dictionary(); private readonly Dictionary _visuals = new Dictionary(); private readonly Dictionary _parryTriggers = new Dictionary(); private void Awake() { instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); SLog.Section("ShieldManager — Awake"); GameModeManager.AddHook("BattleStart", (Func)OnBattleStart); GameModeManager.AddHook("PointEnd", (Func)OnPointEnd); GameModeManager.AddHook("GameStart", (Func)OnGameStart); } private void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } } [IteratorStateMachine(typeof(d__6))] private static IEnumerator OnBattleStart(IGameModeHandler gm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0); } [IteratorStateMachine(typeof(d__7))] private static IEnumerator OnPointEnd(IGameModeHandler gm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0); } [IteratorStateMachine(typeof(d__8))] private static IEnumerator OnGameStart(IGameModeHandler gm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0); } public void ResetAllForBattle() { 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)) { ShieldHandRebuild.RebuildForPlayer(player.playerID); ShieldState orCreateShield = GetOrCreateShield(player.playerID); if (orCreateShield.HasShield) { orCreateShield.ResetToFull(); } else { orCreateShield.Current = 0f; } 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 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(); 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(); 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 list = new List(); foreach (KeyValuePair visual in _visuals) { if ((Object)(object)visual.Value == (Object)null) { list.Add(visual.Key); } } foreach (int item in list) { _visuals.Remove(item); } List list2 = new List(); foreach (KeyValuePair 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 _recentlyDeflected = new HashSet(); public void Init(Player owner, ShieldState state, float radius) { _owner = owner; _state = state; _block = ((Component)owner).GetComponent(); _trigger = ((Component)this).gameObject.AddComponent(); ((Collider2D)_trigger).isTrigger = true; _trigger.radius = radius; Rigidbody2D obj = ((Component)this).gameObject.AddComponent(); 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() ?? ((Component)other).GetComponentInParent(); if ((Object)(object)val == (Object)null) { return; } PhotonView component = ((Component)val).GetComponent(); 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(); 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() ?? ((Component)other).GetComponentInParent(); if ((Object)(object)val != (Object)null) { _recentlyDeflected.Remove(((Object)((Component)val).gameObject).GetInstanceID()); } } } public class ShieldState { public const float DefaultMax = 100f; public float Max; public float Current; public const float BubbleAlpha = 0.05f; public bool HasShield => Max > 0f; 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(); _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(); if ((Object)(object)val == (Object)null) { val = ((Component)player).GetComponentInChildren(); } 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.Resistance { internal static class ResistanceTierLogic { public const float StackBonus = 0.05f; public const float Lv2UpgradeThreshold = 0.5f; public const float Lv3UpgradeThreshold = 0.75f; private static readonly float[] FirstReductionByLevel = new float[4] { 0f, 0.25f, 0.5f, 0.75f }; internal static float GetFirstReduction(int level) { if (level < 1 || level > 3) { return 0f; } return FirstReductionByLevel[level]; } internal static float ComputeFromHand(IEnumerable cards, IReadOnlyDictionary tierByCardName, CardInfo exclude = null) { if (tierByCardName == null || cards == null) { return 0f; } float num = 0f; bool flag = false; foreach (CardInfo card in cards) { if (!((Object)(object)card == (Object)null) && (!((Object)(object)exclude != (Object)null) || !(((Object)card).name == ((Object)exclude).name)) && TryGetLevel(card, tierByCardName, out var level)) { if (!flag) { num = GetFirstReduction(level); flag = true; } else { num = ApplyStacking(num, level, out var _); } } } if (!flag) { return 0f; } return ClampReduction(num); } internal static float ApplyCard(float currentReduction, int level, out float? healthMultiplier) { healthMultiplier = null; if (!(currentReduction > 0.0001f)) { return ClampReduction(GetFirstReduction(level)); } return ClampReduction(ApplyStacking(currentReduction, level, out healthMultiplier)); } internal static void ApplyHealthBonus(CharacterData data, float multiplier) { if (!((Object)(object)data == (Object)null) && !(multiplier <= 1.0001f)) { float num = ((data.maxHealth > 0f) ? (data.health / data.maxHealth) : 1f); data.maxHealth *= multiplier; data.health = Mathf.Clamp(data.maxHealth * num, 1f, data.maxHealth); } } private static float ApplyStacking(float current, int level, out float? healthMultiplier) { healthMultiplier = null; switch (level) { case 1: return current + 0.05f; case 2: if (current < 0.5f) { return 0.5f; } healthMultiplier = 1.1f; return current + 0.05f; case 3: if (current < 0.75f) { return 0.75f; } healthMultiplier = 1.25f; return current + 0.05f; default: return current; } } private static bool TryGetLevel(CardInfo card, IReadOnlyDictionary tierByCardName, out int level) { level = 0; if ((Object)(object)card == (Object)null) { return false; } string cardName = card.cardName; if (string.IsNullOrEmpty(cardName) && (Object)(object)card.sourceCard != (Object)null) { cardName = card.sourceCard.cardName; } if (!string.IsNullOrEmpty(cardName)) { return tierByCardName.TryGetValue(cardName, out level); } return false; } private static float ClampReduction(float value) { return Mathf.Clamp01(value); } } } 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() != (Object)null) { return true; } Transform root = damagingWeapon.transform.root; if ((Object)(object)root != (Object)null && (Object)(object)((Component)root).GetComponentInChildren() != (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 _levelByCardName; internal static void RegisterTier(string cardName, int level) { if (!string.IsNullOrEmpty(cardName) && level >= 1 && level <= 3) { if (_levelByCardName == null) { _levelByCardName = new Dictionary(StringComparer.Ordinal); } _levelByCardName[cardName] = level; } } internal static float ComputeReductionFromHand(IEnumerable cards, CardInfo exclude = null) { return ResistanceTierLogic.ComputeFromHand(cards, _levelByCardName, exclude); } internal static void RebuildForPlayer(int playerID) { PoisonResistanceManager.instance?.RebuildForPlayer(playerID); } } public class PoisonResistanceManager : MonoBehaviour { [CompilerGenerated] private sealed class d__3 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 _reductionByPlayer = new Dictionary(); private void Awake() { instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); GameModeManager.AddHook("BattleStart", (Func)OnBattleStart); SLog.Section("PoisonResistanceManager — Awake"); } [IteratorStateMachine(typeof(d__3))] private static IEnumerator OnBattleStart(IGameModeHandler gm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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("DeckBuilder.CardDelete.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 — CardDeleteManager not found; delete hook skipped."); } return num; } private static void Postfix(int playerID) { ShieldHandRebuild.RebuildForPlayer(playerID); PoisonHandRebuild.RebuildForPlayer(playerID); StunHandRebuild.RebuildForPlayer(playerID); LifestealHandRebuild.RebuildForPlayer(playerID); } } [HarmonyPatch(typeof(CharacterStatModifiers), "DealtDamage")] internal static class CharacterStatModifiersDealtDamagePatch { [HarmonyPostfix] private static void Postfix(CharacterStatModifiers __instance, Vector2 damage, bool selfDamage, Player damagedPlayer) { if (selfDamage || (Object)(object)damagedPlayer == (Object)null || __instance.lifeSteal == 0f || (Object)(object)LifestealResistanceManager.instance == (Object)null || LifestealResistanceManager.instance.GetReduction(damagedPlayer.playerID) <= 0f) { return; } float num = ((Vector2)(ref damage)).magnitude * __instance.lifeSteal; float resistedAmount; float num2 = LifestealResistanceManager.instance.ApplyResistance(damagedPlayer.playerID, num, out resistedAmount); if (!(resistedAmount <= 0f)) { Player component = ((Component)__instance).GetComponent(); if (!((Object)(object)component?.data == (Object)null)) { CharacterData data = component.data; data.health -= resistedAmount; component.data.health = Mathf.Clamp(component.data.health, 1f, component.data.maxHealth); SLog.Section("Lifesteal resistance"); SLog.Line($"Player {component?.playerID ?? (-1)} would've healed {num:F1} from life steal but healed {num2:F1} instead (victim {damagedPlayer.playerID} resisted {resistedAmount:F1})."); } } } } [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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (damage == Vector2.zero) { return true; } Player component = ((Component)__instance).GetComponent(); 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 && magnitude > num) { LogPoisonPlayerDamage(component.playerID, magnitude, num); } return true; } 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})."); } } [HarmonyPatch(typeof(StunHandler), "AddStun")] internal static class StunHandlerAddStunPatch { [HarmonyPrefix] private static bool Prefix(StunHandler __instance, ref float f) { if (f <= 0f || (Object)(object)StunResistanceManager.instance == (Object)null) { return true; } Player component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } if (StunResistanceManager.instance.GetReduction(component.playerID) <= 0f) { return true; } float num = f; f = StunResistanceManager.instance.ApplyResistance(component.playerID, num, out var _); if (num > f) { SLog.Section("Stun resistance"); SLog.Line($"Player {component.playerID} would've been stunned for {num:F2}s but duration was reduced to {f:F2}s."); } if (f <= 0f) { return false; } return true; } } } 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.Lifesteal { internal static class LifestealHandRebuild { private static Dictionary _levelByCardName; internal static void RegisterTier(string cardName, int level) { if (!string.IsNullOrEmpty(cardName) && level >= 1 && level <= 3) { if (_levelByCardName == null) { _levelByCardName = new Dictionary(StringComparer.Ordinal); } _levelByCardName[cardName] = level; } } internal static float ComputeReductionFromHand(IEnumerable cards, CardInfo exclude = null) { return ResistanceTierLogic.ComputeFromHand(cards, _levelByCardName, exclude); } internal static void RebuildForPlayer(int playerID) { LifestealResistanceManager.instance?.RebuildForPlayer(playerID); } } public class LifestealResistanceManager : MonoBehaviour { [CompilerGenerated] private sealed class d__3 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 LifestealResistanceManager instance; private readonly Dictionary _reductionByPlayer = new Dictionary(); private void Awake() { instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); GameModeManager.AddHook("BattleStart", (Func)OnBattleStart); SLog.Section("LifestealResistanceManager — Awake"); } [IteratorStateMachine(typeof(d__3))] private static IEnumerator OnBattleStart(IGameModeHandler gm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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 = LifestealHandRebuild.ComputeReductionFromHand(val.data.currentCards); _reductionByPlayer[playerID] = num; SLog.Line($"LifestealResistance rebuild player={playerID} reduction={num * 100f:F0}%"); } } } public float ApplyResistance(int playerID, float rawHeal, out float resistedAmount) { float reduction = GetReduction(playerID); resistedAmount = rawHeal * reduction; return rawHeal - resistedAmount; } } } namespace ShieldsMod.Cards { public static class CardArtLoader { private static readonly Dictionary Cache = new Dictionary(); public static string AssetsDirectory => Path.Combine(Plugin.PluginDirectory, "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(); 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(); 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 LifestealCardDeltaRegistrar { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func <>9__1_2; public static Func <>9__1_3; public static Func, float> <>9__1_4; public static SimpleDeltaProvider <>9__1_1; internal float b__1_2(int id) { return LifestealResistanceManager.instance.GetReductionPercent(id); } internal IReadOnlyList<(string label, string before, string after)> b__1_1(Player player, CardInfo cardInfo) { return ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Lifesteal Resistance", (int id) => LifestealResistanceManager.instance.GetReductionPercent(id), (IEnumerable cards) => LifestealHandRebuild.ComputeReductionFromHand(cards)); } internal float b__1_3(int id) { return LifestealResistanceManager.instance.GetReductionPercent(id); } internal float b__1_4(IEnumerable cards) { return LifestealHandRebuild.ComputeReductionFromHand(cards); } } internal static void RegisterAll() { SLog.Section("LifestealCardDeltaRegistrar — RegisterAll"); RegisterTier(LifestealCardRegistry.Lv1, 1); RegisterTier(LifestealCardRegistry.Lv2, 2); RegisterTier(LifestealCardRegistry.Lv3, 3); } private static void RegisterTier(CardInfo card, int level) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //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 if ((Object)(object)card == (Object)null) { return; } LifestealHandRebuild.RegisterTier(card.cardName, level); CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ResistanceDeltaHelper.ComputeAddDelta(player, level, "Lifesteal Resistance", (int id) => LifestealResistanceManager.instance.GetReductionPercent(id)))); string cardName = card.cardName; object obj = <>c.<>9__1_1; if (obj == null) { SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Lifesteal Resistance", (int id) => LifestealResistanceManager.instance.GetReductionPercent(id), (IEnumerable cards) => LifestealHandRebuild.ComputeReductionFromHand(cards)); <>c.<>9__1_1 = val; obj = (object)val; } CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj); SLog.Line($"Registered lifesteal delta preview for '{card.cardName}' (LV{level})."); } } internal static class LifestealCardRegistrar { internal static void RegisterAll() { SLog.Section("LifestealCardRegistrar — RegisterAll"); CustomCard.BuildCard((Action)delegate(CardInfo ci) { LifestealCardRegistry.Lv3 = ci; }); CustomCard.BuildCard((Action)delegate(CardInfo ci) { LifestealCardRegistry.Lv2 = ci; }); CustomCard.BuildCard((Action)OnLv1Built); } private static void OnLv1Built(CardInfo ci) { LifestealCardRegistry.Lv1 = ci; SLog.Line("Registered Lifesteal Resistance LV1: " + ci.cardName); LifestealCardDeltaRegistrar.RegisterAll(); } } internal static class LifestealCardRegistry { internal static CardInfo Lv1; internal static CardInfo Lv2; internal static CardInfo Lv3; } public abstract class LifestealResistanceBase : CustomCard { protected abstract int Level { get; } protected abstract string ArtFileName { get; } protected abstract Rarity CardRarity { get; } protected override string GetTitle() { return "Lifesteal Resistance " + Roman(Level); } protected override string GetDescription() { return ResistanceCardText.Description(Level, "lifesteal"); } 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 = ResistanceCardText.StatAmount(Level), stat = "Life Steal 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)4; } 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)) { string cardName = (((Object)(object)base.cardInfo != (Object)null) ? base.cardInfo.cardName : null); ResistanceCardOnAdd.Apply(player, data, Level, cardName, (IEnumerable cards) => LifestealHandRebuild.ComputeReductionFromHand(cards), delegate(int id) { LifestealResistanceManager.instance?.RebuildForPlayer(id); }); SLog.Section($"LifestealResistance LV{Level} — OnAddCard"); SLog.Line($"player={player.playerID} reduction={LifestealResistanceManager.instance?.GetReductionPercent(player.playerID):F0}%"); } } private static string Roman(int level) { return level switch { 1 => "I", 2 => "II", 3 => "III", _ => level.ToString(), }; } } public class LifestealResistanceLv1 : LifestealResistanceBase { protected override int Level => 1; protected override string ArtFileName => "lifesteal_resistance_lv1.png"; protected override Rarity CardRarity => (Rarity)1; } public class LifestealResistanceLv2 : LifestealResistanceBase { protected override int Level => 2; protected override string ArtFileName => "lifesteal_resistance_lv2.png"; protected override Rarity CardRarity => (Rarity)2; } public class LifestealResistanceLv3 : LifestealResistanceBase { protected override int Level => 3; protected override string ArtFileName => "lifesteal_resistance_lv3.png"; protected override Rarity CardRarity => RarityHelper.Epic; } internal static class PoisonCardDeltaRegistrar { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func <>9__1_2; public static Func <>9__1_3; public static Func, float> <>9__1_4; public static SimpleDeltaProvider <>9__1_1; internal float b__1_2(int id) { return PoisonResistanceManager.instance.GetReductionPercent(id); } internal IReadOnlyList<(string label, string before, string after)> b__1_1(Player player, CardInfo cardInfo) { return ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Poison Resistance", (int id) => PoisonResistanceManager.instance.GetReductionPercent(id), (IEnumerable cards) => PoisonHandRebuild.ComputeReductionFromHand(cards)); } internal float b__1_3(int id) { return PoisonResistanceManager.instance.GetReductionPercent(id); } internal float b__1_4(IEnumerable cards) { return PoisonHandRebuild.ComputeReductionFromHand(cards); } } internal static void RegisterAll() { SLog.Section("PoisonCardDeltaRegistrar — RegisterAll"); RegisterTier(PoisonCardRegistry.Lv1, 1); RegisterTier(PoisonCardRegistry.Lv2, 2); RegisterTier(PoisonCardRegistry.Lv3, 3); } private static void RegisterTier(CardInfo card, int level) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //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 if ((Object)(object)card == (Object)null) { return; } PoisonHandRebuild.RegisterTier(card.cardName, level); CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ResistanceDeltaHelper.ComputeAddDelta(player, level, "Poison Resistance", (int id) => PoisonResistanceManager.instance.GetReductionPercent(id)))); string cardName = card.cardName; object obj = <>c.<>9__1_1; if (obj == null) { SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Poison Resistance", (int id) => PoisonResistanceManager.instance.GetReductionPercent(id), (IEnumerable cards) => PoisonHandRebuild.ComputeReductionFromHand(cards)); <>c.<>9__1_1 = val; obj = (object)val; } CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj); SLog.Line($"Registered poison delta preview for '{card.cardName}' (LV{level})."); } } internal static class PoisonCardRegistrar { internal static void RegisterAll() { SLog.Section("PoisonCardRegistrar — RegisterAll"); CustomCard.BuildCard((Action)delegate(CardInfo ci) { PoisonCardRegistry.Lv3 = ci; }); CustomCard.BuildCard((Action)delegate(CardInfo ci) { PoisonCardRegistry.Lv2 = ci; }); CustomCard.BuildCard((Action)OnLv1Built); } private static void OnLv1Built(CardInfo ci) { PoisonCardRegistry.Lv1 = ci; SLog.Line("Registered Poison Resistance LV1: " + ci.cardName); PoisonCardDeltaRegistrar.RegisterAll(); } } internal static class PoisonCardRegistry { internal static CardInfo Lv1; internal static CardInfo Lv2; internal static CardInfo Lv3; } public abstract class PoisonResistanceBase : CustomCard { protected abstract int Level { 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 ResistanceCardText.Description(Level, "poison"); } 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 = ResistanceCardText.StatAmount(Level), 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)) { string cardName = (((Object)(object)base.cardInfo != (Object)null) ? base.cardInfo.cardName : null); ResistanceCardOnAdd.Apply(player, data, Level, cardName, (IEnumerable cards) => PoisonHandRebuild.ComputeReductionFromHand(cards), delegate(int id) { PoisonResistanceManager.instance?.RebuildForPlayer(id); }); SLog.Section($"PoisonResistance LV{Level} — OnAddCard"); SLog.Line($"player={player.playerID} reduction={PoisonResistanceManager.instance?.GetReductionPercent(player.playerID):F0}%"); } } 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 string ArtFileName => "poison_resistance_lv1.png"; protected override Rarity CardRarity => (Rarity)1; } public class PoisonResistanceLv2 : PoisonResistanceBase { protected override int Level => 2; 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 string ArtFileName => "poison_resistance_lv3.png"; protected override Rarity CardRarity => RarityHelper.Epic; } internal static class RarityHelper { public static Rarity Scarce => RarityUtils.GetRarity("Scarce"); public static Rarity Epic => RarityUtils.GetRarity("Epic"); public static Rarity Legendary => RarityUtils.GetRarity("Legendary"); } internal static class ResistanceCardOnAdd { internal static void Apply(Player player, CharacterData data, int level, string cardName, Func, float> computeFromHand, Action rebuild) { if (!((Object)(object)player == (Object)null) && computeFromHand != null) { IEnumerable arg = player.data?.currentCards?.Where((CardInfo c) => (Object)(object)c != (Object)null && c.cardName != cardName) ?? Enumerable.Empty(); ResistanceTierLogic.ApplyCard(computeFromHand(arg), level, out var healthMultiplier); if (healthMultiplier.HasValue) { ResistanceTierLogic.ApplyHealthBonus(data, healthMultiplier.Value); } rebuild?.Invoke(player.playerID); } } } internal static class ResistanceCardText { internal static string Description(int level, string effectLabel) { return level switch { 1 => "Sets " + effectLabel + " resistance to 25%, or +5% if you already have resistance.", 2 => "Sets " + effectLabel + " resistance to 50% if below 50%; otherwise +5% resistance and +10% max HP.", 3 => "Sets " + effectLabel + " resistance to 75% if below 75%; otherwise +5% resistance and +25% max HP.", _ => "Improves " + effectLabel + " resistance.", }; } internal static string StatAmount(int level) { return level switch { 1 => "25% / +5%", 2 => "50% / +5%", 3 => "75% / +5%", _ => "—", }; } } internal static class ResistanceDeltaHelper { internal static IReadOnlyList<(string label, string before, string after)> ComputeAddDelta(Player player, int level, string statLabel, Func getReductionPercent) { if ((Object)(object)player == (Object)null || getReductionPercent == null) { return Array.Empty<(string, string, string)>(); } float num = getReductionPercent(player.playerID); float? healthMultiplier; float num2 = ResistanceTierLogic.ApplyCard(num / 100f, level, out healthMultiplier) * 100f; List<(string, string, string)> list = new List<(string, string, string)> { (statLabel, $"{num:F0}%", $"{num2:F0}%") }; if (healthMultiplier.HasValue && (Object)(object)player.data != (Object)null) { float maxHealth = player.data.maxHealth; float num3 = maxHealth * healthMultiplier.Value; list.Add(("HP", $"{maxHealth:F0}", $"{num3:F0}")); } return list; } internal static IReadOnlyList<(string label, string before, string after)> ComputeRemovalDelta(Player player, CardInfo cardToRemove, string statLabel, Func getReductionPercent, Func, float> computeFromHand) { if ((Object)(object)player == (Object)null || (Object)(object)cardToRemove == (Object)null || getReductionPercent == null || computeFromHand == null) { return Array.Empty<(string, string, string)>(); } float num = getReductionPercent(player.playerID); IEnumerable arg = player.data?.currentCards?.Where((CardInfo c) => (Object)(object)c != (Object)null && ((Object)c).name != ((Object)cardToRemove).name) ?? Enumerable.Empty(); float num2 = computeFromHand(arg) * 100f; if (Mathf.Approximately(num, num2)) { return Array.Empty<(string, string, string)>(); } return new(string, string, string)[1] { (statLabel, $"{num:F0}%", $"{num2:F0}%") }; } } 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 == "DeckBuilder"); if (assembly == null) { SLog.Warn("DeckBuilder assembly not found — shield unlock chain will not be registered."); return; } Type type = assembly.GetType("DeckBuilder.CardPrerequisiteRegistry"); if (type == null) { SLog.Warn("DeckBuilder 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 DeckBuilder 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 { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static SimpleDeltaProvider <>9__1_1; internal IReadOnlyList<(string label, string before, string after)> b__1_1(Player player, CardInfo cardInfo) { return ComputeShieldRemoval(player, cardInfo); } } internal static void RegisterAll() { SLog.Section("ShieldCardDeltaRegistrar — RegisterAll"); RegisterTier(ShieldCardRegistry.Lv1, 100f, 1.2f); RegisterTier(ShieldCardRegistry.Lv2, 150f, 1.5f); RegisterTier(ShieldCardRegistry.Lv3, 250f, 2f); RegisterTier(ShieldCardRegistry.Lv4, 500f, 3f); RegisterTier(ShieldCardRegistry.Lv5, 1000f, 3.5f); } private static void RegisterTier(CardInfo card, float firstShieldMax, float stackMultiplier) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown if ((Object)(object)card == (Object)null) { SLog.Warn("ShieldCardDeltaRegistrar — skipped null card reference."); return; } ShieldHandRebuild.RegisterTier(card, firstShieldMax, stackMultiplier); CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ComputeShieldDelta(player, firstShieldMax, stackMultiplier))); string cardName = card.cardName; object obj = <>c.<>9__1_1; if (obj == null) { SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ComputeShieldRemoval(player, cardInfo); <>c.<>9__1_1 = val; obj = (object)val; } CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj); SLog.Line($"Registered stat-delta preview for '{card.cardName}' (first={firstShieldMax:F0}, x{stackMultiplier:F2})."); } private static IReadOnlyList<(string label, string before, string after)> ComputeShieldDelta(Player player, float firstShieldMax, float stackMultiplier) { if ((Object)(object)player == (Object)null || (Object)(object)ShieldManager.instance == (Object)null) { return Array.Empty<(string, string, string)>(); } ShieldState shield = ShieldManager.instance.GetShield(player.playerID); float max = shield.Max; float num = (shield.HasShield ? (max * stackMultiplier) : firstShieldMax); return new(string, string, string)[1] { ("Shield Max", $"{max:F0}", $"{num:F0}") }; } private static IReadOnlyList<(string label, string before, string after)> ComputeShieldRemoval(Player player, CardInfo cardToRemove) { if ((Object)(object)player == (Object)null || (Object)(object)ShieldManager.instance == (Object)null || (Object)(object)cardToRemove == (Object)null) { return Array.Empty<(string, string, string)>(); } float max = ShieldManager.instance.GetShield(player.playerID).Max; float num = ShieldHandRebuild.ComputeMaxFromHandExcluding(player.data?.currentCards, cardToRemove); if (Mathf.Approximately(max, num)) { return Array.Empty<(string, string, string)>(); } string item = ((num > 0f) ? $"{num:F0}" : "None"); return new(string, string, string)[1] { ("Shield Health", $"{max:F0}", item) }; } } internal static class ShieldCardRegistrar { internal static void RegisterAll() { SLog.Section("ShieldCardRegistrar — RegisterAll"); CustomCard.BuildCard((Action)delegate(CardInfo ci) { ShieldCardRegistry.Lv5 = ci; }); CustomCard.BuildCard((Action)delegate(CardInfo ci) { ShieldCardRegistry.Lv4 = ci; }); CustomCard.BuildCard((Action)delegate(CardInfo ci) { ShieldCardRegistry.Lv3 = ci; }); CustomCard.BuildCard((Action)delegate(CardInfo ci) { ShieldCardRegistry.Lv2 = ci; }); CustomCard.BuildCard((Action)OnLv1Built); } private static void OnLv1Built(CardInfo ci) { ShieldCardRegistry.Lv1 = ci; SLog.Line("Registered LV1: " + ci.cardName); ShieldCardDeltaRegistrar.RegisterAll(); } } 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 class StunCardDeltaRegistrar { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func <>9__1_2; public static Func <>9__1_3; public static Func, float> <>9__1_4; public static SimpleDeltaProvider <>9__1_1; internal float b__1_2(int id) { return StunResistanceManager.instance.GetReductionPercent(id); } internal IReadOnlyList<(string label, string before, string after)> b__1_1(Player player, CardInfo cardInfo) { return ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Stun Resistance", (int id) => StunResistanceManager.instance.GetReductionPercent(id), (IEnumerable cards) => StunHandRebuild.ComputeReductionFromHand(cards)); } internal float b__1_3(int id) { return StunResistanceManager.instance.GetReductionPercent(id); } internal float b__1_4(IEnumerable cards) { return StunHandRebuild.ComputeReductionFromHand(cards); } } internal static void RegisterAll() { SLog.Section("StunCardDeltaRegistrar — RegisterAll"); RegisterTier(StunCardRegistry.Lv1, 1); RegisterTier(StunCardRegistry.Lv2, 2); RegisterTier(StunCardRegistry.Lv3, 3); } private static void RegisterTier(CardInfo card, int level) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //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 if ((Object)(object)card == (Object)null) { return; } StunHandRebuild.RegisterTier(card.cardName, level); CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ResistanceDeltaHelper.ComputeAddDelta(player, level, "Stun Resistance", (int id) => StunResistanceManager.instance.GetReductionPercent(id)))); string cardName = card.cardName; object obj = <>c.<>9__1_1; if (obj == null) { SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Stun Resistance", (int id) => StunResistanceManager.instance.GetReductionPercent(id), (IEnumerable cards) => StunHandRebuild.ComputeReductionFromHand(cards)); <>c.<>9__1_1 = val; obj = (object)val; } CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj); SLog.Line($"Registered stun delta preview for '{card.cardName}' (LV{level})."); } } internal static class StunCardRegistrar { internal static void RegisterAll() { SLog.Section("StunCardRegistrar — RegisterAll"); CustomCard.BuildCard((Action)delegate(CardInfo ci) { StunCardRegistry.Lv3 = ci; }); CustomCard.BuildCard((Action)delegate(CardInfo ci) { StunCardRegistry.Lv2 = ci; }); CustomCard.BuildCard((Action)OnLv1Built); } private static void OnLv1Built(CardInfo ci) { StunCardRegistry.Lv1 = ci; SLog.Line("Registered Stun Resistance LV1: " + ci.cardName); StunCardDeltaRegistrar.RegisterAll(); } } internal static class StunCardRegistry { internal static CardInfo Lv1; internal static CardInfo Lv2; internal static CardInfo Lv3; } public abstract class StunResistanceBase : CustomCard { protected abstract int Level { get; } protected abstract string ArtFileName { get; } protected abstract Rarity CardRarity { get; } protected override string GetTitle() { return "Stun Resistance " + Roman(Level); } protected override string GetDescription() { return ResistanceCardText.Description(Level, "stun"); } 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 = ResistanceCardText.StatAmount(Level), stat = "Stun 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)7; } 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)) { string cardName = (((Object)(object)base.cardInfo != (Object)null) ? base.cardInfo.cardName : null); ResistanceCardOnAdd.Apply(player, data, Level, cardName, (IEnumerable cards) => StunHandRebuild.ComputeReductionFromHand(cards), delegate(int id) { StunResistanceManager.instance?.RebuildForPlayer(id); }); SLog.Section($"StunResistance LV{Level} — OnAddCard"); SLog.Line($"player={player.playerID} reduction={StunResistanceManager.instance?.GetReductionPercent(player.playerID):F0}%"); } } private static string Roman(int level) { return level switch { 1 => "I", 2 => "II", 3 => "III", _ => level.ToString(), }; } } public class StunResistanceLv1 : StunResistanceBase { protected override int Level => 1; protected override string ArtFileName => "stun_resistance_lv1.png"; protected override Rarity CardRarity => (Rarity)1; } public class StunResistanceLv2 : StunResistanceBase { protected override int Level => 2; protected override string ArtFileName => "stun_resistance_lv2.png"; protected override Rarity CardRarity => (Rarity)2; } public class StunResistanceLv3 : StunResistanceBase { protected override int Level => 3; protected override string ArtFileName => "stun_resistance_lv3.png"; protected override Rarity CardRarity => RarityHelper.Epic; } public abstract class UpgradeShieldHealthBase : CustomCard { protected abstract int Level { get; } protected abstract float FirstShieldMax { 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 "Grants or increases max shield health by " + PercentLabel(Multiplier) + ". First pickup sets a base shield if you have none."; } 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; if (!orCreateShield.HasShield) { orCreateShield.Max = FirstShieldMax; orCreateShield.Current = orCreateShield.Max; } else { 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} firstMax={FirstShieldMax:F0} multiplier={Multiplier:F2} max {max:F1} -> {orCreateShield.Max:F1}"); } } 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 FirstShieldMax => 100f; protected override float Multiplier => 1.2f; 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 FirstShieldMax => 150f; protected override float Multiplier => 1.5f; protected override string ArtFileName => "lv2_artwork.png"; protected override Rarity CardRarity => RarityHelper.Scarce; } public class UpgradeShieldLv3 : UpgradeShieldHealthBase { protected override int Level => 3; protected override float FirstShieldMax => 250f; protected override float Multiplier => 2f; 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 FirstShieldMax => 500f; protected override float Multiplier => 3f; protected override string ArtFileName => "lv4_artwork.png"; protected override Rarity CardRarity => RarityHelper.Epic; } public class UpgradeShieldLv5 : UpgradeShieldHealthBase { protected override int Level => 5; protected override float FirstShieldMax => 1000f; protected override float Multiplier => 3.5f; protected override string ArtFileName => "lv5_artwork.png"; protected override Rarity CardRarity => RarityHelper.Legendary; } }