using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ProliferatorMultiplier")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ViliusVV")]
[assembly: AssemblyProduct("ProliferatorMultiplier")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6CD44CB7-E582-4F87-8174-9A172922F948")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyVersion("1.2.0.0")]
namespace ProliferatorMultiplier;
internal class GameLoad_Patch
{
[HarmonyPrefix]
[HarmonyPatch(typeof(UIRoot), "OnGameMainObjectCreated")]
public static void OnGameMainObjectCreated()
{
PatchProliferator.Setup();
}
}
[BepInPlugin("viliusvv.proliferatormultiplier", "ProliferatorMultiplier", "1.2.0")]
public class ProliferatorMultiplier : BaseUnityPlugin
{
private const string PluginGuid = "viliusvv.proliferatormultiplier";
private const string PluginName = "ProliferatorMultiplier";
private const string PluginVersion = "1.2.0";
internal static ManualLogSource Logger;
private readonly Harmony _harmony = new Harmony("viliusvv.proliferatormultiplier");
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)string.Format("==> {0} [{1}], Dev Mode: {2}", "ProliferatorMultiplier", "1.2.0-2026-03-21T17:34:12Z", false));
((BaseUnityPlugin)this).Config.Save();
PatchProliferator.Init(((BaseUnityPlugin)this).Config);
_harmony.PatchAll(typeof(GameLoad_Patch));
}
private void Update()
{
}
private void OnDestroy()
{
PatchProliferator.Teardown();
_harmony.UnpatchSelf();
}
}
internal static class PatchProliferator
{
private const string ConfigEffectGroup = "Proliferator effect";
private const string ConfigRecipeGroup = "Proliferator recipe";
private const string KeyMultProduction = "MultProduction";
private const string KeyMultSpeed = "MultSpeed";
private const string KeyMultEnergy = "MultEnergy";
private const string KeyMultRecipeCost = "MultRecipeCost";
private const string KeyMultRecipeDuration = "MultRecipeDuration";
private static readonly int[] RecipeIds = new int[3] { 106, 107, 108 };
private static ConfigFile _configFile;
private static ConfigEntry<float> _multProduction;
private static ConfigEntry<float> _multSpeed;
private static ConfigEntry<float> _multEnergy;
private static ConfigEntry<float> _multRecipeCost;
private static ConfigEntry<float> _multRecipeDuration;
private static readonly double[] _backupIncTableMilli = Utils.CopyTable(Cargo.incTableMilli);
private static readonly double[] _backupAccTableMilli = Utils.CopyTable(Cargo.accTableMilli);
private static readonly int[] _backupIncFastDivisionNumerator = Utils.CopyTable(Cargo.incFastDivisionNumerator);
private static readonly int[] _backupIncTable = Utils.CopyTable(Cargo.incTable);
private static readonly int[] _backupAccTable = Utils.CopyTable(Cargo.accTable);
private static readonly int[] _backupPowerTable = Utils.CopyTable(Cargo.powerTable);
private static readonly double[] _backupPowerTableRatio = Utils.CopyTable(Cargo.powerTableRatio);
private static readonly Dictionary<int, int[]> _originalRecipeCost = new Dictionary<int, int[]>();
private static readonly Dictionary<int, int> _originalRecipeDuration = new Dictionary<int, int>();
public static void Init(ConfigFile config)
{
_configFile = config;
BindConfig();
BackupOriginalRecipes();
}
public static void Setup()
{
ApplyConfig();
}
private static void ApplyConfig()
{
PatchTables();
PatchProliferatorRecipes();
PrintTables();
}
public static void ReloadConfig()
{
float value = _multProduction.Value;
float value2 = _multSpeed.Value;
float value3 = _multEnergy.Value;
float value4 = _multRecipeCost.Value;
float value5 = _multRecipeDuration.Value;
_configFile.Reload();
if ((0u | (LogIfChanged("MultProduction", value, _multProduction.Value) ? 1u : 0u) | (LogIfChanged("MultSpeed", value2, _multSpeed.Value) ? 1u : 0u) | (LogIfChanged("MultEnergy", value3, _multEnergy.Value) ? 1u : 0u) | (LogIfChanged("MultRecipeCost", value4, _multRecipeCost.Value) ? 1u : 0u) | (LogIfChanged("MultRecipeDuration", value5, _multRecipeDuration.Value) ? 1u : 0u)) == 0)
{
ProliferatorMultiplier.Logger.LogInfo((object)"Config reloaded: nothing changed.");
}
ApplyConfig();
}
private static bool LogIfChanged(string name, float prev, float curr)
{
if (Mathf.Approximately(prev, curr))
{
return false;
}
ProliferatorMultiplier.Logger.LogInfo((object)$"Config changed: {name} {prev} -> {curr}");
return true;
}
public static void Teardown()
{
ProliferatorMultiplier.Logger.LogInfo((object)"Restoring original proliferator state...");
Array.Copy(_backupIncTableMilli, Cargo.incTableMilli, _backupIncTableMilli.Length);
Array.Copy(_backupIncTable, Cargo.incTable, _backupIncTable.Length);
Array.Copy(_backupIncFastDivisionNumerator, Cargo.incFastDivisionNumerator, _backupIncFastDivisionNumerator.Length);
Array.Copy(_backupAccTableMilli, Cargo.accTableMilli, _backupAccTableMilli.Length);
Array.Copy(_backupAccTable, Cargo.accTable, _backupAccTable.Length);
Array.Copy(_backupPowerTable, Cargo.powerTable, _backupPowerTable.Length);
Array.Copy(_backupPowerTableRatio, Cargo.powerTableRatio, _backupPowerTableRatio.Length);
int[] recipeIds = RecipeIds;
foreach (int num in recipeIds)
{
RecipeProto recipe = GetRecipe(num);
if (recipe != null)
{
if (_originalRecipeCost.TryGetValue(num, out var value))
{
recipe.ItemCounts = value;
}
if (_originalRecipeDuration.TryGetValue(num, out var value2))
{
recipe.TimeSpend = value2;
}
}
}
ProliferatorMultiplier.Logger.LogInfo((object)"Teardown done.");
}
private static void BindConfig()
{
_multProduction = Bind("Proliferator effect", "MultProduction", "Production multiplier for proliferator effect");
_multSpeed = Bind("Proliferator effect", "MultSpeed", "Speed multiplier for proliferator effect");
_multEnergy = Bind("Proliferator effect", "MultEnergy", "Energy consumption multiplier for proliferator effect");
_multRecipeCost = Bind("Proliferator recipe", "MultRecipeCost", "Multiplier for recipe cost");
_multRecipeDuration = Bind("Proliferator recipe", "MultRecipeDuration", "Multiplier for spray duration");
ProliferatorMultiplier.Logger.LogInfo((object)$"Config: Production={_multProduction.Value}, Speed={_multSpeed.Value}, Energy={_multEnergy.Value}");
}
private static ConfigEntry<float> Bind(string section, string key, string desc)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
return _configFile.Bind<float>(section, key, 1f, new ConfigDescription(desc, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1000f), Array.Empty<object>()));
}
private static void PatchTables()
{
MultiplyArrayToDest(_multProduction.Value, _backupIncTable, Cargo.incTable);
MultiplyArrayToDest(_multProduction.Value, _backupIncTableMilli, Cargo.incTableMilli);
PatchIncDivisionTable(Cargo.incFastDivisionNumerator);
MultiplyArrayToDest(_multSpeed.Value, _backupAccTableMilli, Cargo.accTableMilli);
MultiplyArrayToDest(_multSpeed.Value, _backupAccTable, Cargo.accTable);
MultiplyArrayToDest(_multEnergy.Value, _backupPowerTable, Cargo.powerTable);
PatchPowerTableRatio(_multEnergy.Value, _backupPowerTableRatio, Cargo.powerTableRatio);
}
private static void PatchProliferatorRecipes()
{
int[] recipeIds = RecipeIds;
foreach (int num in recipeIds)
{
RecipeProto recipe = GetRecipe(num);
if (recipe != null)
{
MultiplyArrayToDest(_multRecipeCost.Value, _originalRecipeCost[num], recipe.ItemCounts);
recipe.TimeSpend = (int)Math.Round((double)_originalRecipeDuration[num] * (double)_multRecipeDuration.Value);
}
}
}
private static void BackupOriginalRecipes()
{
int[] recipeIds = RecipeIds;
for (int i = 0; i < recipeIds.Length; i++)
{
RecipeProto recipe = GetRecipe(recipeIds[i]);
if (recipe != null)
{
_originalRecipeCost[((Proto)recipe).ID] = recipe.ItemCounts;
_originalRecipeDuration[((Proto)recipe).ID] = recipe.TimeSpend;
ProliferatorMultiplier.Logger.LogDebug((object)string.Format("Backed up recipe {0}: cost=[{1}], t={2}", Localization.Translate(((Proto)recipe).Name), GeneralExtensions.Join<int>((IEnumerable<int>)recipe.ItemCounts, (Func<int, string>)null, ", "), recipe.TimeSpend));
}
}
}
private static void PrintTables()
{
}
private static void MultiplyArrayToDest(float mult, double[] original, double[] dest)
{
for (int i = 0; i < original.Length; i++)
{
dest[i] = original[i] * (double)mult;
}
}
private static void MultiplyArrayToDest(float mult, int[] original, int[] dest)
{
for (int i = 0; i < original.Length; i++)
{
dest[i] = (int)((float)original[i] * mult);
}
}
private static void PatchIncDivisionTable(int[] dest)
{
for (int i = 0; i < dest.Length; i++)
{
dest[i] = 40 + (int)Math.Round(Cargo.incTableMilli[i] * 40.0);
}
}
private static void PatchPowerTableRatio(float mult, double[] original, double[] dest)
{
for (int i = 0; i < original.Length; i++)
{
dest[i] = (original[i] - 1.0) * (double)mult + 1.0;
}
}
private static RecipeProto GetRecipe(int id)
{
RecipeProto? obj = ((IEnumerable<RecipeProto>)((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray).FirstOrDefault((Func<RecipeProto, bool>)((RecipeProto r) => ((Proto)r).ID == id));
if (obj == null)
{
ProliferatorMultiplier.Logger.LogError((object)$"Recipe with ID {id} not found!");
}
return obj;
}
}
internal static class Utils
{
internal const bool IsDev = false;
public static T[] CopyTable<T>(T[] original)
{
T[] array = new T[original.Length];
Array.Copy(original, array, original.Length);
return array;
}
}
internal static class VersionInfo
{
public const string Version = "1.2.0";
public const string BuildDate = "2026-03-21T17:34:12Z";
public const string VersionBuild = "1.2.0-2026-03-21T17:34:12Z";
}