using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BulkBuy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("BulkBuy")]
[assembly: AssemblyTitle("BulkBuy")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[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 BulkBuy
{
internal static class AudioSuppressor
{
private static readonly HashSet<string> BatchedKeys = new HashSet<string> { "Buy_0", "Sell_0", "PickUp_V", "Error" };
private static readonly HashSet<string> PlayedThisBatch = new HashSet<string>();
private static bool _active;
public static void BeginBatch()
{
PlayedThisBatch.Clear();
_active = true;
}
public static void EndBatch()
{
_active = false;
PlayedThisBatch.Clear();
}
public static bool ShouldSuppress(string cooldownKey)
{
if (!_active || string.IsNullOrEmpty(cooldownKey))
{
return false;
}
if (!BatchedKeys.Contains(cooldownKey))
{
return false;
}
return !PlayedThisBatch.Add(cooldownKey);
}
}
internal static class BaitToastBatcher
{
private const float TailSeconds = 1f;
private const float SlidingWindowSeconds = 0.25f;
private static bool _batchActive;
private static float _windowEnd;
private static int _accumulated;
private static bool _emitting;
public static void BeginBatch()
{
_batchActive = true;
}
public static void EndBatch()
{
_batchActive = false;
_windowEnd = Mathf.Max(_windowEnd, Time.time + 1f);
}
public static bool TrySwallow(int amount, bool increased)
{
if (_emitting || !increased)
{
return false;
}
if (!_batchActive && Time.time > _windowEnd)
{
return false;
}
_accumulated += amount;
_windowEnd = Mathf.Max(_windowEnd, Time.time + 0.25f);
return true;
}
public static void Tick()
{
if (!_batchActive && _accumulated > 0 && !(Time.time <= _windowEnd))
{
int accumulated = _accumulated;
_accumulated = 0;
_windowEnd = 0f;
_emitting = true;
try
{
PlayerUI.OnBaitChange(accumulated, true);
}
finally
{
_emitting = false;
}
Plugin.Log.LogDebug((object)$"Collapsed bait toasts into a single +{accumulated}.");
}
}
public static void Reset()
{
_batchActive = false;
_accumulated = 0;
_windowEnd = 0f;
_emitting = false;
}
}
internal sealed class BulkBuyConfig
{
public const int HardCeiling = 50;
private const string QuantitiesDefault = "1,5,10,25,50";
public ConfigEntry<KeyboardShortcut> CycleKey { get; }
public ConfigEntry<KeyboardShortcut> ReverseModifier { get; }
public ConfigEntry<string> Quantities { get; }
public ConfigEntry<int> MaxQuantity { get; }
public ConfigEntry<bool> ShowIndicator { get; }
public ConfigEntry<bool> ResetOnShopClose { get; }
public IReadOnlyList<int> Ladder { get; private set; }
public BulkBuyConfig(ConfigFile file)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Expected O, but got Unknown
CycleKey = file.Bind<KeyboardShortcut>("Keys", "CycleKey", new KeyboardShortcut((KeyCode)116, Array.Empty<KeyCode>()), "Cycles the bulk-buy quantity forward. Only active while looking at a bait vendor. Default is T because the game already binds Q to 'drop held item'.");
ReverseModifier = file.Bind<KeyboardShortcut>("Keys", "ReverseModifier", new KeyboardShortcut((KeyCode)116, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Cycles the bulk-buy quantity backward. Checked before CycleKey.");
Quantities = file.Bind<string>("Quantity", "Quantities", "1,5,10,25,50", "Comma-separated quantity ladder to cycle through. Values above MaxQuantity (and above the hard ceiling of " + 50 + ") are clamped on load. Duplicates and junk entries are dropped.");
MaxQuantity = file.Bind<int>("Quantity", "MaxQuantity", 50, new ConfigDescription("Hard ceiling for a single batch. Cannot exceed " + 50 + ".", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
ShowIndicator = file.Bind<bool>("UI", "ShowIndicator", true, "Show the 'Bulk: xN' indicator while looking at a bait vendor.");
ResetOnShopClose = file.Bind<bool>("UI", "ResetOnShopClose", false, "If true, the quantity resets to the first rung of the ladder when you look away from a vendor. If false, it persists.");
Ladder = ParseLadder(Quantities.Value, MaxQuantity.Value);
Quantities.SettingChanged += delegate
{
RebuildLadder();
};
MaxQuantity.SettingChanged += delegate
{
RebuildLadder();
};
}
private void RebuildLadder()
{
Ladder = ParseLadder(Quantities.Value, MaxQuantity.Value);
Plugin.Log.LogInfo((object)("Quantity ladder reloaded: " + string.Join(", ", Ladder)));
}
public static IReadOnlyList<int> ParseLadder(string raw, int maxQuantity)
{
int val = Mathf.Clamp(maxQuantity, 1, 50);
List<int> list = new List<int>();
if (!string.IsNullOrEmpty(raw))
{
string[] array = raw.Split(',');
for (int i = 0; i < array.Length; i++)
{
string text = array[i].Trim();
if (text.Length == 0)
{
continue;
}
if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
Plugin.Log.LogWarning((object)("Ignoring unparseable quantity '" + text + "' in Quantities."));
continue;
}
if (result < 1)
{
Plugin.Log.LogWarning((object)$"Ignoring non-positive quantity '{result}' in Quantities.");
continue;
}
int num = Math.Min(result, val);
if (num != result)
{
Plugin.Log.LogInfo((object)$"Clamped quantity {result} to {num}.");
}
if (!list.Contains(num))
{
list.Add(num);
}
}
}
if (list.Count == 0)
{
Plugin.Log.LogWarning((object)"Quantities produced no usable values; falling back to '1,5,10,25,50'.");
string[] array = "1,5,10,25,50".Split(',');
for (int i = 0; i < array.Length; i++)
{
int item = Math.Min(int.Parse(array[i], CultureInfo.InvariantCulture), val);
if (!list.Contains(item))
{
list.Add(item);
}
}
}
return list;
}
}
internal static class BulkBuyState
{
private const float HoverGraceSeconds = 0.5f;
private static int _ladderIndex;
private static bool _wasHovering;
private static Purchasable _lastSeen;
private static float _lastSeenTime = float.NegativeInfinity;
public static Purchasable Hovered
{
get
{
Player localPlayer = Player.LocalPlayer;
PlayerHolding val = (((Object)(object)localPlayer == (Object)null) ? null : localPlayer.Holding);
Purchasable val2 = (Purchasable)(((Object)(object)val == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
if ((Object)(object)val2 != (Object)null)
{
_lastSeen = val2;
_lastSeenTime = Time.time;
return val2;
}
if ((Object)(object)_lastSeen != (Object)null && Time.time - _lastSeenTime <= 0.5f)
{
return _lastSeen;
}
_lastSeen = null;
return null;
}
}
public static int Quantity
{
get
{
IReadOnlyList<int> ladder = Plugin.Settings.Ladder;
if (ladder.Count == 0)
{
return 1;
}
return ladder[Mathf.Clamp(_ladderIndex, 0, ladder.Count - 1)];
}
}
public static void NoteHoverState(bool hovering)
{
if (_wasHovering && !hovering && Plugin.Settings.ResetOnShopClose.Value && _ladderIndex != 0)
{
_ladderIndex = 0;
Plugin.Log.LogInfo((object)$"Vendor closed - quantity reset to x{Quantity}.");
}
_wasHovering = hovering;
}
public static void Cycle(bool forward)
{
IReadOnlyList<int> ladder = Plugin.Settings.Ladder;
if (ladder.Count != 0)
{
int count = ladder.Count;
_ladderIndex = Mathf.Clamp(_ladderIndex, 0, count - 1);
_ladderIndex = (forward ? ((_ladderIndex + 1) % count) : ((_ladderIndex - 1 + count) % count));
Plugin.Log.LogInfo((object)$"Bulk quantity -> x{Quantity}");
}
}
}
internal static class BulkPurchaseRunner
{
private enum Confirm
{
None,
HeldItem,
VendorState
}
private readonly struct VendorSnapshot
{
private readonly Item _held;
private readonly int _cost;
private readonly bool _canBuy;
private VendorSnapshot(Item held, int cost, bool canBuy)
{
_held = held;
_cost = cost;
_canBuy = canBuy;
}
public static VendorSnapshot Capture(Purchasable purchasable, Player player)
{
PlayerHolding val = (((Object)(object)player == (Object)null) ? null : player.Holding);
return new VendorSnapshot(((Object)(object)val == (Object)null) ? null : val.HeldItem, purchasable._customCost, purchasable._customCanBuy);
}
public bool Matches(VendorSnapshot other, Confirm confirm)
{
switch (confirm)
{
case Confirm.HeldItem:
return _held == other._held;
case Confirm.VendorState:
if (_cost == other._cost)
{
return _canBuy == other._canBuy;
}
return false;
default:
return true;
}
}
}
private const int StallTimeoutFrames = 90;
public static bool Reentrant { get; private set; }
public static bool IsRunning { get; private set; }
public static int Progress { get; private set; }
public static int Target { get; private set; }
public static IEnumerator Run(Purchasable purchasable, Player player, int total)
{
IsRunning = true;
Progress = 1;
Target = total;
AudioSuppressor.BeginBatch();
BaitToastBatcher.BeginBatch();
Confirm confirm = ConfirmFor(purchasable);
int baseline = MoneyManager.Money;
int committed = purchasable._customCost;
int bought = 1;
string stopReason = null;
VendorSnapshot pending = VendorSnapshot.Capture(purchasable, player);
Plugin.Log.LogInfo((object)($"Batch start: {((object)purchasable).GetType().Name} x{total} " + $"(first unit ${committed}, have ${baseline}, confirm by {confirm})."));
for (int i = 1; i < total; i++)
{
if (confirm == Confirm.None)
{
yield return (object)new WaitForFixedUpdate();
}
else
{
bool advanced = false;
for (int f = 0; f < 90; f++)
{
if (advanced)
{
break;
}
yield return (object)new WaitForFixedUpdate();
if ((Object)(object)purchasable == (Object)null || (Object)(object)player == (Object)null)
{
break;
}
TryRefresh(purchasable, ref stopReason);
advanced = !VendorSnapshot.Capture(purchasable, player).Matches(pending, confirm);
}
if (!advanced)
{
stopReason = "the previous purchase did not land";
break;
}
}
if ((Object)(object)purchasable == (Object)null)
{
stopReason = "the vendor went away";
break;
}
if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.LocalPlayer)
{
stopReason = "the player went away";
break;
}
if (!TryRefresh(purchasable, ref stopReason))
{
break;
}
if (!purchasable._customCanBuy)
{
stopReason = "nothing left to buy here";
break;
}
int customCost = purchasable._customCost;
if (customCost > 0 && baseline - committed < customCost)
{
stopReason = "out of money";
break;
}
pending = VendorSnapshot.Capture(purchasable, player);
try
{
Reentrant = true;
((Interactable)purchasable).Interact(player);
}
catch (Exception arg)
{
stopReason = "an error occurred";
Plugin.Log.LogError((object)$"Batch aborted after {bought}/{total}: {arg}");
break;
}
finally
{
Reentrant = false;
}
committed += customCost;
bought = (Progress = bought + 1);
}
RestoreHoverState(purchasable);
AudioSuppressor.EndBatch();
BaitToastBatcher.EndBatch();
IsRunning = false;
Progress = 0;
Target = 0;
yield return (object)new WaitForSeconds(0.5f);
int num2 = baseline - MoneyManager.Money;
if (stopReason == null)
{
Plugin.Log.LogInfo((object)$"Batch result: bought {bought} of {total}, spent ${num2}.");
yield break;
}
Plugin.Log.LogInfo((object)$"Batch result: bought {bought} of {total}, spent ${num2} - {stopReason}.");
}
private static Confirm ConfirmFor(Purchasable purchasable)
{
if (purchasable is BaitPurchasable)
{
return Confirm.None;
}
if (purchasable is ItemPurchasable)
{
return Confirm.HeldItem;
}
return Confirm.VendorState;
}
private static bool TryRefresh(Purchasable purchasable, ref string stopReason)
{
try
{
((Interactable)purchasable).Hover();
return true;
}
catch (Exception ex)
{
stopReason = "the vendor stopped responding";
Plugin.Log.LogDebug((object)("Hover refresh failed: " + ex.Message));
return false;
}
}
private static void RestoreHoverState(Purchasable purchasable)
{
try
{
if (!((Object)(object)purchasable == (Object)null))
{
Player localPlayer = Player.LocalPlayer;
PlayerHolding val = (((Object)(object)localPlayer == (Object)null) ? null : localPlayer.Holding);
if (!((Object)(object)val != (Object)null) || (object)val._interactable != purchasable)
{
((Interactable)purchasable).UnHover();
}
}
}
catch (Exception ex)
{
Plugin.Log.LogDebug((object)("Could not restore hover state: " + ex.Message));
}
}
}
internal sealed class Indicator
{
private const float FontSize = 26f;
private static readonly Vector2 AnchoredPosition = new Vector2(0f, -120f);
private TextMeshProUGUI _text;
private string _shownText;
private bool _loggedCreateFailure;
private bool Ready => (Object)(object)_text != (Object)null;
private bool EnsureCreated()
{
if (Ready)
{
return true;
}
try
{
return Create();
}
catch (Exception ex)
{
if (!_loggedCreateFailure)
{
_loggedCreateFailure = true;
Plugin.Log.LogDebug((object)("Indicator not ready yet, will retry: " + ex.Message));
}
return false;
}
}
private bool Create()
{
//IL_0063: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: 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)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
TextMeshProUGUI canvasTextPrefab = PlayerUI.CanvasTextPrefab;
Transform fXCanvasTrans = PlayerUI.FXCanvasTrans;
if ((Object)(object)canvasTextPrefab == (Object)null || (Object)(object)fXCanvasTrans == (Object)null)
{
return false;
}
_text = Object.Instantiate<TextMeshProUGUI>(canvasTextPrefab, fXCanvasTrans);
((Object)_text).name = "BulkBuyIndicator";
((TMP_Text)_text).fontSize = 26f;
((TMP_Text)_text).alignment = (TextAlignmentOptions)514;
((Graphic)_text).color = GameInfo.GreenColor;
((Graphic)_text).raycastTarget = false;
((TMP_Text)_text).text = string.Empty;
RectTransform rectTransform = ((TMP_Text)_text).rectTransform;
((Transform)rectTransform).localScale = Vector3.one;
((Transform)rectTransform).localRotation = Quaternion.identity;
rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.anchoredPosition = AnchoredPosition;
((Component)_text).gameObject.SetActive(false);
_loggedCreateFailure = false;
Plugin.Log.LogDebug((object)"Indicator created.");
return true;
}
public void Refresh(bool visible, int quantity, int progress, int target)
{
if (!visible)
{
if (Ready && ((Component)_text).gameObject.activeSelf)
{
((Component)_text).gameObject.SetActive(false);
_shownText = null;
}
}
else if (EnsureCreated())
{
string text = ((target > 0) ? $"Bulk: {progress}/{target}" : $"Bulk: x{quantity}");
if (_shownText != text)
{
((TMP_Text)_text).text = text;
_shownText = text;
}
if (!((Component)_text).gameObject.activeSelf)
{
((Component)_text).gameObject.SetActive(true);
}
}
}
public void Destroy()
{
if ((Object)(object)_text != (Object)null)
{
Object.Destroy((Object)(object)((Component)_text).gameObject);
_text = null;
}
_shownText = null;
}
}
[HarmonyPatch]
internal static class PurchasableInteractPatch
{
private static IEnumerable<MethodBase> TargetMethods()
{
List<MethodBase> list = new List<MethodBase>();
Type[] types = typeof(Purchasable).Assembly.GetTypes();
foreach (Type type in types)
{
if (!type.IsAbstract && typeof(Purchasable).IsAssignableFrom(type))
{
MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "Interact", new Type[1] { typeof(Player) }, (Type[])null);
if (methodInfo != null)
{
list.Add(methodInfo);
}
}
}
return list;
}
private static void Postfix(Purchasable __instance, Player player)
{
try
{
if (!BulkPurchaseRunner.Reentrant && !BulkPurchaseRunner.IsRunning)
{
int quantity = BulkBuyState.Quantity;
if (quantity > 1 && !((Object)(object)__instance == (Object)null) && !((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.LocalPlayer) && !((Object)(object)Server.Instance == (Object)null) && __instance._customCanBuy && MoneyManager.CanAfford(__instance._customCost))
{
Plugin.Instance.StartBatch(__instance, player, quantity);
}
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Bulk purchase failed to start: {arg}");
}
}
}
[HarmonyPatch(typeof(AudioManager), "PlayClip", new Type[]
{
typeof(string),
typeof(Vector3),
typeof(float),
typeof(float),
typeof(bool),
typeof(AudioDistance),
typeof(bool),
typeof(string)
})]
internal static class AudioManagerPlayClipPatch
{
[HarmonyPrefix]
private static bool Prefix(string clip, string cooldownKey)
{
try
{
return !AudioSuppressor.ShouldSuppress(string.IsNullOrEmpty(cooldownKey) ? clip : cooldownKey);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Audio suppression failed, passing through: {arg}");
return true;
}
}
}
[HarmonyPatch(typeof(PlayerUI), "OnBaitChange", new Type[]
{
typeof(int),
typeof(bool)
})]
internal static class PlayerUIOnBaitChangePatch
{
[HarmonyPrefix]
private static bool Prefix(int amount, bool increased)
{
try
{
return !BaitToastBatcher.TrySwallow(amount, increased);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Bait toast batching failed, passing through: {arg}");
return true;
}
}
}
[BepInPlugin("com.zoe.howtofish.bulkbuy", "BulkBuy", "1.2.0")]
public sealed class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.zoe.howtofish.bulkbuy";
public const string PluginName = "BulkBuy";
public const string PluginVersion = "1.2.0";
private Harmony _harmony;
private Indicator _indicator;
private bool _loggedUpdateFailure;
internal static ManualLogSource Log { get; private set; }
internal static BulkBuyConfig Settings { get; private set; }
internal static Plugin Instance { get; private set; }
private void Awake()
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
Settings = new BulkBuyConfig(((BaseUnityPlugin)this).Config);
_indicator = new Indicator();
Log.LogInfo((object)("Quantity ladder: " + string.Join(", ", Settings.Ladder)));
Log.LogInfo((object)($"Cycle key: {Settings.CycleKey.Value} (reverse: {Settings.ReverseModifier.Value}). " + "Q is left alone - the game binds it to 'drop held item'."));
_harmony = new Harmony("com.zoe.howtofish.bulkbuy");
_harmony.PatchAll(typeof(Plugin).Assembly);
SceneManager.sceneUnloaded += OnSceneUnloaded;
Log.LogInfo((object)"BulkBuy 1.2.0 loaded.");
}
private void OnDestroy()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
_indicator?.Destroy();
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
Instance = null;
}
private void OnSceneUnloaded(Scene scene)
{
((MonoBehaviour)this).StopAllCoroutines();
_indicator?.Destroy();
BaitToastBatcher.Reset();
AudioSuppressor.EndBatch();
}
internal void StartBatch(Purchasable purchasable, Player player, int quantity)
{
((MonoBehaviour)this).StartCoroutine(BulkPurchaseRunner.Run(purchasable, player, quantity));
}
private void Update()
{
try
{
Tick();
}
catch (Exception arg)
{
if (!_loggedUpdateFailure)
{
_loggedUpdateFailure = true;
Log.LogError((object)$"Update failed (further occurrences suppressed): {arg}");
}
}
}
private void Tick()
{
BaitToastBatcher.Tick();
bool num = (Object)(object)BulkBuyState.Hovered != (Object)null && CanTakeInput();
BulkBuyState.NoteHoverState(num);
if (num && !BulkPurchaseRunner.IsRunning)
{
HandleCycleInput();
}
bool visible = (num || BulkPurchaseRunner.IsRunning) && Settings.ShowIndicator.Value;
_indicator.Refresh(visible, BulkBuyState.Quantity, BulkPurchaseRunner.IsRunning ? BulkPurchaseRunner.Progress : 0, BulkPurchaseRunner.IsRunning ? BulkPurchaseRunner.Target : 0);
}
private static bool CanTakeInput()
{
Player localPlayer = Player.LocalPlayer;
if ((Object)(object)localPlayer != (Object)null && Player.LocalPlayerEnabled && !localPlayer.BlockInputs)
{
return !PauseManager.IsPaused;
}
return false;
}
private static void HandleCycleInput()
{
//IL_000a: 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)
//IL_002a: 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)
KeyboardShortcut value = Settings.ReverseModifier.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
BulkBuyState.Cycle(forward: false);
return;
}
value = Settings.CycleKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
BulkBuyState.Cycle(forward: true);
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}