Decompiled source of AdjustableGameEconomy v1.3.1

AdjustableGameEconomy.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using AdjustableGameEconomy.Wrappers;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("AdjustableGameEconomy")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AdjustableGameEconomy")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("589FA81F-96F0-4480-89B4-9C1831B7865C")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AdjustableGameEconomy
{
	internal static class Configuration
	{
		public static ConfigEntry<bool> UpgradePlayerCostScale;

		public static ConfigEntry<bool> HealthPackPlayerCostScale;

		public static ConfigEntry<bool> DronePlayerCostScale;

		public static ConfigEntry<bool> CartPlayerCostScale;

		public static ConfigEntry<bool> PowerCrystalPlayerCostScale;

		public static ConfigEntry<bool> ExplosivePlayerCostScale;

		public static ConfigEntry<bool> MeleePlayerCostScale;

		public static ConfigEntry<bool> GunPlayerCostScale;

		public static ConfigEntry<bool> OrbPlayerCostScale;

		public static ConfigEntry<bool> TrackerPlayerCostScale;

		public static ConfigEntry<bool> DisableCostRandomization;

		public static ConfigEntry<bool> DisableUpgradesPurchasedCostScale;

		public static ConfigEntry<bool> DisableLevelsCompletedCostScale;

		public static ConfigEntry<float> PurchaseHistoryScaleMultiplier;

		public static ConfigEntry<float> LevelsCompletedScaleMultiplier;

		public static ConfigEntry<float> UpgradePriceMultiplier;

		public static ConfigEntry<float> DronePriceMultiplier;

		public static ConfigEntry<float> CartPriceMultiplier;

		public static ConfigEntry<float> PowerCrystalPriceMultiplier;

		public static ConfigEntry<float> ExplosivePriceMultiplier;

		public static ConfigEntry<float> MeleePriceMultiplier;

		public static ConfigEntry<float> HealthPackPriceMultiplier;

		public static ConfigEntry<float> GunPriceMultiplier;

		public static ConfigEntry<float> OrbPriceMultiplier;

		public static ConfigEntry<float> TrackerPriceMultiplier;

		public static ConfigEntry<string> PlayerScaleArray;

		public static void Init(ConfigFile config)
		{
			UpgradePlayerCostScale = config.Bind<bool>("Toggles", "UpgradePlayerCostScale", false, "Enable cost scaling for upgrades based on player count.");
			HealthPackPlayerCostScale = config.Bind<bool>("Toggles", "HealthPackPlayerCostScale", false, "Enable cost scaling for health packs based on player count.");
			DronePlayerCostScale = config.Bind<bool>("Toggles", "DronePlayerCostScale", false, "Enable cost scaling for drones based on player count.");
			CartPlayerCostScale = config.Bind<bool>("Toggles", "CartPlayerCostScale", false, "Enable cost scaling for carts based on player count.");
			PowerCrystalPlayerCostScale = config.Bind<bool>("Toggles", "PowerCrystalPlayerCostScale", false, "Enable cost scaling for power crystals based on player count.");
			ExplosivePlayerCostScale = config.Bind<bool>("Toggles", "ExplosivePlayerCostScale", false, "Enable cost scaling for explosive weapons based on player count.");
			MeleePlayerCostScale = config.Bind<bool>("Toggles", "MeleePlayerCostScale", false, "Enable cost scaling for melee weapons based on player count.");
			GunPlayerCostScale = config.Bind<bool>("Toggles", "GunPlayerCostScale", false, "Enable cost scaling for guns based on player count.");
			OrbPlayerCostScale = config.Bind<bool>("Toggles", "OrbPlayerCostScale", false, "Enable cost scaling for orbs based on player count.");
			TrackerPlayerCostScale = config.Bind<bool>("Toggles", "TrackerPlayerCostScale", false, "Enable cost scaling for trackers based on player count.");
			DisableCostRandomization = config.Bind<bool>("General", "DisableCostRandomization", false, "Disable cost randomization, setting all costs to their average values.");
			DisableUpgradesPurchasedCostScale = config.Bind<bool>("General", "DisableUpgradesPurchasedCostScale", false, "Disable cost scaling based on the number of upgrades purchased.");
			DisableLevelsCompletedCostScale = config.Bind<bool>("General", "DisableLevelsCompletedCostScale", false, "Disable cost scaling based on the number of levels completed.");
			PurchaseHistoryScaleMultiplier = config.Bind<float>("Multipliers", "PurchaseHistoryScaleMultiplier", 1f, "Multiplier applied to existing purchase-scaling values (Upgrades).");
			LevelsCompletedScaleMultiplier = config.Bind<float>("Multipliers", "LevelsCompletedScaleMultiplier", 1f, "Multiplier applied to existing level-scaling values (Crystals, Health Packs).");
			UpgradePriceMultiplier = config.Bind<float>("Multipliers", "UpgradePriceMultiplier", 1f, "Multiplier for upgrade costs.");
			DronePriceMultiplier = config.Bind<float>("Multipliers", "DronePriceMultiplier", 1f, "Multiplier for drone costs.");
			CartPriceMultiplier = config.Bind<float>("Multipliers", "CartPriceMultiplier", 1f, "Multiplier for cart costs.");
			PowerCrystalPriceMultiplier = config.Bind<float>("Multipliers", "PowerCrystalPriceMultiplier", 1f, "Multiplier for power crystal costs.");
			ExplosivePriceMultiplier = config.Bind<float>("Multipliers", "ExplosivePriceMultiplier", 1f, "Multiplier for explosive weapon costs.");
			MeleePriceMultiplier = config.Bind<float>("Multipliers", "MeleePriceMultiplier", 1f, "Multiplier for melee weapon costs.");
			HealthPackPriceMultiplier = config.Bind<float>("Multipliers", "HealthPackPriceMultiplier", 1f, "Multiplier for health pack costs.");
			GunPriceMultiplier = config.Bind<float>("Multipliers", "GunPriceMultiplier", 1f, "Multiplier for gun costs.");
			OrbPriceMultiplier = config.Bind<float>("Multipliers", "OrbPriceMultiplier", 1f, "Multiplier for orb costs.");
			TrackerPriceMultiplier = config.Bind<float>("Multipliers", "TrackerPriceMultiplier", 1f, "Multiplier for tracker costs.");
			PlayerScaleArray = config.Bind<string>("ScaleArrays", "PlayerScaleArray", "1,2,2.5,3,4,4.5", "Array defining cost multiplier for different player counts (e.g., x4.5 for 6 players).");
		}
	}
	[BepInPlugin("HopeEradicated.REPO.AdjustableGameEconomy", "R.E.P.O. Adjustable Game Economy", "1.3.1")]
	public class AdjustableGameEconomyBase : BaseUnityPlugin
	{
		private const string PluginGuid = "HopeEradicated.REPO.AdjustableGameEconomy";

		private const string PluginName = "R.E.P.O. Adjustable Game Economy";

		private const string PluginVersion = "1.3.1";

		private readonly Harmony harmony = new Harmony("HopeEradicated.REPO.AdjustableGameEconomy");

		internal static AdjustableGameEconomyBase Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static float[] PlayerScaleData { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			Logger = ((BaseUnityPlugin)this).Logger;
			Configuration.Init(((BaseUnityPlugin)this).Config);
			harmony.PatchAll(typeof(AdjustableGameEconomyBase).Assembly);
			LoadPlayerScaleData();
			Logger.LogInfo((object)"R.E.P.O. Adjustable Game Economy v1.3.1 loaded");
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)4;
		}

		private void LoadPlayerScaleData()
		{
			string[] array = Configuration.PlayerScaleArray.Value.Split(new char[1] { ',' });
			PlayerScaleData = new float[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				if (!float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out PlayerScaleData[i]))
				{
					Logger.LogError((object)("Invalid value in PlayerScaleArray: " + array[i] + ". Defaulting to 1.0"));
					PlayerScaleData[i] = 1f;
				}
			}
		}
	}
}
namespace AdjustableGameEconomy.Wrappers
{
	internal static class ItemAttributesWrapper
	{
		private static readonly FieldRef<ItemAttributes, PhotonView> photonViewRef = GetFieldRef<PhotonView>("photonView");

		private static readonly FieldRef<ItemAttributes, string> itemAssetNameRef = GetFieldRef<string>("itemAssetName");

		private static readonly FieldRef<ItemAttributes, itemType> itemTypeRef = GetFieldRef<itemType>("itemType");

		private static readonly FieldRef<ItemAttributes, int> valueRef = GetFieldRef<int>("value");

		private static readonly FieldRef<ItemAttributes, float> itemValueMinRef = GetFieldRef<float>("itemValueMin");

		private static readonly FieldRef<ItemAttributes, float> itemValueMaxRef = GetFieldRef<float>("itemValueMax");

		public static ItemAttributes instance { get; set; }

		public static PhotonView PhotonView => photonViewRef.Invoke(instance);

		public static string itemAssetName => itemAssetNameRef.Invoke(instance);

		public static itemType itemType => itemTypeRef.Invoke(instance);

		public static float itemValueMin => itemValueMinRef.Invoke(instance);

		public static float itemValueMax => itemValueMaxRef.Invoke(instance);

		public static int value
		{
			get
			{
				return valueRef.Invoke(instance);
			}
			set
			{
				valueRef.Invoke(instance) = value;
			}
		}

		private static FieldRef<ItemAttributes, T> GetFieldRef<T>(string fieldName)
		{
			return AccessTools.FieldRefAccess<ItemAttributes, T>(fieldName);
		}
	}
	internal static class ShopManagerWrapper
	{
		private static readonly FieldRef<ShopManager, float> itemValueMultiplierRef = GetFieldRef<float>("itemValueMultiplier");

		private static readonly FieldRef<ShopManager, float> upgradeValueIncreaseRef = GetFieldRef<float>("upgradeValueIncrease");

		private static readonly FieldRef<ShopManager, float> healthPackValueIncreaseRef = GetFieldRef<float>("healthPackValueIncrease");

		private static readonly FieldRef<ShopManager, float> crystalValueIncreaseRef = GetFieldRef<float>("crystalValueIncrease");

		private static readonly FieldRef<ShopManager, List<ItemAttributes>> shoppingListRef = GetFieldRef<List<ItemAttributes>>("shoppingList");

		public static ShopManager instance { get; set; }

		public static float itemValueMultiplier => itemValueMultiplierRef.Invoke(instance);

		public static float upgradeValueIncrease => upgradeValueIncreaseRef.Invoke(instance);

		public static float healthPackValueIncrease => healthPackValueIncreaseRef.Invoke(instance);

		public static float crystalValueIncrease => crystalValueIncreaseRef.Invoke(instance);

		public static List<ItemAttributes> shoppingList
		{
			get
			{
				return shoppingListRef.Invoke(instance);
			}
			set
			{
				shoppingListRef.Invoke(instance) = value;
			}
		}

		private static FieldRef<ShopManager, T> GetFieldRef<T>(string fieldName)
		{
			return AccessTools.FieldRefAccess<ShopManager, T>(fieldName);
		}
	}
}
namespace AdjustableGameEconomy.Patches
{
	[HarmonyPatch(typeof(ItemAttributes), "GetValue")]
	public class ItemAttributesPatch
	{
		public static bool Prefix(ItemAttributes __instance)
		{
			//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)
			try
			{
				ItemAttributesWrapper.instance = __instance;
				if (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient)
				{
					return false;
				}
				float num = CalculateBaseValue();
				num = ApplyMultipliers(num);
				ItemAttributesWrapper.value = Mathf.Max(1, (int)num);
				if (GameManager.Multiplayer() && PhotonNetwork.IsMasterClient)
				{
					if ((Object)(object)ItemAttributesWrapper.PhotonView == (Object)null)
					{
						AdjustableGameEconomyBase.Logger.LogFatal((object)" PhotonView is null — RPC will not be sent!");
					}
					else
					{
						ItemAttributesWrapper.PhotonView.RPC("GetValueRPC", (RpcTarget)1, new object[1] { ItemAttributesWrapper.value });
					}
				}
				ManualLogSource logger = AdjustableGameEconomyBase.Logger;
				string arg = ItemAttributesWrapper.itemAssetName ?? "<null>";
				itemType itemType = ItemAttributesWrapper.itemType;
				logger.LogInfo((object)$" '{arg}' of {((object)(itemType)(ref itemType)).ToString()} → Price: {ItemAttributesWrapper.value}");
			}
			catch (Exception ex)
			{
				AdjustableGameEconomyBase.Logger.LogFatal((object)(" EXCEPTION during price calculation!\n" + $"Exception: {ex}\n" + "StackTrace: " + ex.StackTrace));
			}
			return false;
		}

		private static float CalculateBaseValue()
		{
			float num = Random.Range(ItemAttributesWrapper.itemValueMin, ItemAttributesWrapper.itemValueMax) * ShopManagerWrapper.itemValueMultiplier;
			if (Configuration.DisableCostRandomization.Value)
			{
				num = (ItemAttributesWrapper.itemValueMin + ItemAttributesWrapper.itemValueMax) * ShopManagerWrapper.itemValueMultiplier / 2f;
			}
			return (num < 1000f) ? 1f : Mathf.Ceil(num / 1000f);
		}

		private static float ApplyMultipliers(float num)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected I4, but got Unknown
			int num2 = Mathf.Clamp(SemiFunc.PlayerGetAll().Count - 1, 0, AdjustableGameEconomyBase.PlayerScaleData.Length - 1);
			float scaleFactor = AdjustableGameEconomyBase.PlayerScaleData[num2];
			bool flag = !Configuration.DisableLevelsCompletedCostScale.Value && (Object)(object)RunManager.instance != (Object)null;
			bool flag2 = !Configuration.DisableUpgradesPurchasedCostScale.Value && (Object)(object)StatsManager.instance != (Object)null;
			itemType itemType = ItemAttributesWrapper.itemType;
			itemType val = itemType;
			switch ((int)val)
			{
			case 3:
			case 4:
				if (flag2)
				{
					float num4 = ShopManagerWrapper.upgradeValueIncrease * Configuration.PurchaseHistoryScaleMultiplier.Value;
					num += num * num4 * (float)StatsManager.instance.GetItemsUpgradesPurchased(ItemAttributesWrapper.itemAssetName);
				}
				num = ApplyPlayerScaling(num, Configuration.UpgradePlayerCostScale.Value, scaleFactor);
				num *= Configuration.UpgradePriceMultiplier.Value;
				break;
			case 0:
				num = ApplyPlayerScaling(num, Configuration.DronePlayerCostScale.Value, scaleFactor);
				num *= Configuration.DronePriceMultiplier.Value;
				break;
			case 2:
			case 12:
				num = ApplyPlayerScaling(num, Configuration.CartPlayerCostScale.Value, scaleFactor);
				num *= Configuration.CartPriceMultiplier.Value;
				break;
			case 5:
				if (flag)
				{
					float num3 = ShopManagerWrapper.crystalValueIncrease * Configuration.LevelsCompletedScaleMultiplier.Value;
					num += num * num3 * (float)RunManager.instance.levelsCompleted;
				}
				num = ApplyPlayerScaling(num, Configuration.PowerCrystalPlayerCostScale.Value, scaleFactor);
				num *= Configuration.PowerCrystalPriceMultiplier.Value;
				break;
			case 6:
			case 11:
				num = ApplyPlayerScaling(num, Configuration.ExplosivePlayerCostScale.Value, scaleFactor);
				num *= Configuration.ExplosivePriceMultiplier.Value;
				break;
			case 7:
				num = ApplyPlayerScaling(num, Configuration.MeleePlayerCostScale.Value, scaleFactor);
				num *= Configuration.MeleePriceMultiplier.Value;
				break;
			case 8:
				if (flag)
				{
					num += num * ShopManagerWrapper.healthPackValueIncrease * (float)RunManager.instance.levelsCompleted;
				}
				num = ApplyPlayerScaling(num, Configuration.HealthPackPlayerCostScale.Value, scaleFactor);
				num *= Configuration.HealthPackPriceMultiplier.Value;
				break;
			case 9:
				num = ApplyPlayerScaling(num, Configuration.GunPlayerCostScale.Value, scaleFactor);
				num *= Configuration.GunPriceMultiplier.Value;
				break;
			case 1:
				num = ApplyPlayerScaling(num, Configuration.OrbPlayerCostScale.Value, scaleFactor);
				num *= Configuration.OrbPriceMultiplier.Value;
				break;
			case 10:
				num = ApplyPlayerScaling(num, Configuration.TrackerPlayerCostScale.Value, scaleFactor);
				num *= Configuration.TrackerPriceMultiplier.Value;
				break;
			}
			return num;
		}

		private static float ApplyPlayerScaling(float num, bool condition, float scaleFactor)
		{
			return (condition && GameManager.Multiplayer()) ? (num * scaleFactor) : num;
		}
	}
	[HarmonyPatch(typeof(ShopManager), "Awake")]
	public class ShopManagerPatch
	{
		public static void Postfix(ShopManager __instance)
		{
			ShopManagerWrapper.instance = __instance;
		}
	}
}