Decompiled source of ShopDiscounts v1.0.3

ShopDiscounts.dll

Decompiled 21 hours ago
using 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();
			}
		}
	}
}