Decompiled source of BetterRollover v0.0.4

BetterRollover.dll

Decompiled 5 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CustomQuotaSystem.Patches;
using HarmonyLib;
using LethalNetworkAPI;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CustomQuotaSystem
{
	public static class ConfigManager
	{
		public static ConfigEntry<int> StartingCredits { get; private set; }

		public static ConfigEntry<int> StartingQuota { get; private set; }

		public static ConfigEntry<int> DaysToDeadline { get; private set; }

		public static ConfigEntry<int> BaseIncrease { get; private set; }

		public static ConfigEntry<float> CurveSharpness { get; private set; }

		public static ConfigEntry<float> RandomizerMultiplier { get; private set; }

		public static ConfigEntry<float> OvertimePayPercent { get; private set; }

		public static ConfigEntry<bool> DisableQuota { get; private set; }

		public static ConfigEntry<int> QuotaCap { get; private set; }

		internal static void Initialize(ConfigFile config)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			StartingCredits = config.Bind<int>("Basic", "StartingCredits", 60, "Starting credits for a new lobby.");
			StartingQuota = config.Bind<int>("Basic", "StartingQuota", 130, "Starting quota for a new lobby.");
			DaysToDeadline = config.Bind<int>("Basic", "DaysToDeadline", 3, "Number of days to meet each quota.");
			BaseIncrease = config.Bind<int>("Quota Scaling", "BaseIncrease", 100, "Base amount the quota increases per cycle.");
			CurveSharpness = config.Bind<float>("Quota Scaling", "CurveSharpness", 16f, "Controls how fast the quota ramps up. Higher = slower growth.");
			RandomizerMultiplier = config.Bind<float>("Quota Scaling", "RandomizerMultiplier", 1f, "Random variance on each quota increase. 0 = no randomness, 1 = ±50%.");
			OvertimePayPercent = config.Bind<float>("Rollover", "OvertimePayPercent", 0.2f, new ConfigDescription("Percentage of excess scrap beyond (new quota - 1) that is paid as bonus credits. 0.2 = 20% of excess becomes credits.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			DisableQuota = config.Bind<bool>("Basic", "DisableQuota", true, "Completely disables the custom quota system.");
			QuotaCap = config.Bind<int>("Quota Scaling", "QuotaCap", -1, "Maximum quota value. Set -1 for no limit.");
		}
	}
	[BepInPlugin("Syntheal.BetterRollover", "BetterRollover", "0.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class QuotaManager : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("Syntheal.BetterRollover");

		public static QuotaManager Instance;

		public static ManualLogSource Log;

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			NetworkSync.Initialize();
			Log.LogInfo((object)"Custom Quota System loaded!");
			harmony.PatchAll();
		}
	}
}
namespace CustomQuotaSystem.Patches
{
	internal static class NetworkSync
	{
		private static LNetworkMessage<int> _syncRolloverMessage;

		private static LNetworkMessage<int> _syncDeadlineMessage;

		private static LNetworkMessage<int> _syncQuotaMessage;

		public static void Initialize()
		{
			try
			{
				_syncRolloverMessage = LNetworkMessage<int>.Connect("CustomQuotaSystem_SyncRollover", (Action<int, ulong>)null, (Action<int>)OnRolloverReceived, (Action<int, ulong>)null);
				_syncDeadlineMessage = LNetworkMessage<int>.Connect("CustomQuotaSystem_SyncDeadline", (Action<int, ulong>)null, (Action<int>)OnDeadlineReceived, (Action<int, ulong>)null);
				_syncQuotaMessage = LNetworkMessage<int>.Connect("CustomQuotaSystem_SyncQuota", (Action<int, ulong>)null, (Action<int>)OnQuotaReceived, (Action<int, ulong>)null);
				QuotaManager.Log.LogInfo((object)"Network sync initialized.");
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not initialize network sync: " + ex.Message));
			}
		}

		public static void SyncRolloverToClients(int rollover)
		{
			try
			{
				if (_syncRolloverMessage == null)
				{
					QuotaManager.Log.LogWarning((object)"Rollover message not initialized");
					return;
				}
				_syncRolloverMessage.SendClients(rollover);
				QuotaManager.Log.LogInfo((object)$"Synced rollover {rollover} to clients");
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not sync rollover: " + ex.Message));
			}
		}

		public static void SyncDeadlineToClients(int deadline)
		{
			try
			{
				if (_syncDeadlineMessage == null)
				{
					QuotaManager.Log.LogWarning((object)"Deadline message not initialized");
				}
				else
				{
					_syncDeadlineMessage.SendClients(deadline);
				}
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not sync deadline: " + ex.Message));
			}
		}

		public static void SyncQuotaToClients(int quota)
		{
			try
			{
				if (_syncQuotaMessage == null)
				{
					QuotaManager.Log.LogWarning((object)"Quota message not initialized");
				}
				else
				{
					_syncQuotaMessage.SendClients(quota);
				}
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not sync quota: " + ex.Message));
			}
		}

		private static void OnRolloverReceived(int rollover)
		{
			try
			{
				TimeOfDay instance = TimeOfDay.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.quotaFulfilled = rollover;
					QuotaManager.Log.LogInfo((object)$"Client received rollover: {rollover}");
				}
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not apply synced rollover on client: " + ex.Message));
			}
		}

		private static void OnDeadlineReceived(int deadline)
		{
			try
			{
				TimeOfDay instance = TimeOfDay.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.daysUntilDeadline = deadline;
					if (instance.totalTime > 0f)
					{
						instance.timeUntilDeadline = instance.totalTime * (float)deadline;
					}
				}
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not apply synced deadline on client: " + ex.Message));
			}
		}

		private static void OnQuotaReceived(int quota)
		{
			try
			{
				TimeOfDay instance = TimeOfDay.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.profitQuota = quota;
				}
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not apply synced quota on client: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	internal static class TerminalPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void ApplyStartingCredits(Terminal __instance)
		{
			try
			{
				int value = ConfigManager.StartingCredits.Value;
				if (value >= 0)
				{
					__instance.groupCredits = value;
					QuotaManager.Log.LogInfo((object)$"Starting credits set to {value}.");
				}
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogWarning((object)("Could not apply starting credits: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(TimeOfDay))]
	internal static class TimeOfDayPatch
	{
		private static bool _initialQuotaApplied;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void TimeOfDay_Awake_Postfix(TimeOfDay __instance)
		{
			ApplyQuotaVariables(__instance);
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void TimeOfDay_Start_Postfix(TimeOfDay __instance)
		{
			if (__instance.timesFulfilledQuota == 0 && !_initialQuotaApplied)
			{
				_initialQuotaApplied = true;
				if (((NetworkBehaviour)__instance).IsServer)
				{
					int num = (__instance.profitQuota = ConfigManager.StartingQuota.Value);
					__instance.quotaFulfilled = 0;
					QuotaManager.Log.LogInfo((object)$"Initial quota set to {num}");
					NetworkSync.SyncQuotaToClients(num);
					NetworkSync.SyncRolloverToClients(0);
				}
			}
		}

		private static void ApplyQuotaVariables(TimeOfDay instance)
		{
			try
			{
				if (instance.quotaVariables != null)
				{
					instance.quotaVariables.startingQuota = ConfigManager.StartingQuota.Value;
					instance.quotaVariables.startingCredits = ConfigManager.StartingCredits.Value;
					QuotaManager.Log.LogInfo((object)$"Quota variables set: startingQuota={ConfigManager.StartingQuota.Value}, startingCredits={ConfigManager.StartingCredits.Value}");
				}
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not apply quota settings at startup: " + ex.Message));
			}
		}

		[HarmonyPatch("SetNewProfitQuota")]
		[HarmonyPrefix]
		private static bool SetNewProfitQuota_Prefix(TimeOfDay __instance, ref int ___timesFulfilledQuota, ref int ___profitQuota, ref float ___timeUntilDeadline, ref int ___quotaFulfilled, ref int ___daysUntilDeadline, ref float ___totalTime)
		{
			try
			{
				if (!((NetworkBehaviour)__instance).IsServer)
				{
					return false;
				}
				if (ConfigManager.DisableQuota.Value)
				{
					___profitQuota = Mathf.Max(0, ConfigManager.StartingQuota.Value);
					SetDeadlineTimer(___totalTime, ref ___daysUntilDeadline, ref ___timeUntilDeadline);
					NetworkSync.SyncQuotaToClients(___profitQuota);
					NetworkSync.SyncRolloverToClients(0);
					NetworkSync.SyncDeadlineToClients(___daysUntilDeadline);
					return false;
				}
				int num = ___profitQuota;
				___timesFulfilledQuota++;
				int num2 = CalculateNewQuota(num, ___timesFulfilledQuota);
				int prevDays = ___daysUntilDeadline;
				int num3 = ___quotaFulfilled - num;
				int num4 = num2 - 1;
				int num5 = Mathf.Min(num3, num4);
				int num6 = Mathf.Max(0, num3 - num4);
				int num7 = Mathf.RoundToInt((float)num6 * ConfigManager.OvertimePayPercent.Value);
				int num8 = SetDeadlineTimer(___totalTime, ref ___daysUntilDeadline, ref ___timeUntilDeadline, prevDays);
				__instance.quotaVariables.deadlineDaysAmount = num8;
				___profitQuota = num2;
				___quotaFulfilled = num5;
				___daysUntilDeadline = num8;
				___timeUntilDeadline = ___totalTime * (float)num8;
				__instance.SyncNewProfitQuotaClientRpc(num2, num7, ___timesFulfilledQuota);
				NetworkSync.SyncQuotaToClients(num2);
				NetworkSync.SyncRolloverToClients(num5);
				NetworkSync.SyncDeadlineToClients(num8);
				QuotaManager.Log.LogInfo((object)($"Quota {___timesFulfilledQuota}: {num} -> {num2}, " + $"overage: {num3}, rollover: {num5}/{num4}, " + $"overtime scrap: {num6}, overtime bonus: ${num7}"));
				return false;
			}
			catch (Exception ex)
			{
				QuotaManager.Log.LogError((object)("Could not calculate the next quota: " + ex.Message));
				return true;
			}
		}

		private static int CalculateNewQuota(int previousQuota, int timesFulfilled)
		{
			float num = Mathf.Max(0.1f, ConfigManager.CurveSharpness.Value);
			float num2 = timesFulfilled;
			float num3 = Mathf.Clamp(1f + num2 * (num2 / num), 0f, 10000f);
			float num4 = 1f;
			float value = ConfigManager.RandomizerMultiplier.Value;
			if (value > 0f)
			{
				num4 = 1f + Random.Range(-0.5f, 0.5f) * value;
			}
			float num5 = (float)ConfigManager.BaseIncrease.Value * num3 * num4;
			int num6 = Mathf.RoundToInt(Mathf.Clamp((float)previousQuota + num5, 0f, 1E+09f));
			int value2 = ConfigManager.QuotaCap.Value;
			if (value2 != -1)
			{
				num6 = Mathf.Min(num6, value2);
			}
			return num6;
		}

		private static int SetDeadlineTimer(float dayDuration, ref int days, ref float timeUntilDeadline, int prevDays = -1)
		{
			int num = (days = Mathf.Max(1, ConfigManager.DaysToDeadline.Value));
			timeUntilDeadline = (float)num * dayDuration;
			return num;
		}
	}
}