Decompiled source of SpurRework v1.0.1

SpurRework.dll

Decompiled 23 minutes ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemQualities;
using ItemQualities.Utilities.Extensions;
using KinematicCharacterController;
using Microsoft.CodeAnalysis;
using R2API;
using R2API.Networking;
using R2API.Networking.Interfaces;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Items;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SpurRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("SpurRework")]
[assembly: AssemblyTitle("SpurRework")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 SpurRework
{
	internal static class QualityCompat
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		private static QualityTier HighestTier(CharacterBody body)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)body.inventory))
			{
				return (QualityTier)(-1);
			}
			ItemQualityCounts itemCountsEffective = InventoryExtensions.GetItemCountsEffective(body.inventory, ItemQualityGroups.JumpDamageStrike);
			return ((ItemQualityCounts)(ref itemCountsEffective)).HighestQuality;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static int AirUses(CharacterBody body)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected I4, but got Unknown
			QualityTier val = HighestTier(body);
			return (int)val switch
			{
				0 => SpurReworkPlugin.UncommonAirUses.Value, 
				1 => SpurReworkPlugin.RareAirUses.Value, 
				2 => SpurReworkPlugin.EpicAirUses.Value, 
				3 => SpurReworkPlugin.LegendaryAirUses.Value, 
				_ => 0, 
			};
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void ApplyChargeCost(CharacterBody body, int chargeBefore)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (SpurReworkPlugin.OverrideRareChargeCost.Value && chargeBefore >= 25 && (int)HighestTier(body) == 1)
			{
				int num = Math.Max(0, chargeBefore - SpurReworkPlugin.RareChargeCost.Value);
				body.SetBuffCount(Buffs.JumpDamageStrikeCharge.buffIndex, num);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void AddItemText(Dictionary<string, string> tokens)
		{
			AddTier(tokens, "UNCOMMON", 75, 150, SpurReworkPlugin.UncommonAirUses.Value);
			int chargeCost = (SpurReworkPlugin.OverrideRareChargeCost.Value ? SpurReworkPlugin.RareChargeCost.Value : 50);
			AddTier(tokens, "RARE", chargeCost, 250, SpurReworkPlugin.RareAirUses.Value);
			AddTier(tokens, "EPIC", 25, 350, SpurReworkPlugin.EpicAirUses.Value);
			AddTier(tokens, "LEGENDARY", 10, 500, SpurReworkPlugin.LegendaryAirUses.Value);
		}

		private static void AddTier(Dictionary<string, string> tokens, string tier, int chargeCost, int damagePerSpeed, int airUses)
		{
			bool flag = !SpurReworkPlugin.UsableInAir.Value;
			tokens["ITEM_JUMPDAMAGESTRIKE_" + tier + "_PICKUP"] = "Moving around builds up movement speed and jump height. At 25% charge or higher, press Interact while holding Jump to discharge into an electric blast that launches you upward.\n<sprite name=\"Quality\"> Increase damage based on movement speed and reduce charge used per blast." + (flag ? $" Use it {airUses} times in the air." : "");
			tokens["ITEM_JUMPDAMAGESTRIKE_" + tier + "_DESC"] = SpurReworkPlugin.BonusesText + "At 25% charge or higher, pressing <style=cIsUtility>Interact</style> while holding <style=cIsUtility>Jump</style> launches you upward, " + string.Format("consumes {0} <style=cIsUtility>{1}%</style> charge and triggers an <style=cIsDamage>explosive discharge</style> for ", "<sprite name=\"Quality\">", chargeCost) + "<style=cIsDamage>400% <style=cStack>(+280% per stack)</style> damage</style>, " + string.Format("plus an additional {0} <style=cIsDamage>{1}% <style=cStack>(+{2}% per stack)</style> damage</style> for every <style=cIsUtility>100% movement speed</style>, ", "<sprite name=\"Quality\">", damagePerSpeed, damagePerSpeed) + "in a 17m-32m <style=cStack>(+7.5m per stack)</style> area." + (flag ? string.Format(" Usable on the ground, or {0} <style=cIsUtility>{1} times</style> before landing.", "<sprite name=\"Quality\">", airUses) : "");
		}
	}
	internal static class RiskOfOptionsCompat
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static IsDisabledDelegate <>9__0_0;

			public static IsDisabledDelegate <>9__3_0;

			internal bool <Register>b__0_0()
			{
				return !SpurReworkPlugin.OverrideRareChargeCost.Value;
			}

			internal bool <AddKeyBind>b__3_0()
			{
				return !SpurReworkPlugin.UseCustomKeys.Value;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Register(string pluginLocation)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("Reworks Faraday Spur: lower speed and jump bonuses that stack, and the blast fires from pressing Interact while holding Jump.");
			Sprite val = LoadIcon(pluginLocation);
			if (Object.op_Implicit((Object)(object)val))
			{
				ModSettingsManager.SetModIcon(val);
			}
			AddSlider(SpurReworkPlugin.MoveSpeedBase, 0f, 200f, 5f, "{0:0}%");
			AddSlider(SpurReworkPlugin.MoveSpeedPerStack, 0f, 100f, 5f, "{0:0}%");
			AddSlider(SpurReworkPlugin.JumpBase, 0f, 200f, 5f, "{0:0}%");
			AddSlider(SpurReworkPlugin.JumpPerStack, 0f, 100f, 5f, "{0:0}%");
			AddSlider(SpurReworkPlugin.ChargeSpeed, 0.25f, 3f, 0.05f, "{0:0.00}x");
			AddSlider(SpurReworkPlugin.LaunchMultiplier, 0f, 3f, 0.05f, "{0:0.00}x");
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(SpurReworkPlugin.UsableInAir));
			AddSlider(SpurReworkPlugin.GroundBuffer, 0f, 1f, 0.05f, "{0:0.00}s");
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(SpurReworkPlugin.BlockWhenInteractableInView));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(SpurReworkPlugin.UseCustomKeys));
			AddKeyBind(SpurReworkPlugin.BlastKey);
			AddKeyBind(SpurReworkPlugin.JumpKey);
			if (!SpurReworkPlugin.QualityLoaded)
			{
				return;
			}
			AddIntSlider(SpurReworkPlugin.UncommonAirUses, 1, 10);
			AddIntSlider(SpurReworkPlugin.RareAirUses, 1, 10);
			AddIntSlider(SpurReworkPlugin.EpicAirUses, 1, 10);
			AddIntSlider(SpurReworkPlugin.LegendaryAirUses, 1, 10);
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(SpurReworkPlugin.OverrideRareChargeCost));
			ConfigEntry<int> rareChargeCost = SpurReworkPlugin.RareChargeCost;
			IntSliderConfig val2 = new IntSliderConfig
			{
				min = 5,
				max = 75
			};
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				IsDisabledDelegate val3 = () => !SpurReworkPlugin.OverrideRareChargeCost.Value;
				<>c.<>9__0_0 = val3;
				obj = (object)val3;
			}
			((BaseOptionConfig)val2).checkIfDisabled = (IsDisabledDelegate)obj;
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(rareChargeCost, val2));
		}

		private static void AddSlider(ConfigEntry<float> entry, float min, float max, float increment, string format)
		{
			//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_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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(entry, new StepSliderConfig
			{
				min = min,
				max = max,
				increment = increment,
				FormatString = format
			}));
		}

		private static void AddIntSlider(ConfigEntry<int> entry, int min, int max)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig
			{
				min = min,
				max = max
			}));
		}

		private static void AddKeyBind(ConfigEntry<KeyboardShortcut> entry)
		{
			//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_0030: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			KeyBindConfig val = new KeyBindConfig();
			object obj = <>c.<>9__3_0;
			if (obj == null)
			{
				IsDisabledDelegate val2 = () => !SpurReworkPlugin.UseCustomKeys.Value;
				<>c.<>9__3_0 = val2;
				obj = (object)val2;
			}
			((BaseOptionConfig)val).checkIfDisabled = (IsDisabledDelegate)obj;
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(entry, val));
		}

		private static Sprite LoadIcon(string pluginLocation)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			string path = Path.Combine(Path.GetDirectoryName(pluginLocation), "icon.png");
			if (!File.Exists(path))
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2);
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path)))
			{
				return null;
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
	}
	public static class SpurPatches
	{
		private class InputState
		{
			public bool blastKeyWasDown;

			public InteractionDriver interactionDriver;

			public float airTime;

			public int usesSinceGrounded;

			public float lastUseTime = float.NegativeInfinity;
		}

		private const float LandingGraceTime = 0.1f;

		private static readonly ConditionalWeakTable<JumpDamageStrikeBodyBehavior, InputState> inputStates = new ConditionalWeakTable<JumpDamageStrikeBodyBehavior, InputState>();

		private static bool dischargeAllowed;

		private static float FullChargeBonus(CharacterBody body, float baseValue, float perStack)
		{
			int num = (Object.op_Implicit((Object)(object)body.inventory) ? body.inventory.GetItemCountEffective(Items.JumpDamageStrike) : 0);
			if (num <= 0)
			{
				return 0f;
			}
			return (baseValue + perStack * (float)(num - 1)) / 100f;
		}

		public static float MoveSpeedPerCharge(CharacterBody body)
		{
			return FullChargeBonus(body, SpurReworkPlugin.MoveSpeedBase.Value, SpurReworkPlugin.MoveSpeedPerStack.Value) / 100f;
		}

		public static float JumpPowerPerCharge(CharacterBody body)
		{
			return FullChargeBonus(body, SpurReworkPlugin.JumpBase.Value, SpurReworkPlugin.JumpPerStack.Value) / 100f;
		}

		[HarmonyPatch(typeof(CharacterBody), "RecalculateStats")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> RecalculateStatsTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo moveField = AccessTools.Field(typeof(JumpDamageStrikeBodyBehavior), "MoveSpeedVelocityPerCharge");
			FieldInfo jumpField = AccessTools.Field(typeof(JumpDamageStrikeBodyBehavior), "JumpVelocityPerCharge");
			MethodInfo moveMethod = AccessTools.Method(typeof(SpurPatches), "MoveSpeedPerCharge", (Type[])null, (Type[])null);
			MethodInfo jumpMethod = AccessTools.Method(typeof(SpurPatches), "JumpPowerPerCharge", (Type[])null, (Type[])null);
			bool movePatched = false;
			bool jumpPatched = false;
			foreach (CodeInstruction instruction in instructions)
			{
				MethodInfo replacement = null;
				if (CodeInstructionExtensions.LoadsField(instruction, moveField, false))
				{
					replacement = moveMethod;
					movePatched = true;
				}
				else if (CodeInstructionExtensions.LoadsField(instruction, jumpField, false))
				{
					replacement = jumpMethod;
					jumpPatched = true;
				}
				if (replacement == null)
				{
					yield return instruction;
					continue;
				}
				yield return CodeInstructionExtensions.MoveBlocksFrom(CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Ldarg_0, (object)null), instruction), instruction);
				yield return new CodeInstruction(OpCodes.Call, (object)replacement);
			}
			if (!movePatched || !jumpPatched)
			{
				SpurReworkPlugin.Log.LogError((object)$"RecalculateStats patch incomplete (move speed: {movePatched}, jump: {jumpPatched}). A game update probably changed the Spur code.");
			}
		}

		[HarmonyPatch(typeof(JumpDamageStrikeBodyBehavior), "FixedUpdate")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> FixedUpdateTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo positionGetter = AccessTools.PropertyGetter(typeof(Transform), "position");
			MethodInfo replacement = AccessTools.Method(typeof(SpurPatches), "SimulatedPosition", (Type[])null, (Type[])null);
			bool patched = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!patched && CodeInstructionExtensions.Calls(instruction, positionGetter))
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = replacement;
					patched = true;
				}
				yield return instruction;
			}
			if (!patched)
			{
				SpurReworkPlugin.Log.LogError((object)"Charge rate fix not applied. A game update probably changed the Spur code.");
			}
		}

		public static Vector3 SimulatedPosition(Transform transform)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			KinematicCharacterMotor component = ((Component)transform).GetComponent<KinematicCharacterMotor>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return transform.position;
			}
			return component.TransientPosition;
		}

		[HarmonyPatch(typeof(JumpDamageStrikeBodyBehavior), "UpdateCharge")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> UpdateChargeTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo moveSpeedGetter = AccessTools.PropertyGetter(typeof(CharacterBody), "moveSpeed");
			MethodInfo scale = AccessTools.Method(typeof(SpurPatches), "ScaleChargeGain", (Type[])null, (Type[])null);
			bool patched = false;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (!patched && CodeInstructionExtensions.Calls(instruction, moveSpeedGetter))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)scale);
					patched = true;
				}
			}
			if (!patched)
			{
				SpurReworkPlugin.Log.LogError((object)"Charge speed patch not applied. A game update probably changed the Spur code.");
			}
		}

		public static float ScaleChargeGain(float moveSpeed)
		{
			return moveSpeed * SpurReworkPlugin.ChargeSpeed.Value;
		}

		[HarmonyPatch(typeof(JumpDamageStrikeBodyBehavior), "DischargeEffects")]
		[HarmonyPrefix]
		private static bool DischargeEffectsPrefix()
		{
			return dischargeAllowed;
		}

		[HarmonyPatch(typeof(JumpDamageStrikeBodyBehavior), "FixedUpdate")]
		[HarmonyPostfix]
		private static void FixedUpdatePostfix(JumpDamageStrikeBodyBehavior __instance)
		{
			//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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_01c6: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody component = ((Component)__instance).GetComponent<CharacterBody>();
			if (!Object.op_Implicit((Object)(object)component) || !component.hasEffectiveAuthority || !Object.op_Implicit((Object)(object)component.inputBank))
			{
				return;
			}
			bool value = SpurReworkPlugin.UseCustomKeys.Value;
			int num;
			int num2;
			if (value)
			{
				num = (LocalPlayerHasControl(component) ? 1 : 0);
				if (num == 0)
				{
					num2 = 0;
					goto IL_006f;
				}
			}
			else
			{
				num = 1;
			}
			KeyboardShortcut value2;
			if (!value)
			{
				num2 = (component.inputBank.interact.down ? 1 : 0);
			}
			else
			{
				value2 = SpurReworkPlugin.BlastKey.Value;
				num2 = (Input.GetKey(((KeyboardShortcut)(ref value2)).MainKey) ? 1 : 0);
			}
			goto IL_006f;
			IL_006f:
			bool flag = (byte)num2 != 0;
			int num3;
			if (num != 0)
			{
				if (!value)
				{
					num3 = (component.inputBank.jump.down ? 1 : 0);
				}
				else
				{
					value2 = SpurReworkPlugin.JumpKey.Value;
					num3 = (Input.GetKey(((KeyboardShortcut)(ref value2)).MainKey) ? 1 : 0);
				}
			}
			else
			{
				num3 = 0;
			}
			bool flag2 = (byte)num3 != 0;
			InputState orCreateValue = inputStates.GetOrCreateValue(__instance);
			bool flag3 = !Object.op_Implicit((Object)(object)component.characterMotor) || component.characterMotor.isGrounded;
			if (flag3)
			{
				orCreateValue.airTime = 0f;
				if (Time.fixedTime - orCreateValue.lastUseTime > 0.1f)
				{
					orCreateValue.usesSinceGrounded = 0;
				}
			}
			else
			{
				orCreateValue.airTime += Time.fixedDeltaTime;
			}
			bool num4 = flag && !orCreateValue.blastKeyWasDown;
			orCreateValue.blastKeyWasDown = flag;
			if (!num4 || !flag2 || component.GetBuffCount(Buffs.JumpDamageStrikeCharge) < 25 || (!flag3 && !CanUseInAir(component, orCreateValue)))
			{
				return;
			}
			if (!value && SpurReworkPlugin.BlockWhenInteractableInView.Value)
			{
				if (!Object.op_Implicit((Object)(object)orCreateValue.interactionDriver))
				{
					orCreateValue.interactionDriver = ((Component)component).GetComponent<InteractionDriver>();
				}
				if (Object.op_Implicit((Object)(object)orCreateValue.interactionDriver) && Object.op_Implicit((Object)(object)orCreateValue.interactionDriver.currentInteractable))
				{
					return;
				}
			}
			orCreateValue.usesSinceGrounded++;
			orCreateValue.lastUseTime = Time.fixedTime;
			LaunchUpward(component);
			if (NetworkServer.active)
			{
				Discharge(__instance);
			}
			else
			{
				NetMessageExtensions.Send((INetMessage)(object)new RequestDischargeMessage(((NetworkBehaviour)component).netId), (NetworkDestination)2);
			}
		}

		private static bool CanUseInAir(CharacterBody body, InputState state)
		{
			if (SpurReworkPlugin.UsableInAir.Value)
			{
				return true;
			}
			int num = (SpurReworkPlugin.QualityLoaded ? QualityCompat.AirUses(body) : 0);
			if (num <= 0)
			{
				if (state.usesSinceGrounded == 0)
				{
					return state.airTime <= SpurReworkPlugin.GroundBuffer.Value;
				}
				return false;
			}
			return state.usesSinceGrounded < num;
		}

		private static bool LocalPlayerHasControl(CharacterBody body)
		{
			CharacterMaster master = body.master;
			PlayerCharacterMasterController val = (Object.op_Implicit((Object)(object)master) ? master.playerCharacterMasterController : null);
			NetworkUser val2 = (Object.op_Implicit((Object)(object)val) ? val.networkUser : null);
			LocalUser val3 = (Object.op_Implicit((Object)(object)val2) ? val2.localUser : null);
			if (val3 != null && !val3.isUIFocused && Object.op_Implicit((Object)(object)val2.cameraRigController))
			{
				return val2.cameraRigController.isControlAllowed;
			}
			return false;
		}

		private static void LaunchUpward(CharacterBody body)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			CharacterMotor characterMotor = body.characterMotor;
			float value = SpurReworkPlugin.LaunchMultiplier.Value;
			if (Object.op_Implicit((Object)(object)characterMotor) && !(value <= 0f))
			{
				Vector3 velocity = characterMotor.velocity;
				velocity.y = Mathf.Max(velocity.y, body.jumpPower * value * characterMotor.jumpPowerPenaltyCoefficient);
				characterMotor.velocity = velocity;
				((BaseCharacterController)characterMotor).Motor.ForceUnground(0.1f);
			}
		}

		public static void Discharge(JumpDamageStrikeBodyBehavior behavior)
		{
			CharacterBody component = ((Component)behavior).GetComponent<CharacterBody>();
			int buffCount = component.GetBuffCount(Buffs.JumpDamageStrikeCharge);
			dischargeAllowed = true;
			try
			{
				behavior.DischargeEffects();
				if (SpurReworkPlugin.QualityLoaded)
				{
					QualityCompat.ApplyChargeCost(component, buffCount);
				}
			}
			finally
			{
				dischargeAllowed = false;
			}
		}
	}
	public class RequestDischargeMessage : INetMessage, ISerializableObject
	{
		private NetworkInstanceId bodyId;

		public RequestDischargeMessage()
		{
		}

		public RequestDischargeMessage(NetworkInstanceId bodyId)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			this.bodyId = bodyId;
		}

		public void Serialize(NetworkWriter writer)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			writer.Write(bodyId);
		}

		public void Deserialize(NetworkReader reader)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			bodyId = reader.ReadNetworkId();
		}

		public void OnReceived()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (NetworkServer.active ? NetworkServer.FindLocalObject(bodyId) : null);
			JumpDamageStrikeBodyBehavior val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<JumpDamageStrikeBodyBehavior>() : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				SpurPatches.Discharge(val2);
			}
		}
	}
	[BepInPlugin("com.spurrework.faradayspur", "Spur Rework", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SpurReworkPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.spurrework.faradayspur";

		public const string PluginName = "Spur Rework";

		private const string RiskOfOptionsGuid = "com.rune580.riskofoptions";

		private const string QualityGuid = "com.Gorakh.ItemQualities";

		public const string BasePickupText = "Moving around builds up movement speed and jump height. At 25% charge or higher, press Interact while holding Jump to discharge into an electric blast that launches you upward.";

		public static ManualLogSource Log;

		public static ConfigEntry<float> MoveSpeedBase;

		public static ConfigEntry<float> MoveSpeedPerStack;

		public static ConfigEntry<float> JumpBase;

		public static ConfigEntry<float> JumpPerStack;

		public static ConfigEntry<float> LaunchMultiplier;

		public static ConfigEntry<float> ChargeSpeed;

		public static ConfigEntry<bool> UsableInAir;

		public static ConfigEntry<float> GroundBuffer;

		public static ConfigEntry<int> UncommonAirUses;

		public static ConfigEntry<int> RareAirUses;

		public static ConfigEntry<int> EpicAirUses;

		public static ConfigEntry<int> LegendaryAirUses;

		public static ConfigEntry<bool> OverrideRareChargeCost;

		public static ConfigEntry<int> RareChargeCost;

		public static ConfigEntry<bool> BlockWhenInteractableInView;

		public static ConfigEntry<bool> UseCustomKeys;

		public static ConfigEntry<KeyboardShortcut> BlastKey;

		public static ConfigEntry<KeyboardShortcut> JumpKey;

		private LanguageOverlay descriptionOverlay;

		public static bool QualityLoaded { get; private set; }

		public static string BonusesText => "Moving around builds up <style=cIsUtility>charge</style>, granting up to " + $"<style=cIsUtility>+{MoveSpeedBase.Value:0.##}% <style=cStack>(+{MoveSpeedPerStack.Value:0.##}% per stack)</style> movement speed</style> and " + $"<style=cIsUtility>+{JumpBase.Value:0.##}% <style=cStack>(+{JumpPerStack.Value:0.##}% per stack)</style> jump height</style> at 100%. ";

		private void Awake()
		{
			//IL_0192: 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_02a7: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			QualityLoaded = Chainloader.PluginInfos.ContainsKey("com.Gorakh.ItemQualities");
			MoveSpeedBase = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Move Speed", 40f, "Percent move speed at 100% charge with one stack.");
			MoveSpeedPerStack = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Move Speed Per Stack", 25f, "Extra percent move speed at 100% charge per additional stack.");
			JumpBase = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Jump Height", 30f, "Percent jump power at 100% charge with one stack, the same stat as vanilla's +200%. Height grows with the square of power, so +30% is about +69% height.");
			JumpPerStack = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Jump Height Per Stack", 15f, "Extra percent jump power at 100% charge per additional stack.");
			ChargeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Charge Speed", 1.5f, "How fast charge builds, as a multiple of vanilla. 1.5 is 50% faster.");
			LaunchMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Blast", "Launch Multiplier", 1.75f, "Upward launch from the blast, as a multiple of your normal jump speed at that charge. 0 turns the launch off.");
			UsableInAir = ((BaseUnityPlugin)this).Config.Bind<bool>("Blast", "Usable On Ground And In Air", false, "On: the blast works any time, with no limit on uses in the air. Off: it only works on the ground or just after leaving it, plus any Quality air uses.");
			GroundBuffer = ((BaseUnityPlugin)this).Config.Bind<float>("Blast", "Ground Buffer", 0.3f, "Seconds after leaving the ground that the blast still counts as used from the ground, so it works right after a jump.");
			BlockWhenInteractableInView = ((BaseUnityPlugin)this).Config.Bind<bool>("Blast", "Block When Interactable In View", true, "Pressing Interact while looking at a chest, shrine, etc. uses that object and does not fire the blast.");
			UseCustomKeys = ((BaseUnityPlugin)this).Config.Bind<bool>("Keys", "Use Custom Keys", false, "Off: the blast uses the game's own Interact and Jump controls, including controllers. On: it uses the two keys below.");
			BlastKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "Blast Key", new KeyboardShortcut((KeyCode)101, Array.Empty<KeyCode>()), "Press this while holding the Hold Key to fire the blast. Only used with Use Custom Keys on.");
			JumpKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "Hold Key", new KeyboardShortcut((KeyCode)32, Array.Empty<KeyCode>()), "Hold this while pressing the Blast Key. Only used with Use Custom Keys on.");
			if (QualityLoaded)
			{
				UncommonAirUses = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "Uncommon Air Uses", 2, "Blasts per trip through the air with an Uncommon Spur. Each one still needs 25% charge.");
				RareAirUses = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "Rare Air Uses", 3, "Blasts per trip through the air with a Rare Spur. Each one still needs 25% charge, so 3 needs Override Rare Charge Cost on.");
				EpicAirUses = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "Epic Air Uses", 4, "Blasts per trip through the air with an Epic Spur. Each one still needs 25% charge.");
				LegendaryAirUses = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "Legendary Air Uses", 8, "Blasts per trip through the air with a Legendary Spur. Each one still needs 25% charge.");
				OverrideRareChargeCost = ((BaseUnityPlugin)this).Config.Bind<bool>("Quality", "Override Rare Charge Cost", true, "On: a Rare Spur spends Rare Charge Cost per blast. Off: it spends Quality's own 50%, which only allows 2 blasts from a full bar.");
				RareChargeCost = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "Rare Charge Cost", 35, "Percent charge a Rare Spur spends per blast. Only used with Override Rare Charge Cost on.");
			}
			NetworkingAPI.RegisterMessageType<RequestDischargeMessage>();
			new Harmony("com.spurrework.faradayspur").PatchAll(typeof(SpurPatches));
			OverrideItemText();
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				ApplySettingChange();
			};
			if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
			{
				RiskOfOptionsCompat.Register(((BaseUnityPlugin)this).Info.Location);
			}
		}

		private void ApplySettingChange()
		{
			OverrideItemText();
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if (readOnlyInstances.HasBuff(Buffs.JumpDamageStrikeCharge))
				{
					readOnlyInstances.MarkAllStatsDirty();
				}
			}
		}

		private void OverrideItemText()
		{
			LanguageOverlay obj = descriptionOverlay;
			if (obj != null)
			{
				obj.Remove();
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				["ITEM_JUMPDAMAGESTRIKE_PICKUP"] = "Moving around builds up movement speed and jump height. At 25% charge or higher, press Interact while holding Jump to discharge into an electric blast that launches you upward.",
				["ITEM_JUMPDAMAGESTRIKE_DESC"] = BonusesText + "At 25% charge or higher, pressing <style=cIsUtility>Interact</style> while holding <style=cIsUtility>Jump</style> launches you upward and triggers an <style=cIsDamage>explosive discharge</style> for <style=cIsDamage>400% <style=cStack>(+280% per stack)</style> damage</style> in a 17m-32m <style=cStack>(+7.5m per stack)</style> area." + (UsableInAir.Value ? "" : " Usable on the ground or right after leaving it.")
			};
			if (QualityLoaded)
			{
				QualityCompat.AddItemText(dictionary);
			}
			descriptionOverlay = LanguageAPI.AddOverlay(dictionary);
		}
	}
}