Decompiled source of NeedleSwapper v0.4.0

plugins/PaleOilSoap/PaleOilSoap.dll

Decompiled 2 weeks ago
using System;
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.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GlobalEnums;
using GlobalSettings;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using TeamCherry.Localization;
using UnityEngine;

[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("PaleOilSoap")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0+3ce75450abaa2cffdafc14d99fc9df381475a8db")]
[assembly: AssemblyProduct("PaleOilSoap")]
[assembly: AssemblyTitle("PaleOilSoap")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 PaleOilSoap
{
	internal sealed class Assets
	{
		public bool initialized
		{
			get
			{
				if (Object.op_Implicit((Object)(object)disableSound) && Object.op_Implicit((Object)(object)overrideSound))
				{
					return Object.op_Implicit((Object)(object)constrainedSound);
				}
				return false;
			}
		}

		public AudioClip disableSound { get; private set; }

		public AudioClip overrideSound { get; private set; }

		public AudioClip constrainedSound { get; private set; }

		public Assets()
		{
			string guid = "81cdd0803a8bcfb81097fa4b8f33bb6e.bundle";
			AssetBundle val = AssetBundle.GetAllLoadedAssetBundles().FirstOrDefault((Func<AssetBundle, bool>)((AssetBundle bundle) => ((Object)bundle).name == guid));
			if ((Object)(object)val != (Object)null)
			{
				Plugin.Logger.LogDebug((object)"Found target asset bundle in loaded asset bundles.");
				LoadSounds(val);
			}
			else
			{
				Plugin.Logger.LogDebug((object)"Could not find target asset bundle in loaded asset bundles, attempting to load manually.");
				val = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "aa", "StandaloneWindows64", "sfxstatic_assets_shared.bundle"));
				LoadSounds(val);
				val.Unload(false);
			}
			if (initialized)
			{
				Plugin.Logger.LogDebug((object)"Located assets.");
			}
			else
			{
				Plugin.Logger.LogWarning((object)"Failed to locate assets.");
			}
		}

		private void LoadSounds(AssetBundle assetBundle)
		{
			if ((Object)(object)assetBundle == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"Failed to locate target asset bundle.");
				return;
			}
			disableSound = assetBundle.LoadAsset<AudioClip>("Assets/Audio/SFX/Heroes/Hornet/Crest Weapons/hornet_hunter_needleart_slash_2.wav");
			overrideSound = assetBundle.LoadAsset<AudioClip>("Assets/Audio/SFX/Enemy/Bosses/Hornet/hornet_needle_catch.wav");
			constrainedSound = assetBundle.LoadAsset<AudioClip>("Assets/Audio/SFX/sword_hit_reject.wav");
		}
	}
	internal static class Compatibility
	{
		public const string SilksongPrepatcherGUID = "org.silksong-modding.prepatcher";

		public static bool PrepatcherPresent => Chainloader.PluginInfos.ContainsKey("org.silksong-modding.prepatcher");

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Apply()
		{
		}
	}
	internal sealed class Config
	{
		private readonly ConfigFile file;

		private readonly AcceptableValueRange<int> acceptableTargetNeedleUpgradeLevels = new AcceptableValueRange<int>(-1, 4);

		private readonly ConfigEntry<int> targetNeedleUpgradeLevel;

		private readonly ConfigEntry<bool> allowTargetAboveUpgradedLevel;

		private readonly ConfigEntry<bool> capTargetToObtainedUpgradeLevel;

		public int TargetNeedleUpgradeLevel
		{
			get
			{
				return targetNeedleUpgradeLevel.Value;
			}
			internal set
			{
				targetNeedleUpgradeLevel.Value = value;
			}
		}

		public bool AllowTargetAboveUpgradedLevel => allowTargetAboveUpgradedLevel.Value;

		public bool CapTargetToObtainedUpgradeLevel => capTargetToObtainedUpgradeLevel.Value;

		internal void Reload()
		{
			Plugin.Logger.LogDebug((object)("Reloading " + file.ConfigFilePath.Substring(file.ConfigFilePath.LastIndexOf(Path.DirectorySeparatorChar) + 1)));
			file.Reload();
		}

		internal Config(ConfigFile config)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			file = config;
			config.SaveOnConfigSet = false;
			targetNeedleUpgradeLevel = config.Bind<int>("Needle", "targetNeedleUpgradeLevel", -1, new ConfigDescription("The target upgrade level to override the Needle to.\n(-1 to disable override, 0 for starting Needle, 1–4 for each Needle upgrade)", (AcceptableValueBase)(object)acceptableTargetNeedleUpgradeLevels, Array.Empty<object>()));
			allowTargetAboveUpgradedLevel = config.Bind<bool>("Needle", "allowTargetAboveUpgradedLevel", false, "Allow targetNeedleUpgradeLevel to use levels higher than what has been acquired through the Pinmaster.");
			capTargetToObtainedUpgradeLevel = config.Bind<bool>("Needle", "capTargetToObtainedUpgradeLevel", true, "Prevent targetNeedleUpgradeLevel from becoming higher than what has been acquired through the Pinmaster when allowTargetAboveUpgradeLevel is false.\n\nEssentially caps the internal tracker to the current save's maximum upgrade level, to avoid requiring multiple \"downgrades\" to see a change in applied Needle level.");
			config.SaveOnConfigSet = true;
			config.Save();
		}
	}
	internal sealed class InventoryItemMenuButtonPrompt : InventoryItemButtonPrompt
	{
		private MenuActions _menuAction;

		public MenuActions menuAction
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return _menuAction;
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				_menuAction = value;
				((InventoryItemButtonPromptBase<InventoryItemButtonPromptData>)this).data.Action = Action;
			}
		}

		public HeroActionButton Action
		{
			get
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Expected I4, but got Unknown
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Expected I4, but got Unknown
				if (Platform.Current.WasLastInputKeyboard)
				{
					MenuActions val = menuAction;
					switch (val - 1)
					{
					case 0:
						return (HeroActionButton)0;
					case 1:
						return (HeroActionButton)4;
					case 2:
						return (HeroActionButton)2;
					case 3:
						return (HeroActionButton)10;
					}
				}
				else
				{
					MenuActions val = menuAction;
					switch (val - 1)
					{
					case 0:
						return (HeroActionButton)8;
					case 1:
						return (HeroActionButton)9;
					case 2:
						return (HeroActionButton)18;
					case 3:
						return (HeroActionButton)19;
					}
				}
				return (HeroActionButton)9;
			}
		}

		public override void OnShow(InventoryItemButtonPromptDisplayList displayList, InventoryItemButtonPromptData data)
		{
			//IL_0003: 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)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			data.Action = Action;
			((InventoryItemButtonPrompt)this).OnShow(displayList, data);
		}

		private void Awake()
		{
			((Behaviour)this).enabled = false;
		}
	}
	[HarmonyPatch]
	internal static class NailUpgrades
	{
		internal static int AdjustNailUpgrade(int acquiredNailUpgrade)
		{
			Config config = Plugin.Config;
			if (config.TargetNeedleUpgradeLevel < 0)
			{
				return acquiredNailUpgrade;
			}
			if (!config.AllowTargetAboveUpgradedLevel && config.TargetNeedleUpgradeLevel > acquiredNailUpgrade)
			{
				return acquiredNailUpgrade;
			}
			return config.TargetNeedleUpgradeLevel;
		}

		[HarmonyILManipulator]
		[HarmonyPatch(typeof(InventoryItemNail), "UpdateState")]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPatch(typeof(HealthManager), "ApplyDamageScaling")]
		private static void Redirect__PlayerData_nailUpgrades(ILContext il)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Plugin.Logger.LogDebug((object)("Attempting to patch " + ((MemberReference)il.Method).Name));
			ILCursor val = new ILCursor(il);
			int num2 = default(int);
			Func<Instruction, bool>[] array = new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<PlayerData>(x, "nailUpgrades"),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref num2)
			};
			if (Compatibility.PrepatcherPresent)
			{
				Plugin.Logger.LogDebug((object)"Detected 'org.silksong-modding.prepatcher', trying alternative IL instruction match.");
				int num = default(int);
				array = new Func<Instruction, bool>[3]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdstr(x, "nailUpgrades"),
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<PlayerData>(x, "GetInt"),
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref num)
				};
			}
			if (val.TryGotoNext((MoveType)2, array))
			{
				int index = val.Index;
				val.Index = index - 1;
				val.EmitDelegate<Func<int, int>>((Func<int, int>)AdjustNailUpgrade);
			}
			else
			{
				Plugin.Logger.LogError((object)("Cannot hook: failed to match IL instructions for " + ((MemberReference)il.Method).Name));
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("itsschwer.NeedleSwapper", "NeedleSwapper", "0.4.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string GUID = "itsschwer.NeedleSwapper";

		public const string Author = "itsschwer";

		public const string Name = "NeedleSwapper";

		public const string Version = "0.4.0";

		internal static ManualLogSource Logger { get; private set; }

		internal static Config Config { get; private set; }

		internal static Assets Assets { get; private set; }

		private void Awake()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			Logger.Sources.Remove((ILogSource)(object)((BaseUnityPlugin)this).Logger);
			Logger = Logger.CreateLogSource("itsschwer.NeedleSwapper");
			Config = new Config(((BaseUnityPlugin)this).Config);
			Assets = new Assets();
			new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID).PatchAll();
			Logger.LogMessage((object)"~awake.");
		}

		private void Update()
		{
			if (Input.GetKey((KeyCode)278) && Input.GetKeyDown((KeyCode)279))
			{
				Logger.LogWarning((object)"Debugging input triggered, reloading config.");
				Config.Reload();
			}
		}
	}
	[HarmonyPatch(typeof(InventoryItemSelectable))]
	internal static class UX
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryItemNail), "Start")]
		private static void InventoryItemNail_Start(InventoryItemNail __instance)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			InventoryItemButtonPrompt component = ((Component)__instance).GetComponent<InventoryItemButtonPrompt>();
			if ((Object)(object)component == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"Tried to set up button prompts but InventoryItemNail did not have any to copy from!");
				return;
			}
			LocalisedString responseText = default(LocalisedString);
			((LocalisedString)(ref responseText))..ctor("Tools", "UI_BUTTON_TOGGLE_STATE");
			InventoryItemMenuButtonPrompt inventoryItemMenuButtonPrompt = SetUpPrompt(component);
			((InventoryItemButtonPromptBase<InventoryItemButtonPromptData>)(object)inventoryItemMenuButtonPrompt).data.ResponseText = responseText;
			inventoryItemMenuButtonPrompt.menuAction = (MenuActions)3;
			InventoryItemMenuButtonPrompt inventoryItemMenuButtonPrompt2 = SetUpPrompt(component);
			((InventoryItemButtonPromptBase<InventoryItemButtonPromptData>)(object)inventoryItemMenuButtonPrompt2).data.ResponseText = responseText;
			inventoryItemMenuButtonPrompt2.menuAction = (MenuActions)1;
			ManualLogSource logger = Plugin.Logger;
			Platform current = Platform.Current;
			logger.LogInfo((object)string.Format("Set up button prompts (with {0}: {1})", "WasLastInputKeyboard", (current != null) ? new bool?(current.WasLastInputKeyboard) : null));
		}

		private static InventoryItemMenuButtonPrompt SetUpPrompt(InventoryItemButtonPrompt copy)
		{
			InventoryItemMenuButtonPrompt inventoryItemMenuButtonPrompt = ((Component)copy).gameObject.AddComponent<InventoryItemMenuButtonPrompt>();
			((InventoryItemButtonPromptBase<InventoryItemButtonPromptData>)(object)inventoryItemMenuButtonPrompt).appearCondition = ((InventoryItemButtonPromptBase<InventoryItemButtonPromptData>)(object)copy).appearCondition;
			((InventoryItemButtonPromptBase<InventoryItemButtonPromptData>)(object)inventoryItemMenuButtonPrompt).display = ((InventoryItemButtonPromptBase<InventoryItemButtonPromptData>)(object)copy).display;
			((Behaviour)inventoryItemMenuButtonPrompt).enabled = true;
			return inventoryItemMenuButtonPrompt;
		}

		[HarmonyPatch("Submit")]
		[HarmonyPostfix]
		private static void InventoryItemSelectable_Submit(InventoryItemSelectable __instance)
		{
			InventoryItemNail val = (InventoryItemNail)(object)((__instance is InventoryItemNail) ? __instance : null);
			if (val != null)
			{
				ChangeNail(val, 1);
			}
		}

		[HarmonyPatch("Extra")]
		[HarmonyPostfix]
		private static void InventoryItemSelectable_Extra(InventoryItemSelectable __instance)
		{
			InventoryItemNail val = (InventoryItemNail)(object)((__instance is InventoryItemNail) ? __instance : null);
			if (val != null)
			{
				ChangeNail(val, -1);
			}
		}

		private static void ChangeNail(InventoryItemNail nail, int delta)
		{
			int targetNeedleUpgradeLevel = Plugin.Config.TargetNeedleUpgradeLevel;
			Plugin.Config.TargetNeedleUpgradeLevel += delta;
			if (PlayerData.instance != null)
			{
				Config config = Plugin.Config;
				PlayerData instance = PlayerData.instance;
				if (config.CapTargetToObtainedUpgradeLevel && !config.AllowTargetAboveUpgradedLevel && config.TargetNeedleUpgradeLevel > instance.nailUpgrades)
				{
					config.TargetNeedleUpgradeLevel = instance.nailUpgrades;
				}
			}
			nail.UpdateState();
			((InventoryItemSelectable)nail).UpdateDisplay();
			string arg = ((PlayerData.instance == null) ? "{nameof(PlayerData)}.{nameof(PlayerData.instance)} is null??" : $"AcquiredNailUpgrades: {PlayerData.instance.nailUpgrades}}} (resolves as {NailUpgrades.AdjustNailUpgrade(PlayerData.instance.nailUpgrades)}");
			Plugin.Logger.LogDebug((object)(string.Format("Changed {0} from {1} to {2}", "TargetNeedleUpgradeLevel", targetNeedleUpgradeLevel, Plugin.Config.TargetNeedleUpgradeLevel) + string.Format("\n\t{{{0}: {1}, {2})", "AllowTargetAboveUpgradedLevel", Plugin.Config.AllowTargetAboveUpgradedLevel, arg)));
			PlayAudioFeedback(targetNeedleUpgradeLevel);
		}

		private static void PlayAudioFeedback(int before)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Assets.initialized)
			{
				Plugin.Logger.LogWarning((object)string.Format("Tried to play audio feedback but {0}.{1} is {2}!", "Assets", "initialized", Plugin.Assets.initialized));
				return;
			}
			Config config = Plugin.Config;
			PlayerData instance = PlayerData.instance;
			if (instance == null)
			{
				Plugin.Logger.LogWarning((object)"Tried to play audio feedback but PlayerData.instance is null!");
				return;
			}
			AudioEvent val = default(AudioEvent);
			val.PitchMin = 0.95f;
			val.PitchMax = 1.05f;
			val.Volume = 1f;
			if (config.TargetNeedleUpgradeLevel < 0)
			{
				val.Clip = Plugin.Assets.disableSound;
			}
			else if ((!config.AllowTargetAboveUpgradedLevel && config.TargetNeedleUpgradeLevel > instance.nailUpgrades) || before == config.TargetNeedleUpgradeLevel)
			{
				val.Clip = Plugin.Assets.constrainedSound;
			}
			else
			{
				val.Clip = Plugin.Assets.overrideSound;
				val.PitchMax = (val.PitchMin = 1f + 0.1f * (float)config.TargetNeedleUpgradeLevel);
			}
			((AudioEvent)(ref val)).SpawnAndPlayOneShot(Audio.DefaultUIAudioSourcePrefab, Vector3.zero, (Action)null);
		}
	}
}