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;
}
}
}