using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [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("GiveCorrectChange")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GiveCorrectChange")] [assembly: AssemblyTitle("GiveCorrectChange")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 GiveCorrectChange { [BepInPlugin("com.acesgaminguk.givecorrectchange", "GiveCorrectChange", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static Harmony Harmony; internal static ConfigEntry Enabled; internal static ConfigEntry Mode; internal static ConfigEntry ManualHotkey; internal static ConfigEntry PanelX; internal static ConfigEntry PanelY; internal static Data_Container? ActiveCashRegister; internal static bool ManualChangePrepared; internal static float ManualPreparedAt; private Rect _panelRect; private bool _panelPositionLoaded; private GUIStyle? _windowStyle; private GUIStyle? _titleStyle; private GUIStyle? _smallStyle; private GUIStyle? _buttonStyle; private GUIStyle? _dangerButtonStyle; private void Awake() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind("# General #", "Enabled", true, "Enable Give Correct Change."); Mode = ((BaseUnityPlugin)this).Config.Bind("# General #", "Mode", ChangeMode.ManualFill, "ManualFill shows a status panel and uses the hotkey. AutoFill prepares the exact change automatically. AutoComplete immediately completes cash transactions."); ManualHotkey = ((BaseUnityPlugin)this).Config.Bind("# Controls #", "ManualHotkey", new KeyboardShortcut((KeyCode)102, Array.Empty()), "Hotkey used in ManualFill mode to prepare the correct change. Rebind this in the config or BepInEx ConfigurationManager."); PanelX = ((BaseUnityPlugin)this).Config.Bind("# UI #", "PanelX", -1f, "ManualFill panel X position. -1 uses default centered position."); PanelY = ((BaseUnityPlugin)this).Config.Bind("# UI #", "PanelY", -1f, "ManualFill panel Y position. -1 uses default lower-screen position."); ((BaseUnityPlugin)this).Logger.LogWarning((object)"============================================="); ((BaseUnityPlugin)this).Logger.LogMessage((object)string.Format("{0} v{1} Initializing...", "Give Correct Change", ((BaseUnityPlugin)this).Info.Metadata.Version)); ((BaseUnityPlugin)this).Logger.LogWarning((object)"============================================="); ((BaseUnityPlugin)this).Logger.LogMessage((object)"Author: AcesGamingUK"); ((BaseUnityPlugin)this).Logger.LogMessage((object)"GitHub: https://github.com/AcesGamingUK/Give-Correct-Change"); ((BaseUnityPlugin)this).Logger.LogMessage((object)("ManualFill hotkey: " + ((object)ManualHotkey.Value/*cast due to .constrained prefix*/).ToString())); ((BaseUnityPlugin)this).Logger.LogWarning((object)"============================================="); ((BaseUnityPlugin)this).Logger.LogMessage((object)"Give Correct Change Initialized successfully!"); ((BaseUnityPlugin)this).Logger.LogWarning((object)"============================================="); Harmony = new Harmony("com.acesgaminguk.givecorrectchange"); Harmony.PatchAll(); } private void Update() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (Enabled.Value && Mode.Value == ChangeMode.ManualFill && !((Object)(object)ActiveCashRegister == (Object)null)) { KeyboardShortcut value = ManualHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { CorrectChangeHelper.PrepareCorrectChange(ActiveCashRegister, hideManualPrompt: false); } } } private void OnGUI() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 if (Enabled.Value && Mode.Value == ChangeMode.ManualFill && !((Object)(object)ActiveCashRegister == (Object)null)) { EnsureStyles(); EnsurePanelPosition(); _panelRect = GUI.Window(920041, _panelRect, new WindowFunction(DrawManualPanel), GUIContent.none, _windowStyle); if ((int)Event.current.type == 1) { SavePanelPosition(); } } } private void DrawManualPanel(int windowId) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) float moneyToReturn = CorrectChangeHelper.GetMoneyToReturn(ActiveCashRegister); string text = (Object.op_Implicit((Object)(object)ProductListing.Instance) ? ProductListing.Instance.ConvertFloatToTextPrice(moneyToReturn) : ("$" + moneyToReturn.ToString("0.00"))); GUI.Label(new Rect(16f, 10f, ((Rect)(ref _panelRect)).width - 32f, 24f), "Give Correct Change", _titleStyle); GUI.Label(new Rect(16f, 42f, ((Rect)(ref _panelRect)).width - 32f, 24f), "Change due: " + text, _smallStyle); string text2 = (ManualChangePrepared ? "✓ Change Prepared" : ("Press [" + ((object)ManualHotkey.Value/*cast due to .constrained prefix*/).ToString() + "] to prepare change")); GUI.Label(new Rect(16f, 72f, ((Rect)(ref _panelRect)).width - 32f, 30f), text2, _buttonStyle); GUI.Label(new Rect(16f, 113f, ((Rect)(ref _panelRect)).width - 32f, 22f), ManualChangePrepared ? "Click the cash pile on the counter" : "Cash checkout only", _smallStyle); GUI.Label(new Rect(16f, 140f, ((Rect)(ref _panelRect)).width - 32f, 20f), "Mode: ManualFill", _smallStyle); GUI.Label(new Rect(16f, 162f, ((Rect)(ref _panelRect)).width - 32f, 18f), "Hotkey active during checkout", _smallStyle); GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _panelRect)).width, 34f)); } private void EnsurePanelPosition() { //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) if (!_panelPositionLoaded) { float num = 300f; float num2 = 186f; float num3 = ((float)Screen.width - num) / 2f; float num4 = (float)Screen.height - 245f; float num5 = ((PanelX.Value < 0f) ? num3 : PanelX.Value); float num6 = ((PanelY.Value < 0f) ? num4 : PanelY.Value); num5 = Mathf.Clamp(num5, 0f, Mathf.Max(0f, (float)Screen.width - num)); num6 = Mathf.Clamp(num6, 0f, Mathf.Max(0f, (float)Screen.height - num2)); _panelRect = new Rect(num5, num6, num, num2); _panelPositionLoaded = true; } } private void SavePanelPosition() { if (_panelPositionLoaded) { float num = Mathf.Round(((Rect)(ref _panelRect)).x); float num2 = Mathf.Round(((Rect)(ref _panelRect)).y); if (Mathf.Abs(PanelX.Value - num) > 0.5f) { PanelX.Value = num; } if (Mathf.Abs(PanelY.Value - num2) > 0.5f) { PanelY.Value = num2; } } } private void EnsureStyles() { //IL_001d: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00c4: 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_00d3: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Expected O, but got Unknown if (_windowStyle == null) { Texture2D background = MakeTexture(new Color(0.04f, 0.04f, 0.04f, 0.92f)); Texture2D background2 = MakeTexture(new Color(0.13f, 0.38f, 0.2f, 0.95f)); Texture2D background3 = MakeTexture(new Color(0.18f, 0.5f, 0.28f, 0.95f)); Texture2D background4 = MakeTexture(new Color(0.22f, 0.16f, 0.1f, 0.95f)); Texture2D background5 = MakeTexture(new Color(0.34f, 0.24f, 0.14f, 0.95f)); GUIStyle val = new GUIStyle(GUI.skin.window) { padding = new RectOffset(0, 0, 0, 0), border = new RectOffset(8, 8, 8, 8) }; val.normal.background = background; _windowStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 17, fontStyle = (FontStyle)1 }; val2.normal.textColor = new Color(1f, 0.72f, 0.22f, 1f); _titleStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 13 }; val3.normal.textColor = Color.white; _smallStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.button) { alignment = (TextAnchor)4, fontSize = 14, fontStyle = (FontStyle)1 }; val4.normal.background = background2; val4.normal.textColor = Color.white; val4.hover.background = background3; val4.hover.textColor = Color.white; val4.active.background = background3; val4.active.textColor = Color.white; _buttonStyle = val4; GUIStyle val5 = new GUIStyle(GUI.skin.button) { alignment = (TextAnchor)4, fontSize = 12 }; val5.normal.background = background4; val5.normal.textColor = Color.white; val5.hover.background = background5; val5.hover.textColor = Color.white; val5.active.background = background5; val5.active.textColor = Color.white; _dangerButtonStyle = val5; } } private static Texture2D MakeTexture(Color color) { //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) //IL_000a: 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) //IL_0017: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, color); val.Apply(); return val; } private void OnDestroy() { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public enum ChangeMode { ManualFill, AutoFill, AutoComplete } internal static class CorrectChangeHelper { private static readonly FieldInfo MoneyToReturnField = AccessTools.Field(typeof(Data_Container), "moneyToReturn"); private static readonly FieldInfo CurrentAmountToReturnField = AccessTools.Field(typeof(Data_Container), "currentAmountToReturn"); private static readonly FieldInfo AllowMoneyReturnField = AccessTools.Field(typeof(Data_Container), "allowMoneyReturn"); internal static bool FieldsReady() { if (MoneyToReturnField != null && CurrentAmountToReturnField != null && AllowMoneyReturnField != null) { return true; } Plugin.Log.LogError((object)"Could not find one or more checkout fields. Game update may have changed Data_Container."); return false; } internal static float GetMoneyToReturn(Data_Container container) { if (!FieldsReady()) { return 0f; } return Mathf.Round((float)MoneyToReturnField.GetValue(container) * 100f) / 100f; } internal static void PrepareCorrectChange(Data_Container container, bool hideManualPrompt) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) try { if (!Plugin.Enabled.Value || !FieldsReady()) { return; } float moneyToReturn = GetMoneyToReturn(container); if (moneyToReturn < 0f) { return; } CurrentAmountToReturnField.SetValue(container, moneyToReturn); AllowMoneyReturnField.SetValue(container, true); Transform val = ((Component)container).transform.Find("CashRegisterCanvas/Container/CurrentAmount"); if (Object.op_Implicit((Object)(object)val)) { TextMeshProUGUI component = ((Component)val).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { ((TMP_Text)component).text = ProductListing.Instance.ConvertFloatToTextPrice(moneyToReturn); ((Graphic)component).color = Color.green; } } Transform val2 = ((Component)container).transform.Find("CashRegister/MoneyGivenBack"); if (Object.op_Implicit((Object)(object)val2)) { ((Component)val2).gameObject.SetActive(true); } if ((Object)(object)Plugin.ActiveCashRegister == (Object)(object)container) { Plugin.ManualChangePrepared = true; Plugin.ManualPreparedAt = Time.realtimeSinceStartup; } if (hideManualPrompt && (Object)(object)Plugin.ActiveCashRegister == (Object)(object)container) { Plugin.ActiveCashRegister = null; } } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to prepare correct change: " + ex)); } } } [HarmonyPatch(typeof(Data_Container), "UserCode_RpcHidePaymentMethod__Int32__Int32")] internal static class DataContainer_RpcHidePaymentMethod_Patch { private static void Postfix(Data_Container __instance, int index, int amountGiven) { if (!Plugin.Enabled.Value || index != 0) { return; } try { if (CorrectChangeHelper.FieldsReady() && !(CorrectChangeHelper.GetMoneyToReturn(__instance) < 0f)) { if (Plugin.Mode.Value == ChangeMode.AutoComplete) { Plugin.ActiveCashRegister = null; Plugin.ManualChangePrepared = false; __instance.CmdReceivePayment(0f); } else if (Plugin.Mode.Value == ChangeMode.AutoFill) { Plugin.ActiveCashRegister = null; Plugin.ManualChangePrepared = false; CorrectChangeHelper.PrepareCorrectChange(__instance, hideManualPrompt: true); } else { Plugin.ManualChangePrepared = false; Plugin.ManualPreparedAt = 0f; Plugin.ActiveCashRegister = __instance; } } } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to set up manual correct change: " + ex)); } } } [HarmonyPatch(typeof(Data_Container), "UserCode_CmdReceivePayment__Single")] internal static class DataContainer_CmdReceivePayment_Patch { private static void Prefix(Data_Container __instance, ref float returnDifference) { if (!Plugin.Enabled.Value) { return; } try { if (Plugin.Mode.Value == ChangeMode.AutoFill || Plugin.Mode.Value == ChangeMode.ManualFill) { float moneyToReturn = CorrectChangeHelper.GetMoneyToReturn(__instance); if (Mathf.Abs(__instance.currentAmountToReturn - moneyToReturn) <= 0.011f) { returnDifference = 0f; } } } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to normalize return difference: " + ex)); } } private static void Postfix(Data_Container __instance) { if ((Object)(object)Plugin.ActiveCashRegister == (Object)(object)__instance) { Plugin.ActiveCashRegister = null; Plugin.ManualChangePrepared = false; Plugin.ManualPreparedAt = 0f; } } } internal static class PluginInfo { public const string Guid = "com.acesgaminguk.givecorrectchange"; public const string Name = "GiveCorrectChange"; public const string DisplayName = "Give Correct Change"; public const string Version = "1.0.0"; public const string Author = "AcesGamingUK"; public const string Website = "https://github.com/AcesGamingUK/Give-Correct-Change"; } }