using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using MyBox; using System; using System.Collections.Generic; using System.Reflection.Emit; using TMPro; using UnityEngine; using UnityEngine.TextCore.Text; namespace ChangeCurrency { [BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] public class Plugin : BaseUnityPlugin { public static ManualLogSource StaticLogger; public static ConfigEntry CurrencyPrefix; public static ConfigEntry CurrencySuffix; public static ConfigEntry CurrencyDecimalSeperator; public static ConfigEntry CoinValue1ct; public static ConfigEntry CoinValue5ct; public static ConfigEntry CoinValue10ct; public static ConfigEntry CoinValue25ct; public static ConfigEntry CoinValue50ct; public static ConfigEntry BillValue1d; public static ConfigEntry BillValue5d; public static ConfigEntry BillValue10d; public static ConfigEntry BillValue20d; public static ConfigEntry BillValue50d; public static ConfigEntry LowestBill; public static ConfigEntry TerminalSymbol; public static ConfigEntry ValueText1ct; public static ConfigEntry ValueText5ct; public static ConfigEntry ValueText10ct; public static ConfigEntry ValueText25ct; public static ConfigEntry ValueText50ct; public static ConfigEntry ValueText1d; public static ConfigEntry ValueText5d; public static ConfigEntry ValueText10d; public static ConfigEntry ValueText20d; public static ConfigEntry ValueText50d; public static ConfigEntry Texture1ct; public static ConfigEntry Texture5ct; public static ConfigEntry Texture10ct; public static ConfigEntry Texture25ct; public static ConfigEntry Texture50ct; public static ConfigEntry Texture1d; public static ConfigEntry Texture5d; public static ConfigEntry Texture10d; public static ConfigEntry Texture20d; public static ConfigEntry Texture50d; private void Awake() { StaticLogger = Logger; InitConfig(); Logger.LogInfo($"Plugin {PluginInfo.PLUGIN_GUID} is loaded! Applying patch..."); Harmony harmony = new Harmony(PluginInfo.PLUGIN_GUID); harmony.PatchAll(); } public enum MoneyType { CENT_1 = 0b0001, CENT_5 = 0b0010, CENT_10 = 0b0011, CENT_25 = 0b0100, CENT_50 = 0b0101, DOLLAR_1 = 0b1001, DOLLAR_5 = 0b1010, DOLLAR_10 = 0b1011, DOLLAR_20 = 0b1100, DOLLAR_50 = 0b1101 } public enum TextureType { USD, EUR, GBP, SGD, CAD } public static void ApplyMoneyTexture(MoneyType type, CheckoutDrawer instance, int instanceIndex, int prefabIndex) { var tex = GetMoneyTexture(type); if (tex == null) return; instance.gameObject.transform.GetChild(instanceIndex).GetChild(0).GetChild(0).GetComponentsInChildren().ForEach(x => x.sharedMaterials.ForEach(y => y.mainTexture = tex)); Singleton.Instance.m_MoneyPrefabs[prefabIndex].GetComponent().sharedMaterials.ForEach(x => x.mainTexture = tex); } private static Texture2D GetMoneyTexture(MoneyType type) { bool isBill = (((int)type) & 0b1000) == 0b1000; Texture2D tex = new Texture2D(isBill ? 2048 : 1024, 1024); var bytes = GetMoneyTextureBytes(type); if (bytes == null) return null; tex.LoadImage(bytes); tex.Apply(); return tex; } private static byte[] GetMoneyTextureBytes(MoneyType type) { switch (type) { default: case MoneyType.CENT_1: switch (Texture1ct.Value) { case TextureType.EUR: return Properties.Resources.eur_1; case TextureType.GBP: return Properties.Resources.gbp_1; case TextureType.SGD: return Properties.Resources.sgd_1; case TextureType.CAD: return Properties.Resources.cad_1; case TextureType.USD: default: return null; } case MoneyType.CENT_5: switch (Texture5ct.Value) { case TextureType.EUR: return Properties.Resources.eur_5; case TextureType.GBP: return Properties.Resources.gbp_5; case TextureType.SGD: return Properties.Resources.sgd_5; case TextureType.CAD: return Properties.Resources.cad_5; case TextureType.USD: default: return null; } case MoneyType.CENT_10: switch (Texture10ct.Value) { case TextureType.EUR: return Properties.Resources.eur_10; case TextureType.GBP: return Properties.Resources.gbp_10; case TextureType.SGD: return Properties.Resources.sgd_20; case TextureType.CAD: return Properties.Resources.cad_10; case TextureType.USD: default: return null; } case MoneyType.CENT_25: switch (Texture25ct.Value) { case TextureType.EUR: return Properties.Resources.eur_20; case TextureType.GBP: return Properties.Resources.gbp_20; case TextureType.SGD: return Properties.Resources.sgd_50; case TextureType.CAD: return Properties.Resources.cad_25; case TextureType.USD: default: return null; } case MoneyType.CENT_50: switch (Texture50ct.Value) { case TextureType.EUR: return Properties.Resources.eur_50; case TextureType.GBP: return Properties.Resources.gbp_50; case TextureType.SGD: return Properties.Resources.sgd1; case TextureType.CAD: return Properties.Resources.cad_50; case TextureType.USD: default: return null; } case MoneyType.DOLLAR_1: switch (Texture1d.Value) { case TextureType.EUR: return Properties.Resources.eur1; case TextureType.GBP: return Properties.Resources.gbp1; case TextureType.SGD: return Properties.Resources.sgd2; case TextureType.CAD: return Properties.Resources.cad1; case TextureType.USD: default: return null; } case MoneyType.DOLLAR_5: switch (Texture5d.Value) { case TextureType.EUR: return Properties.Resources.eur5; case TextureType.GBP: return Properties.Resources.gbp5; case TextureType.SGD: return Properties.Resources.sgd5; case TextureType.CAD: return Properties.Resources.cad5; case TextureType.USD: default: return null; } case MoneyType.DOLLAR_10: switch (Texture10d.Value) { case TextureType.EUR: return Properties.Resources.eur10; case TextureType.GBP: return Properties.Resources.gbp10; case TextureType.SGD: return Properties.Resources.sgd10; case TextureType.CAD: return Properties.Resources.cad10; case TextureType.USD: default: return null; } case MoneyType.DOLLAR_20: switch (Texture20d.Value) { case TextureType.EUR: return Properties.Resources.eur20; case TextureType.GBP: return Properties.Resources.gbp20; case TextureType.SGD: return Properties.Resources.sgd20; case TextureType.CAD: return Properties.Resources.cad20; case TextureType.USD: default: return null; } case MoneyType.DOLLAR_50: switch (Texture50d.Value) { case TextureType.EUR: return Properties.Resources.eur50; case TextureType.GBP: return Properties.Resources.gbp50; case TextureType.SGD: return Properties.Resources.sgd50; case TextureType.CAD: return Properties.Resources.cad50; case TextureType.USD: default: return null; } } } private void InitConfig() { CurrencyPrefix = Config.Bind("Money Text", "Prefix", "$", "The currency symbol (or arbitrary string) to use in front of the value, where the dollar sign would normally be."); CurrencySuffix = Config.Bind("Money Text", "Suffix", "", "The currency symbol (or arbitrary string) to use after the value, where a euro sign might for example be."); CurrencyDecimalSeperator = Config.Bind("Money Text", "Decimal Seperator", ".", "What symbol to use to seperate the whole number part from the fractional part."); CoinValue1ct = Config.Bind("Cash Values", "1 Cent Coin", 0.01f, "What cash value the 1 cent coin should represent."); CoinValue5ct = Config.Bind("Cash Values", "5 Cent Coin", 0.05f, "What cash value the 5 cent coin should represent."); CoinValue10ct = Config.Bind("Cash Values", "10 Cent Coin", 0.1f, "What cash value the 10 cent coin should represent."); CoinValue25ct = Config.Bind("Cash Values", "25 Cent Coin", 0.25f, "What cash value the 25 cent coin should represent."); CoinValue50ct = Config.Bind("Cash Values", "50 Cent Coin", 0.5f, "What cash value the 50 cent coin should represent."); BillValue1d = Config.Bind("Cash Values", "1 Dollar Bill", 1f, "What cash value the 1 dollar bill should represent."); BillValue5d = Config.Bind("Cash Values", "5 Dollar Bill", 5f, "What cash value the 5 dollar bill should represent."); BillValue10d = Config.Bind("Cash Values", "10 Dollar Bill", 10f, "What cash value the 10 dollar bill should represent."); BillValue20d = Config.Bind("Cash Values", "20 Dollar Bill", 20f, "What cash value the 20 dollar bill should represent."); BillValue50d = Config.Bind("Cash Values", "50 Dollar Bill", 50f, "What cash value the 50 dollar bill should represent."); ValueText1ct = Config.Bind("Value Texts", "1 Cent Coin", "1¢", "What value text to display below the 1 cent coin."); ValueText5ct = Config.Bind("Value Texts", "5 Cent Coin", "5¢", "What value text to display below the 5 cent coin."); ValueText10ct = Config.Bind("Value Texts", "10 Cent Coin", "10¢", "What value text to display below the 10 cent coin."); ValueText25ct = Config.Bind("Value Texts", "25 Cent Coin", "25¢", "What value text to display below the 25 cent coin."); ValueText50ct = Config.Bind("Value Texts", "50 Cent Coin", "50¢", "What value text to display below the 50 cent coin."); ValueText1d = Config.Bind("Value Texts", "1 Dollar Bill", "$1", "What value text to display above the 1 dollar bill."); ValueText5d = Config.Bind("Value Texts", "5 Dollar Bill", "$5", "What value text to display above the 5 dollar bill."); ValueText10d = Config.Bind("Value Texts", "10 Dollar Bill", "$10", "What value text to display above the 10 dollar bill."); ValueText20d = Config.Bind("Value Texts", "20 Dollar Bill", "$20", "What value text to display above the 20 dollar bill."); ValueText50d = Config.Bind("Value Texts", "50 Dollar Bill", "$50", "What value text to display above the 50 dollar bill."); Texture1ct = Config.Bind("Texture Types", "1 Cent Coin", TextureType.USD, "What visual style this coin should have."); Texture5ct = Config.Bind("Texture Types", "5 Cent Coin", TextureType.USD, "What visual style this coin should have."); Texture10ct = Config.Bind("Texture Types", "10 Cent Coin", TextureType.USD, "What visual style this coin should have."); Texture25ct = Config.Bind("Texture Types", "25 Cent Coin", TextureType.USD, "What visual style this coin should have."); Texture50ct = Config.Bind("Texture Types", "50 Cent Coin", TextureType.USD, "What visual style this coin should have."); Texture1d = Config.Bind("Texture Types", "1 Dollar Bill", TextureType.USD, "What visual style this bill should have."); Texture5d = Config.Bind("Texture Types", "5 Dollar Bill", TextureType.USD, "What visual style this bill should have."); Texture10d = Config.Bind("Texture Types", "10 Dollar Bill", TextureType.USD, "What visual style this bill should have."); Texture20d = Config.Bind("Texture Types", "20 Dollar Bill", TextureType.USD, "What visual style this bill should have."); Texture50d = Config.Bind("Texture Types", "50 Dollar Bill", TextureType.USD, "What visual style this bill should have."); LowestBill = Config.Bind("Miscellaneous", "Lowest Bill", 1f, "The lowest value of money that should be considered a bill by the game."); TerminalSymbol = Config.Bind("Miscellaneous", "Terminal Symbol", "$", "What symbol to display on the credit card terminal."); } } public static class CheckoutDrawerPatch { [HarmonyPatch(typeof(CheckoutChangeManager), "SpawnMoney")] public static class CheckoutChangeManager_SpawnMoney_Patch { public static void Prefix(bool isCoin) => Plugin.StaticLogger.LogWarning(isCoin); } [HarmonyPatch(typeof(CheckoutChangeManager), "AddOrRemoveMoney")] public static class CheckoutChangeManager_AddOrRemoveMoney_Patch { public static IEnumerable Transpiler(IEnumerable instructions) { foreach (var instruction in instructions) { // Check if the instruction loads the constant 1f onto the stack if (instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 1f) { // Replace the constant 1f with your desired value (e.g., 2f) yield return new CodeInstruction(OpCodes.Ldc_R4, Plugin.LowestBill.Value); } else { yield return instruction; } } } } [HarmonyPatch(typeof(PosTerminal), "Start")] public static class PosTerminal_Start_Patch { public static void Postfix(PosTerminal __instance) { string p = Plugin.TerminalSymbol.Value; __instance.gameObject.transform.GetChild(2).GetChild(2).GetChild(1).GetComponent().text = p; } } [HarmonyPatch(typeof(CheckoutDrawer), "Awake")] public static class CheckoutDrawer_Awake_Patch { public static void Postfix(CheckoutDrawer __instance) { void UpdateText(TextMeshProUGUI text, string newText) { text.text = newText; text.enableWordWrapping = false; text.gameObject.SetActive(false); text.gameObject.SetActive(true); } __instance.gameObject.transform.GetChild(6).GetComponent().Value = Plugin.CoinValue1ct.Value; // $0.01 __instance.gameObject.transform.GetChild(7).GetComponent().Value = Plugin.CoinValue5ct.Value; // $0.05 __instance.gameObject.transform.GetChild(8).GetComponent().Value = Plugin.CoinValue10ct.Value; // $0.10 __instance.gameObject.transform.GetChild(9).GetComponent().Value = Plugin.CoinValue25ct.Value; // $0.25 __instance.gameObject.transform.GetChild(10).GetComponent().Value = Plugin.CoinValue50ct.Value; // $0.50 __instance.gameObject.transform.GetChild(1).GetComponent().Value = Plugin.BillValue1d.Value; // $1.00 __instance.gameObject.transform.GetChild(2).GetComponent().Value = Plugin.BillValue5d.Value; // $5.00 __instance.gameObject.transform.GetChild(3).GetComponent().Value = Plugin.BillValue10d.Value; // $10.00 __instance.gameObject.transform.GetChild(4).GetComponent().Value = Plugin.BillValue20d.Value; // $20.00 __instance.gameObject.transform.GetChild(5).GetComponent().Value = Plugin.BillValue50d.Value; // $50.00 UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(5).GetComponent(), Plugin.ValueText1ct.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(6).GetComponent(), Plugin.ValueText5ct.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(7).GetComponent(), Plugin.ValueText10ct.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(8).GetComponent(), Plugin.ValueText25ct.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(9).GetComponent(), Plugin.ValueText50ct.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(0).GetComponent(), Plugin.ValueText1d.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(1).GetComponent(), Plugin.ValueText5d.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(2).GetComponent(), Plugin.ValueText10d.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(3).GetComponent(), Plugin.ValueText20d.Value); UpdateText(__instance.gameObject.transform.GetChild(11).GetChild(4).GetComponent(), Plugin.ValueText50d.Value); Singleton.Instance.m_MoneyPrefabs[0].Value = Plugin.CoinValue1ct.Value; Singleton.Instance.m_MoneyPrefabs[1].Value = Plugin.CoinValue5ct.Value; Singleton.Instance.m_MoneyPrefabs[2].Value = Plugin.CoinValue10ct.Value; Singleton.Instance.m_MoneyPrefabs[3].Value = Plugin.CoinValue25ct.Value; Singleton.Instance.m_MoneyPrefabs[4].Value = Plugin.CoinValue50ct.Value; Singleton.Instance.m_MoneyPrefabs[5].Value = Plugin.BillValue1d.Value; Singleton.Instance.m_MoneyPrefabs[6].Value = Plugin.BillValue5d.Value; Singleton.Instance.m_MoneyPrefabs[7].Value = Plugin.BillValue10d.Value; Singleton.Instance.m_MoneyPrefabs[8].Value = Plugin.BillValue20d.Value; Singleton.Instance.m_MoneyPrefabs[9].Value = Plugin.BillValue50d.Value; Plugin.ApplyMoneyTexture(Plugin.MoneyType.DOLLAR_1, __instance, 1, 5); Plugin.ApplyMoneyTexture(Plugin.MoneyType.DOLLAR_5, __instance, 2, 6); Plugin.ApplyMoneyTexture(Plugin.MoneyType.DOLLAR_10, __instance, 3, 7); Plugin.ApplyMoneyTexture(Plugin.MoneyType.DOLLAR_20, __instance, 4, 8); Plugin.ApplyMoneyTexture(Plugin.MoneyType.DOLLAR_50, __instance, 5, 9); Plugin.ApplyMoneyTexture(Plugin.MoneyType.CENT_1, __instance, 6, 0); Plugin.ApplyMoneyTexture(Plugin.MoneyType.CENT_5, __instance, 7, 1); Plugin.ApplyMoneyTexture(Plugin.MoneyType.CENT_10, __instance, 8, 2); Plugin.ApplyMoneyTexture(Plugin.MoneyType.CENT_25, __instance, 9, 3); Plugin.ApplyMoneyTexture(Plugin.MoneyType.CENT_50, __instance, 10, 4); } } } public static class MoneySymbolPatch { [HarmonyPatch(typeof(Extensions), "ToMoneyText")] public static class Extensions_ToMoneyText_Patch { public static void Postfix(ref string __result, ref float money, ref float fontSize) { string p = Plugin.CurrencyPrefix.Value; string s = Plugin.CurrencySuffix.Value; string d = Plugin.CurrencyDecimalSeperator.Value; string text; if (money < 0f) { text = "-$" + Math.Abs((float)Math.Round((double)money, 2)).ToString("0.00"); } else { text = "$" + ((float)Math.Round((double)money, 2)).ToString("0.00"); } text = text.Replace(',', '.'); text = text.Replace(".", d); text = text.Replace("$", p); text = text + s; int num = text.IndexOf(d); if (num != -1) { string text2 = ""; text2 = text2.Replace(',', '.'); text = text.Insert(num + 1, text2); } __result = text; } } } }