Decompiled source of NeonChrome v1.0.1

plugins/NeonChrome/NeonChrome.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using HarmonyLib;
using Photon.Pun;
using TMPro;
using UnboundLib.Cards;
using UnityEngine;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("1.0.1.0")]
namespace NeonChrome;

public sealed class CyberwareRuntime : MonoBehaviour
{
	private const string ProjectileAction = "NeonChrome.Projectile.v1";

	private static readonly FieldInfo CurrentAmmo = typeof(GunAmmo).GetField("currentAmmo", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private readonly Dictionary<string, int> copies = new Dictionary<string, int>();

	private Player player;

	private CharacterData data;

	private CharacterStatModifiers stats;

	private Gun gun;

	private GunAmmo ammo;

	private bool attached;

	private bool surging;

	private float surgeRemaining;

	private float parryRemaining;

	private float reserve;

	private float previousHealth;

	internal bool HasTendons
	{
		get
		{
			if (attached)
			{
				return Count("Reinforced Tendons") > 0;
			}
			return false;
		}
	}

	private bool OwnsPlayer
	{
		get
		{
			if (!PhotonNetwork.OfflineMode)
			{
				if (Object.op_Implicit((Object)(object)data.view))
				{
					return data.view.IsMine;
				}
				return false;
			}
			return true;
		}
	}

	private bool InCombat
	{
		get
		{
			if (attached && data.isPlaying)
			{
				return !data.dead;
			}
			return false;
		}
	}

	public void Add(string card, Gun weapon, GunAmmo magazine)
	{
		copies.TryGetValue(card, out var value);
		copies[card] = value + 1;
		if (!attached)
		{
			player = ((Component)this).GetComponent<Player>();
			data = player.data;
			stats = ((Component)this).GetComponent<CharacterStatModifiers>();
			gun = weapon;
			ammo = magazine;
			CharacterStatModifiers obj = stats;
			obj.OnReloadDoneAction = (Action<int>)Delegate.Combine(obj.OnReloadDoneAction, new Action<int>(Reloaded));
			Block block = data.block;
			block.BlockAction = (Action<BlockTriggerType>)Delegate.Combine(block.BlockAction, new Action<BlockTriggerType>(Blocked));
			Block block2 = data.block;
			block2.BlockProjectileAction = (Action<GameObject, Vector3, Vector3>)Delegate.Combine(block2.BlockProjectileAction, new Action<GameObject, Vector3, Vector3>(Parried));
			HealthHandler healthHandler = data.healthHandler;
			healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(Revived));
			Gun obj2 = gun;
			obj2.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(obj2.ShootPojectileAction, new Action<GameObject>(ProjectileFired));
			previousHealth = data.health;
			attached = true;
			((Behaviour)this).enabled = true;
			data.view.RefreshRpcMonoBehaviourCache();
		}
	}

	public void RemoveAfterReset(string card)
	{
		if (copies.TryGetValue(card, out var value))
		{
			if (value <= 1)
			{
				copies.Remove(card);
			}
			else
			{
				copies[card] = value - 1;
			}
		}
		ClearTransient(restore: false);
		if (copies.Count == 0)
		{
			Detach();
			((Behaviour)this).enabled = false;
		}
	}

	private int Count(string card)
	{
		if (!copies.TryGetValue(card, out var value))
		{
			return 0;
		}
		return value;
	}

	private void Reloaded(int roundsRestored)
	{
		if (InCombat && roundsRestored > 0 && Count("Sandevistan") != 0)
		{
			surgeRemaining = Mathf.Min(3.5f, 1.5f + 0.5f * (float)(Count("Sandevistan") - 1));
			if (!surging)
			{
				CharacterStatModifiers obj = stats;
				obj.movementSpeed *= 1.35f;
				Gun obj2 = gun;
				obj2.attackSpeed /= 1.3f;
				surging = true;
			}
		}
	}

	private void Parried(GameObject projectile, Vector3 position, Vector3 direction)
	{
		if (InCombat && OwnsPlayer && Count("Kerenzikov") != 0 && Object.op_Implicit((Object)(object)projectile))
		{
			ProjectileHit component = projectile.GetComponent<ProjectileHit>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.ownPlayer) && component.ownPlayer.teamID != player.teamID)
			{
				parryRemaining = 4f;
			}
		}
	}

	private void Blocked(BlockTriggerType trigger)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if ((int)trigger != 0 || !InCombat || !OwnsPlayer || Count("Subdermal Armour") == 0)
		{
			return;
		}
		float num = Mathf.Min(reserve, Mathf.Max(0f, data.maxHealth - data.health));
		reserve = 0f;
		if (!(num <= 0f))
		{
			if (PhotonNetwork.OfflineMode)
			{
				Repair(num);
				return;
			}
			data.view.RPC("NeonChrome_Repair", (RpcTarget)0, new object[1] { num });
		}
	}

	[PunRPC]
	private void NeonChrome_Repair(float amount, PhotonMessageInfo info)
	{
		if (info.Sender == data.view.Owner && InCombat && Count("Subdermal Armour") != 0 && !float.IsNaN(amount) && !float.IsInfinity(amount) && !(amount <= 0f))
		{
			Repair(Mathf.Min(amount, data.maxHealth * 0.25f));
		}
	}

	private void Repair(float amount)
	{
		data.healthHandler.Heal(amount);
		previousHealth = data.health;
	}

	[PunRPC]
	private void NeonChrome_Recharge(float amount, PhotonMessageInfo info)
	{
		if (info.Sender == data.view.Owner && InCombat && Count("Ballistic Coprocessor") != 0 && FiniteRange(amount, 0f, 1f))
		{
			Recharge(amount);
		}
	}

	private void Recharge(float amount)
	{
		if (data.block.counter < data.block.Cooldown())
		{
			data.block.counter = Mathf.Min(data.block.Cooldown() + 0.01f, data.block.counter + amount);
		}
	}

	private void Update()
	{
		if (!attached)
		{
			return;
		}
		if (!InCombat)
		{
			ClearTransient(restore: true);
			return;
		}
		float deltaTime = TimeHandler.deltaTime;
		surgeRemaining = Mathf.Max(0f, surgeRemaining - deltaTime);
		parryRemaining = Mathf.Max(0f, parryRemaining - deltaTime);
		if (surging && surgeRemaining <= 0f)
		{
			EndSurge();
		}
		int num = Count("Subdermal Armour");
		if (OwnsPlayer && num > 0 && data.health < previousHealth)
		{
			float num2 = Mathf.Min(0.4f, 0.2f + 0.05f * (float)(num - 1));
			float num3 = Mathf.Min(0.25f, 0.1f + 0.025f * (float)(num - 1));
			reserve = Mathf.Min(data.maxHealth * num3, reserve + (previousHealth - data.health) * num2);
		}
		previousHealth = data.health;
	}

	private void ProjectileFired(GameObject projectile)
	{
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		ProjectileHit hit = projectile.GetComponent<ProjectileHit>();
		MoveTransform move = projectile.GetComponent<MoveTransform>();
		PhotonView component = projectile.GetComponent<PhotonView>();
		if (!Object.op_Implicit((Object)(object)hit) || !Object.op_Implicit((Object)(object)move))
		{
			return;
		}
		RayHitReflect component2 = projectile.GetComponent<RayHitReflect>();
		if (Object.op_Implicit((Object)(object)component2) && Count("Ballistic Coprocessor") > 0)
		{
			bool paid = false;
			component2.reflectAction = (Action<HitInfo>)Delegate.Combine(component2.reflectAction, (Action<HitInfo>)delegate(HitInfo collision)
			{
				if (!paid && Object.op_Implicit((Object)(object)this) && InCombat && OwnsPlayer && Count("Ballistic Coprocessor") != 0 && (!Object.op_Implicit((Object)(object)collision.transform) || !Object.op_Implicit((Object)(object)((Component)collision.transform).GetComponentInParent<Player>())))
				{
					paid = true;
					float num4 = Mathf.Min(1f, 0.5f + 0.1f * (float)(Count("Ballistic Coprocessor") - 1));
					if (PhotonNetwork.OfflineMode)
					{
						Recharge(num4);
					}
					else
					{
						data.view.RPC("NeonChrome_Recharge", (RpcTarget)0, new object[1] { num4 });
					}
				}
			});
		}
		bool applied = false;
		Action<Vector2, Vector2> action = delegate(Vector2 damageSpeed, Vector2 forceUnused)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			if (!applied && Object.op_Implicit((Object)(object)hit) && Object.op_Implicit((Object)(object)move) && FiniteRange(damageSpeed.x, 1f, 4f) && FiniteRange(damageSpeed.y, 1f, 4f) && FiniteRange(forceUnused.x, 1f, 3f))
			{
				applied = true;
				ProjectileHit obj = hit;
				obj.damage *= damageSpeed.x;
				ProjectileHit obj2 = hit;
				obj2.force *= forceUnused.x;
				MoveTransform obj3 = move;
				obj3.localForce *= damageSpeed.y;
				MoveTransform obj4 = move;
				obj4.worldForce *= damageSpeed.y;
				MoveTransform obj5 = move;
				obj5.velocity *= damageSpeed.y;
			}
		};
		hit.customActionsV2V2["NeonChrome.Projectile.v1"] = action;
		if (!InCombat || !OwnsPlayer)
		{
			return;
		}
		float num = 1f;
		float num2 = 1f;
		float num3 = 1f;
		if (Count("Kerenzikov") > 0 && parryRemaining > 0f)
		{
			num *= 1f + Mathf.Min(0.8f, 0.4f + 0.1f * (float)(Count("Kerenzikov") - 1));
			num2 *= 1.5f;
			parryRemaining = 0f;
		}
		if (Count("Reinforced Tendons") > 0 && !data.isGrounded && !data.isWallGrab && data.sinceGrounded > 0.1f)
		{
			num2 *= 1.3f;
			num3 *= 1.5f;
		}
		if (Count("Tech Capacitor") > 0 && Object.op_Implicit((Object)(object)ammo) && (int)CurrentAmmo.GetValue(ammo) == 1)
		{
			num *= 1f + Mathf.Min(1.2f, 0.6f + 0.15f * (float)(Count("Tech Capacitor") - 1));
			num2 *= 1.8f;
		}
		if (num != 1f || num2 != 1f || num3 != 1f)
		{
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(num, num2);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(num3, 0f);
			if (PhotonNetwork.OfflineMode || !Object.op_Implicit((Object)(object)component) || component.ViewID == 0)
			{
				action(val, val2);
			}
			else if (component.IsMine)
			{
				component.RPC("RPCA_CallCustomActionV2V2", (RpcTarget)0, new object[3] { "NeonChrome.Projectile.v1", val, val2 });
			}
		}
	}

	private static bool FiniteRange(float value, float min, float max)
	{
		if (!float.IsNaN(value) && !float.IsInfinity(value) && value >= min)
		{
			return value <= max;
		}
		return false;
	}

	private void EndSurge()
	{
		if (surging)
		{
			if (Object.op_Implicit((Object)(object)stats))
			{
				CharacterStatModifiers obj = stats;
				obj.movementSpeed /= 1.35f;
			}
			if (Object.op_Implicit((Object)(object)gun))
			{
				Gun obj2 = gun;
				obj2.attackSpeed *= 1.3f;
			}
			surging = false;
		}
	}

	private void ClearTransient(bool restore)
	{
		if (restore)
		{
			EndSurge();
		}
		else
		{
			surging = false;
		}
		surgeRemaining = 0f;
		parryRemaining = 0f;
		reserve = 0f;
		if (Object.op_Implicit((Object)(object)data))
		{
			previousHealth = data.health;
		}
	}

	private void Revived()
	{
		ClearTransient(restore: true);
	}

	private void Detach()
	{
		if (attached)
		{
			CharacterStatModifiers obj = stats;
			obj.OnReloadDoneAction = (Action<int>)Delegate.Remove(obj.OnReloadDoneAction, new Action<int>(Reloaded));
			Block block = data.block;
			block.BlockAction = (Action<BlockTriggerType>)Delegate.Remove(block.BlockAction, new Action<BlockTriggerType>(Blocked));
			Block block2 = data.block;
			block2.BlockProjectileAction = (Action<GameObject, Vector3, Vector3>)Delegate.Remove(block2.BlockProjectileAction, new Action<GameObject, Vector3, Vector3>(Parried));
			HealthHandler healthHandler = data.healthHandler;
			healthHandler.reviveAction = (Action)Delegate.Remove(healthHandler.reviveAction, new Action(Revived));
			Gun obj2 = gun;
			obj2.ShootPojectileAction = (Action<GameObject>)Delegate.Remove(obj2.ShootPojectileAction, new Action<GameObject>(ProjectileFired));
			attached = false;
		}
	}

	private void OnDestroy()
	{
		if (attached)
		{
			EndSurge();
			Detach();
		}
	}
}
[BepInProcess("Rounds.exe")]
[BepInPlugin("com.neonchrome.rounds.cards", "Neon Chrome", "1.0.1")]
[BepInDependency("com.willis.rounds.unbound", "3.2.13")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Id = "com.neonchrome.rounds.cards";

	public const string Version = "1.0.1";

	private int registered;

	private void Start()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		new Harmony("com.neonchrome.rounds.cards").PatchAll(typeof(Plugin).Assembly);
		CustomCard.BuildCard<Sandevistan>((Action<CardInfo>)Registered);
		CustomCard.BuildCard<Kerenzikov>((Action<CardInfo>)Registered);
		CustomCard.BuildCard<SubdermalArmour>((Action<CardInfo>)Registered);
		CustomCard.BuildCard<ReinforcedTendons>((Action<CardInfo>)Registered);
		CustomCard.BuildCard<BallisticCoprocessor>((Action<CardInfo>)Registered);
		CustomCard.BuildCard<TechCapacitor>((Action<CardInfo>)Registered);
	}

	private void Registered(CardInfo card)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered " + ((Object)((Component)card).gameObject).name + " (" + ++registered + "/6)"));
	}
}
public abstract class CyberwareCard : CustomCard
{
	protected abstract string ArtId { get; }

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

	protected override GameObject GetCardArt()
	{
		return CardArt.Load(ArtId);
	}

	public override void Callback()
	{
		((Component)this).gameObject.AddComponent<NeonCardPresentation>();
	}

	public override void OnAddCard(Player player, Gun gun, GunAmmo ammo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
	{
		CyberwareRuntime cyberwareRuntime = ((Component)player).GetComponent<CyberwareRuntime>();
		if (!Object.op_Implicit((Object)(object)cyberwareRuntime))
		{
			cyberwareRuntime = ((Component)player).gameObject.AddComponent<CyberwareRuntime>();
		}
		cyberwareRuntime.Add(((CustomCard)this).GetTitle(), gun, ammo);
	}

	public override void OnRemoveCard(Player player, Gun gun, GunAmmo ammo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
	{
		if (this is ReinforcedTendons)
		{
			data.jumps = Math.Max(1, data.jumps - 1);
		}
		CyberwareRuntime component = ((Component)player).GetComponent<CyberwareRuntime>();
		if (Object.op_Implicit((Object)(object)component))
		{
			component.RemoveAfterReset(((CustomCard)this).GetTitle());
		}
	}

	protected static CardInfoStat Stat(string name, string value, bool positive)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		CardInfoStat val = new CardInfoStat();
		val.stat = name;
		val.amount = value;
		val.positive = positive;
		return val;
	}
}
internal sealed class NeonCardPresentation : MonoBehaviour
{
	private CardVisuals visuals;

	private int refreshFrames;

	private void OnEnable()
	{
		refreshFrames = 30;
	}

	private void Start()
	{
		visuals = ((Component)this).GetComponentInChildren<CardVisuals>(true);
		if (Object.op_Implicit((Object)(object)visuals))
		{
			CardVisuals obj = visuals;
			obj.toggleSelectionAction = (Action<bool>)Delegate.Combine(obj.toggleSelectionAction, new Action<bool>(SelectionChanged));
		}
	}

	private void SelectionChanged(bool selected)
	{
		refreshFrames = 3;
		((Behaviour)this).enabled = true;
	}

	private void OnDestroy()
	{
		if (Object.op_Implicit((Object)(object)visuals))
		{
			CardVisuals obj = visuals;
			obj.toggleSelectionAction = (Action<bool>)Delegate.Remove(obj.toggleSelectionAction, new Action<bool>(SelectionChanged));
		}
	}

	private void LateUpdate()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		Canvas[] componentsInChildren = ((Component)this).GetComponentsInChildren<Canvas>(true);
		foreach (Canvas val in componentsInChildren)
		{
			val.additionalShaderChannels = (AdditionalCanvasShaderChannels)(val.additionalShaderChannels | 0x1B);
		}
		TMP_Text[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<TMP_Text>(true);
		foreach (TMP_Text val2 in componentsInChildren2)
		{
			if (((Object)((Component)val2).gameObject).name == "ModNameText")
			{
				val2.text = "NC";
			}
			val2.ForceMeshUpdate();
		}
		if (--refreshFrames <= 0)
		{
			((Behaviour)this).enabled = false;
		}
	}
}
public sealed class Sandevistan : CyberwareCard
{
	protected override string ArtId => "sandevistan";

	protected override string GetTitle()
	{
		return "Sandevistan";
	}

	protected override string GetDescription()
	{
		return "Finishing a reload overclocks your reflexes for 1.5 seconds. Move and fire faster until the surge fades.";
	}

	protected override Rarity GetRarity()
	{
		return (Rarity)1;
	}

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

	public override void SetupCard(CardInfo card, Gun gun, ApplyCardStats stats, CharacterStatModifiers body, Block block)
	{
		body.health = 0.85f;
	}

	protected override CardInfoStat[] GetStats()
	{
		return (CardInfoStat[])(object)new CardInfoStat[3]
		{
			CyberwareCard.Stat("Surge movement", "+35%", positive: true),
			CyberwareCard.Stat("Surge fire rate", "+30%", positive: true),
			CyberwareCard.Stat("Health", "-15%", positive: false)
		};
	}
}
public sealed class Kerenzikov : CyberwareCard
{
	protected override string ArtId => "kerenzikov";

	protected override string GetTitle()
	{
		return "Kerenzikov";
	}

	protected override string GetDescription()
	{
		return "Parry an enemy projectile to charge your next bullet. One stored charge; expires after 4 seconds.";
	}

	protected override Rarity GetRarity()
	{
		return (Rarity)1;
	}

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

	public override void SetupCard(CardInfo card, Gun gun, ApplyCardStats stats, CharacterStatModifiers body, Block block)
	{
		block.cdAdd = 0.25f;
	}

	protected override CardInfoStat[] GetStats()
	{
		return (CardInfoStat[])(object)new CardInfoStat[3]
		{
			CyberwareCard.Stat("Charged damage", "+40%", positive: true),
			CyberwareCard.Stat("Charged speed", "+50%", positive: true),
			CyberwareCard.Stat("Block cooldown", "+0.25s", positive: false)
		};
	}
}
public sealed class SubdermalArmour : CyberwareCard
{
	protected override string ArtId => "armour";

	protected override string GetTitle()
	{
		return "Subdermal Armour";
	}

	protected override string GetDescription()
	{
		return "Bank 20% of health lost, up to 10% of max HP. Your next manual block spends the reserve to repair you.";
	}

	protected override Rarity GetRarity()
	{
		return (Rarity)0;
	}

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

	public override void SetupCard(CardInfo card, Gun gun, ApplyCardStats stats, CharacterStatModifiers body, Block block)
	{
		body.health = 1.3f;
		body.movementSpeed = 0.9f;
	}

	protected override CardInfoStat[] GetStats()
	{
		return (CardInfoStat[])(object)new CardInfoStat[2]
		{
			CyberwareCard.Stat("Health", "+30%", positive: true),
			CyberwareCard.Stat("Movement speed", "-10%", positive: false)
		};
	}
}
public sealed class ReinforcedTendons : CyberwareCard
{
	protected override string ArtId => "tendons";

	protected override string GetTitle()
	{
		return "Reinforced Tendons";
	}

	protected override string GetDescription()
	{
		return "Aerial stabilisers accelerate your bullets and increase their knockback while airborne. Wall-grabbing does not count.";
	}

	protected override Rarity GetRarity()
	{
		return (Rarity)0;
	}

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

	public override void SetupCard(CardInfo card, Gun gun, ApplyCardStats stats, CharacterStatModifiers body, Block block)
	{
		body.numberOfJumps = 1;
		gun.damage = 0.85f;
	}

	protected override CardInfoStat[] GetStats()
	{
		return (CardInfoStat[])(object)new CardInfoStat[4]
		{
			CyberwareCard.Stat("Jumps", "+1", positive: true),
			CyberwareCard.Stat("Air shot speed", "+30%", positive: true),
			CyberwareCard.Stat("Air knockback", "+50%", positive: true),
			CyberwareCard.Stat("Damage", "-15%", positive: false)
		};
	}
}
public sealed class BallisticCoprocessor : CyberwareCard
{
	protected override string ArtId => "coprocessor";

	protected override string GetTitle()
	{
		return "Ballistic Coprocessor";
	}

	protected override string GetDescription()
	{
		return "Trajectory telemetry powers your defences. Each projectile's first terrain ricochet advances your block recharge by 0.5s.";
	}

	protected override Rarity GetRarity()
	{
		return (Rarity)2;
	}

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

	public override void SetupCard(CardInfo card, Gun gun, ApplyCardStats stats, CharacterStatModifiers body, Block block)
	{
		gun.reflects = 1;
		gun.damage = 0.8f;
		gun.reloadTimeAdd = 0.25f;
	}

	protected override CardInfoStat[] GetStats()
	{
		return (CardInfoStat[])(object)new CardInfoStat[3]
		{
			CyberwareCard.Stat("Bounces", "+1", positive: true),
			CyberwareCard.Stat("Damage", "-20%", positive: false),
			CyberwareCard.Stat("Reload time", "+0.25s", positive: false)
		};
	}
}
public sealed class TechCapacitor : CyberwareCard
{
	protected override string ArtId => "capacitor";

	protected override string GetTitle()
	{
		return "Tech Capacitor";
	}

	protected override string GetDescription()
	{
		return "Dump your capacitor into the last round of each magazine, turning it into a high-velocity finisher.";
	}

	protected override Rarity GetRarity()
	{
		return (Rarity)1;
	}

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

	public override void SetupCard(CardInfo card, Gun gun, ApplyCardStats stats, CharacterStatModifiers body, Block block)
	{
		gun.ammo = -1;
		gun.reloadTimeAdd = 0.25f;
	}

	protected override CardInfoStat[] GetStats()
	{
		return (CardInfoStat[])(object)new CardInfoStat[4]
		{
			CyberwareCard.Stat("Final damage", "+60%", positive: true),
			CyberwareCard.Stat("Final speed", "+80%", positive: true),
			CyberwareCard.Stat("Ammo", "-1", positive: false),
			CyberwareCard.Stat("Reload time", "+0.25s", positive: false)
		};
	}
}
internal static class CardArt
{
	private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>();

	internal static GameObject Load(string id)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Expected O, but got Unknown
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		if (Cache.TryGetValue(id, out var value))
		{
			return value;
		}
		using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("NeonChrome.Art." + id + ".png");
		if (stream == null)
		{
			throw new InvalidOperationException("Missing card artwork: " + id);
		}
		byte[] array;
		using (MemoryStream memoryStream = new MemoryStream())
		{
			stream.CopyTo(memoryStream);
			array = memoryStream.ToArray();
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		if (!ImageConversion.LoadImage(val, array))
		{
			throw new InvalidOperationException("Invalid artwork: " + id);
		}
		((Object)val).name = "NeonChrome." + id;
		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("NeonChrome.Art." + id, new Type[1] { typeof(RectTransform) });
		val2.transform.position = new Vector3(0f, 1000f, 0f);
		Image val3 = val2.AddComponent<Image>();
		val3.sprite = sprite;
		val3.preserveAspect = true;
		((Graphic)val3).raycastTarget = false;
		val2.GetComponent<RectTransform>().sizeDelta = new Vector2(500f, 500f);
		Object.DontDestroyOnLoad((Object)(object)val2);
		Cache.Add(id, val2);
		return val2;
	}
}
[HarmonyPatch(typeof(PlayerJump), "Jump")]
internal static class TendonsJumpFix
{
	private static void Prefix(PlayerJump __instance, bool __0, out int __state)
	{
		__state = -1;
		if (__0)
		{
			return;
		}
		CyberwareRuntime component = ((Component)__instance).GetComponent<CyberwareRuntime>();
		if (Object.op_Implicit((Object)(object)component) && component.HasTendons)
		{
			CharacterData component2 = ((Component)__instance).GetComponent<CharacterData>();
			if (!component2.isGrounded && component2.sinceWallGrab > 0.1f && component2.sinceJump >= 0.1f && component2.currentJumps > 0)
			{
				__state = component2.currentJumps;
			}
		}
	}

	private static void Postfix(PlayerJump __instance, int __state)
	{
		if (__state >= 0)
		{
			CharacterData component = ((Component)__instance).GetComponent<CharacterData>();
			if (component.sinceJump == 0f)
			{
				component.currentJumps = Mathf.Min(component.currentJumps, __state - 1);
			}
		}
	}
}