Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ShopDiscounts v1.0.3
ShopDiscounts.dll
Decompiled 21 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ShopDiscounts")] [assembly: AssemblyDescription("Mod for to get random Discounts on Items in the R.E.P.O. Shop! Developed by Jettcodey.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jettcodey")] [assembly: AssemblyProduct("ShopDiscounts")] [assembly: AssemblyCopyright("Copyright © Jettcodey 2026")] [assembly: ComVisible(false)] [assembly: Guid("49136d56-4387-44af-acca-43a6ca0714ce")] [assembly: AssemblyFileVersion("1.0.3")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.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 ShopDiscounts { public static class ConfigManager { public static ConfigEntry<bool> UseCustomDiscount; public static ConfigEntry<int> CustomDiscountValue; public static ConfigEntry<int> ChanceNoDiscount; public static ConfigEntry<int> ChanceLowDiscount; public static ConfigEntry<int> ChanceMediumDiscount; public static ConfigEntry<int> ChanceHighDiscount; public static ConfigEntry<int> ChanceMaxDiscount; public static ConfigEntry<int> ChanceUltraDiscount; public static ConfigEntry<int> ChanceLegendaryDiscount; public static void Init(ConfigFile config) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown UseCustomDiscount = config.Bind<bool>("Custom Discount", "Enable Custom Discount", false, "Skip rolling and just use a fixed discount."); CustomDiscountValue = config.Bind<int>("Custom Discount", "Discount Percentage", 0, new ConfigDescription("Fixed discount % to apply.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ChanceNoDiscount = config.Bind<int>("Chances", "0% Discount Chance", 5, new ConfigDescription("Weight for no discount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ChanceLowDiscount = config.Bind<int>("Chances", "1-10% Discount Chance", 40, new ConfigDescription("Weight for small discount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ChanceMediumDiscount = config.Bind<int>("Chances", "11-25% Discount Chance", 25, new ConfigDescription("Weight for medium discount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ChanceHighDiscount = config.Bind<int>("Chances", "26-45% Discount Chance", 15, new ConfigDescription("Weight for high discount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ChanceMaxDiscount = config.Bind<int>("Chances", "46-65% Discount Chance", 10, new ConfigDescription("Weight for max discount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ChanceUltraDiscount = config.Bind<int>("Chances", "66-85% Discount Chance", 4, new ConfigDescription("Weight for ultra discount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ChanceLegendaryDiscount = config.Bind<int>("Chances", "86-100% Discount Chance", 1, new ConfigDescription("Weight for legendary discount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); } } internal static class DiscountEvents { public const byte EV_DISCOUNT_ROLLED = 156; public static void RaiseDiscountRolled(int pct) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0030: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom) { ManualLogSource logger = Plugin.Logger; if (logger != null) { logger.LogInfo((object)"Not in a room, So Maybe SP or Internet died lol"); } return; } RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; PhotonNetwork.RaiseEvent((byte)156, (object)new object[1] { pct }, val, SendOptions.SendReliable); ManualLogSource logger2 = Plugin.Logger; if (logger2 != null) { logger2.LogInfo((object)$"sent {pct}% discount to clients"); } } } internal class DiscountEventListener : MonoBehaviourPunCallbacks, IOnEventCallback { private static bool _created; public static void Ensure() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown if (!_created) { _created = true; GameObject val = new GameObject("ShopDiscounts_EventListener"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<DiscountEventListener>(); ManualLogSource logger = Plugin.Logger; if (logger != null) { logger.LogInfo((object)"Discount event listener ready."); } } } public override void OnJoinedRoom() { DiscountManager.ResetDiscount(); } public override void OnLeftRoom() { DiscountManager.ResetDiscount(); } public void OnEvent(EventData photonEvent) { if (photonEvent.Code == 156 && photonEvent.CustomData is object[] array && array.Length >= 1) { int num = (int)array[0]; DiscountManager.ReceiveDiscount(num); ManualLogSource logger = Plugin.Logger; if (logger != null) { logger.LogInfo((object)$"Got discount from host: {num}%"); } } } } public static class DiscountManager { private static readonly Dictionary<ItemAttributes, int> _originalPrices = new Dictionary<ItemAttributes, int>(); public static int CurrentDiscount { get; internal set; } public static bool IsDiscountSynced { get; private set; } public static void RollDiscount() { if (ConfigManager.UseCustomDiscount.Value) { CurrentDiscount = Mathf.Clamp(ConfigManager.CustomDiscountValue.Value, 0, 100); IsDiscountSynced = true; ManualLogSource logger = Plugin.Logger; if (logger != null) { logger.LogInfo((object)$"Custom discount set to {CurrentDiscount}%"); } return; } int value = ConfigManager.ChanceNoDiscount.Value; int value2 = ConfigManager.ChanceLowDiscount.Value; int value3 = ConfigManager.ChanceMediumDiscount.Value; int value4 = ConfigManager.ChanceHighDiscount.Value; int value5 = ConfigManager.ChanceMaxDiscount.Value; int value6 = ConfigManager.ChanceUltraDiscount.Value; int value7 = ConfigManager.ChanceLegendaryDiscount.Value; int num = value + value2 + value3 + value4 + value5 + value6 + value7; if (num <= 0) { CurrentDiscount = 0; IsDiscountSynced = true; ManualLogSource logger2 = Plugin.Logger; if (logger2 != null) { logger2.LogWarning((object)"All discount weights are 0, defaulting to no discount"); } return; } int num2 = Random.Range(0, num); if (num2 < value) { CurrentDiscount = 0; } else if (num2 < value + value2) { CurrentDiscount = Random.Range(1, 11); } else if (num2 < value + value2 + value3) { CurrentDiscount = Random.Range(11, 26); } else if (num2 < value + value2 + value3 + value4) { CurrentDiscount = Random.Range(26, 46); } else if (num2 < value + value2 + value3 + value4 + value5) { CurrentDiscount = Random.Range(46, 66); } else if (num2 < value + value2 + value3 + value4 + value5 + value6) { CurrentDiscount = Random.Range(66, 86); } else { CurrentDiscount = Random.Range(86, 101); } IsDiscountSynced = true; ManualLogSource logger3 = Plugin.Logger; if (logger3 != null) { logger3.LogInfo((object)$"rolled {CurrentDiscount}% shop discount"); } } public static void SyncToClients() { if (SemiFunc.IsMasterClientOrSingleplayer()) { if (PhotonNetwork.IsConnected && PhotonNetwork.InRoom) { DiscountEvents.RaiseDiscountRolled(CurrentDiscount); } else { ApplyDiscountToAllItems(); } } } public static void ReceiveDiscount(int discount) { CurrentDiscount = discount; IsDiscountSynced = true; ApplyDiscountToAllItems(); } public static void ResetDiscount() { CurrentDiscount = 0; IsDiscountSynced = false; _originalPrices.Clear(); } public static void ApplyDiscountToItem(ItemAttributes item) { if ((Object)(object)item == (Object)null || CurrentDiscount <= 0 || _originalPrices.ContainsKey(item)) { return; } _originalPrices[item] = item.value; int num = Mathf.RoundToInt((float)item.value * (1f - (float)CurrentDiscount / 100f)); if (num < 1 && item.value > 0) { num = 1; } item.value = num; if (SemiFunc.IsMasterClientOrSingleplayer()) { PhotonView component = ((Component)item).GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null && PhotonNetwork.IsConnected) { component.RPC("GetValueRPC", (RpcTarget)1, new object[1] { num }); } } } public static void RestoreItemPrice(ItemAttributes item) { if ((Object)(object)item == (Object)null || !_originalPrices.TryGetValue(item, out var value)) { return; } item.value = value; _originalPrices.Remove(item); if (SemiFunc.IsMasterClientOrSingleplayer()) { PhotonView component = ((Component)item).GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null && PhotonNetwork.IsConnected) { component.RPC("GetValueRPC", (RpcTarget)1, new object[1] { value }); } } } public static void ApplyDiscountToAllItems() { if (CurrentDiscount <= 0) { return; } foreach (ItemAttributes shopping in ShopManager.instance.shoppingList) { ApplyDiscountToItem(shopping); } } public static void RestoreAllItemPrices() { foreach (KeyValuePair<ItemAttributes, int> originalPrice in _originalPrices) { if ((Object)(object)originalPrice.Key == (Object)null) { continue; } originalPrice.Key.value = originalPrice.Value; if (SemiFunc.IsMasterClientOrSingleplayer()) { PhotonView component = ((Component)originalPrice.Key).GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null && PhotonNetwork.IsConnected) { component.RPC("GetValueRPC", (RpcTarget)1, new object[1] { originalPrice.Value }); } } } _originalPrices.Clear(); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Jettcodey.ShopDiscounts"; public const string PLUGIN_NAME = "Shop Discounts"; public const string PLUGIN_VERSION = "1.0.3"; } [BepInPlugin("Jettcodey.ShopDiscounts", "Shop Discounts", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private Harmony _harmony; public static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; ConfigManager.Init(((BaseUnityPlugin)this).Config); _harmony = new Harmony("Jettcodey.ShopDiscounts"); _harmony.PatchAll(); SceneManager.sceneLoaded += OnFirstScene; Logger.LogInfo((object)"Plugin Shop Discounts v1.0.3 loaded successfully."); } private void OnFirstScene(Scene scene, LoadSceneMode mode) { DiscountEventListener.Ensure(); SceneManager.sceneLoaded -= OnFirstScene; } } } namespace ShopDiscounts.Patches { [HarmonyPatch(typeof(ExtractionPoint))] public class ExtractionPointPatches { [HarmonyPostfix] [HarmonyPatch("SetHaulText")] public static void AddDiscountTextToScreen(ExtractionPoint __instance) { if (SemiFunc.RunIsShop()) { int currentDiscount = DiscountManager.CurrentDiscount; if (currentDiscount > 0 && !((TMP_Text)__instance.haulGoalScreen).text.Contains("(-")) { TextMeshPro haulGoalScreen = __instance.haulGoalScreen; ((TMP_Text)haulGoalScreen).text = ((TMP_Text)haulGoalScreen).text + $" <color=green>(-{currentDiscount}%)</color>"; } } } [HarmonyPostfix] [HarmonyPatch("DestroyAllPhysObjectsInShoppingList")] public static void RevertItemPrices() { if (SemiFunc.RunIsShop()) { DiscountManager.RestoreAllItemPrices(); } } } [HarmonyPatch(typeof(ShopManager))] public class ShopManagerPatches { [HarmonyPostfix] [HarmonyPatch("ShopInitialize")] public static void GenerateDiscountOnLoad() { if (SemiFunc.RunIsShop() && SemiFunc.IsMasterClientOrSingleplayer()) { DiscountManager.RollDiscount(); DiscountManager.SyncToClients(); } } [HarmonyPrefix] [HarmonyPatch("ShoppingListItemAdd")] public static void OnItemAdded(ItemAttributes item) { if (SemiFunc.RunIsShop() && DiscountManager.IsDiscountSynced) { DiscountManager.ApplyDiscountToItem(item); } } [HarmonyPrefix] [HarmonyPatch("ShoppingListItemRemove")] public static void OnItemRemoved(ItemAttributes item) { if (SemiFunc.RunIsShop()) { DiscountManager.RestoreItemPrice(item); } } [HarmonyPrefix] [HarmonyPatch("ShopCheck")] public static void EnsureDiscountBeforeCheck() { if (SemiFunc.RunIsShop()) { if (!DiscountManager.IsDiscountSynced) { DiscountManager.CurrentDiscount = 0; } DiscountManager.ApplyDiscountToAllItems(); } } } }