Decompiled source of Economy Mod v1.0.3

LethalCompanyEconomyMod.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalNetworkAPI;
using TMPro;
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("LethalCompanyEconomyMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LethalCompanyEconomyMod")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("11dfcace-cb6f-4ed9-b69c-c5bd5a6e6722")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LethalCompanyEconomyMod;

[BepInPlugin("com.raalplay.lethalcompanyeconomy", "EconomyMod", "1.0.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class EconomyMod : BaseUnityPlugin
{
	public const string modGUID = "com.raalplay.lethalcompanyeconomy";

	public const string modName = "EconomyMod";

	public const string modVersion = "1.0.3";

	private readonly Harmony harmony = new Harmony("com.raalplay.lethalcompanyeconomy");

	internal static ManualLogSource Logger;

	internal static EconomyMod Instance { get; private set; }

	private void Awake()
	{
		Logger = ((BaseUnityPlugin)this).Logger;
		Logger.LogInfo((object)"Plugin EconomyMod se ha cargado correctamente!");
		EconomyModPatches.ModConfig.LoadConfig(((BaseUnityPlugin)this).Config);
		Logger.LogInfo((object)"Configuraciones cargadas correctamente!");
		if ((Object)(object)Instance == (Object)null)
		{
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)this);
		}
		else
		{
			if ((Object)(object)((Component)Instance).gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)Instance).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)Instance);
			}
			Instance = this;
		}
		try
		{
			harmony.PatchAll(typeof(EconomyModPatches.StartOfRound_StartGame_Patch));
			Logger.LogInfo((object)"Parches de Harmony aplicados.");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error al aplicar parches de Harmony: " + ex.Message));
		}
	}
}
internal static class EconomyModPatches
{
	public static class ModConfig
	{
		public static ConfigEntry<float> EventProbability { get; private set; }

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

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

		public static void LoadConfig(ConfigFile config)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			EventProbability = config.Bind<float>("General", "Event Probability", 1f, new ConfigDescription("Probability (0.0 to 1.0) of the event occurring.", (AcceptableValueBase)null, Array.Empty<object>()));
			NextExecutionMin = config.Bind<float>("Timing", "Next Execution Minimum", 70f, new ConfigDescription("Minimum time (in seconds) before the next execution.", (AcceptableValueBase)null, Array.Empty<object>()));
			NextExecutionMax = config.Bind<float>("Timing", "Next Execution Maximum", 300f, new ConfigDescription("Maximum time (in seconds) before the next execution.", (AcceptableValueBase)null, Array.Empty<object>()));
		}

		public static float GetNextExecutionTime()
		{
			return Random.Range(NextExecutionMin.Value, NextExecutionMax.Value);
		}
	}

	[HarmonyPatch(typeof(StartOfRound), "StartGame")]
	public static class StartOfRound_StartGame_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(ref StartOfRound __instance)
		{
			RefreshPlayerList(__instance);
			if (!hasInitialized)
			{
				((MonoBehaviour)__instance).StartCoroutine(Event());
			}
			static IEnumerator Event()
			{
				hasInitialized = true;
				eventProbability = ModConfig.EventProbability.Value;
				yield return (object)new WaitForSeconds(nextExecution);
				if (ProbabilityHelper.Attempt(eventProbability))
				{
					quotaMultiplier = 1f;
					daysToDeadlineExtension = 0;
					GenerateEconomicEvent();
					LastExecutionTime = DateTime.UtcNow;
				}
				nextExecution = Generator.RandomNumber(ModConfig.NextExecutionMin.Value, ModConfig.NextExecutionMax.Value);
				((MonoBehaviour)StartOfRound.Instance).StartCoroutine(Event());
			}
		}
	}

	public class EconomicEvent
	{
		public string message;

		public float multiplier;

		public int daysExtension;

		public bool isRare;

		public bool isGood;

		public int quotaChange;

		public Func<bool> condition;

		public EconomicEvent(string message, float multiplier, int daysExtension, bool isGood, int quotaChange, Func<bool> condition = null, bool isRare = false)
		{
			this.message = message;
			this.multiplier = multiplier;
			this.daysExtension = daysExtension;
			this.isRare = isRare;
			this.isGood = isGood;
			this.quotaChange = quotaChange;
			this.condition = condition;
		}

		public bool IsConditionMet()
		{
			if (condition == null)
			{
				return true;
			}
			return condition();
		}
	}

	public static float quotaMultiplier;

	public static int daysToDeadlineExtension;

	private static string hudMessage;

	private static List<string> eventLog;

	private static bool hasInitialized;

	private static LNetworkMessage<EconomicEvent> economicEvent;

	private static PlayerControllerB[] playersList;

	private static DateTime LastExecutionTime;

	private static float nextExecution;

	private static float eventProbability;

	static EconomyModPatches()
	{
		quotaMultiplier = 1f;
		daysToDeadlineExtension = 0;
		eventLog = new List<string>();
		hasInitialized = false;
		economicEvent = LNetworkMessage<EconomicEvent>.Create("economicEvent", (Action<EconomicEvent, ulong>)null, (Action<EconomicEvent>)null, (Action<EconomicEvent, ulong>)null);
		LastExecutionTime = new DateTime(0L);
		nextExecution = Generator.RandomNumber(ModConfig.NextExecutionMin.Value, ModConfig.NextExecutionMax.Value);
		eventProbability = ModConfig.EventProbability.Value;
		economicEvent.OnClientReceived += EconomicEventReceiveFromServer;
	}

	private static void EconomicEventReceiveFromServer(EconomicEvent arg1)
	{
		((MonoBehaviour)StartOfRound.Instance).StartCoroutine(PlayEvent(arg1));
	}

	private static IEnumerator PlayEvent(EconomicEvent economicEvent)
	{
		HUDManager.Instance.DisplayTip(economicEvent.isGood ? "¡Enhorabuena!" : "¡Malas noticias!", hudMessage.RemoveDiacritics(), !economicEvent.isGood, false, "LC_Tip1");
		ShowMessageInChat((economicEvent.isGood ? "¡Enhorabuena!" : "¡Malas noticias!") + "\n" + hudMessage);
		TimeOfDay timeOfDayInstance = TimeOfDay.Instance;
		int newProfitQuota = Mathf.RoundToInt((float)timeOfDayInstance.profitQuota * quotaMultiplier);
		timeOfDayInstance.profitQuota = newProfitQuota;
		timeOfDayInstance.timeUntilDeadline += (float)(int)(timeOfDayInstance.totalTime * (float)daysToDeadlineExtension);
		if (economicEvent.quotaChange < 0)
		{
			timeOfDayInstance.quotaFulfilled += ((timeOfDayInstance.quotaFulfilled >= Mathf.Abs(economicEvent.quotaChange)) ? economicEvent.quotaChange : (timeOfDayInstance.quotaFulfilled * -1));
		}
		else
		{
			timeOfDayInstance.quotaFulfilled += economicEvent.quotaChange;
		}
		if (economicEvent.multiplier != 1f)
		{
			yield return (object)new WaitForSeconds(10f);
			HUDManager.Instance.DisplayNewDeadline(0);
		}
		else
		{
			timeOfDayInstance.UpdateProfitQuotaCurrentTime();
		}
		EconomyMod.Logger.LogInfo((object)"Reseteando cuota y días al inicio de la partida");
	}

	public static void ShowMessageInChat(string message)
	{
		HUDManager.Instance.AddTextToChatOnServer(message, -1);
	}

	private static void DisplayGlobalNotification(string displayText)
	{
		HUDManager instance = HUDManager.Instance;
		instance.globalNotificationAnimator.SetTrigger("TriggerNotif");
		((TMP_Text)instance.globalNotificationText).text = displayText;
		instance.UIAudio.PlayOneShot(instance.globalNotificationSFX);
	}

	private static IEnumerator _ShowHUDMessage()
	{
		yield return (object)new WaitForSeconds(10f);
		HUDManager.Instance.DisplayStatusEffect("Test");
	}

	public static string getRandomPlayerName()
	{
		return playersList[Random.Range(0, playersList.Length - 1)].playerUsername;
	}

	public static PlayerControllerB getRandomPlayer()
	{
		return playersList[Random.Range(0, playersList.Length - 1)];
	}

	private static void RefreshPlayerList(StartOfRound __instance)
	{
		playersList = __instance.ClientPlayerList.Select((KeyValuePair<ulong, int> x) => __instance.allPlayerScripts[x.Value]).ToArray();
		EconomyMod.Logger.LogInfo((object)("Random player: " + getRandomPlayer().playerUsername));
	}

	public static void GenerateEconomicEvent()
	{
		float num = quotaMultiplier;
		int num2 = daysToDeadlineExtension;
		quotaMultiplier = 1f;
		daysToDeadlineExtension = 0;
		TimeOfDay timeOfDayInstance = TimeOfDay.Instance;
		int daysUntilDeadline = (int)(timeOfDayInstance.timeUntilDeadline / timeOfDayInstance.totalTime);
		GrabbableObject[] source = Object.FindObjectsOfType<GrabbableObject>();
		GrabbableObject[] objectsInShipRoom = source.Where((GrabbableObject obj) => obj.isInShipRoom).ToArray();
		PlayerControllerB randomPlayer = getRandomPlayer();
		PlayerControllerB randomLowHealthPlayer = ((IEnumerable<PlayerControllerB>)playersList).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB x) => x.health <= 20));
		PlayerControllerB randomTypingChatPlayer = ((IEnumerable<PlayerControllerB>)playersList).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB x) => x.isTypingChat));
		PlayerControllerB randomDrowningDeadPlayer = ((IEnumerable<PlayerControllerB>)playersList).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB x) => (int)x.causeOfDeath == 9));
		PlayerControllerB randomInTerminalPlayer = ((IEnumerable<PlayerControllerB>)playersList).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB x) => x.inTerminalMenu));
		List<EconomicEvent> list = new List<EconomicEvent>
		{
			new EconomicEvent("La demanda de chatarra ha aumentado. ¡Prepárense para el multón!", 1.5f, 0, isGood: false, 0),
			new EconomicEvent("La demanda de chatarra ha disminuido. Hoy los jefes se despertaron con buena pata.", 0.7f, 0, isGood: true, Generator.RandomNumber(10, 15), null, isRare: true),
			new EconomicEvent("Tus jefes están de buen humor. ¡Milagro! Disfruten este breve momento de paz y oren.", 0.9f, 2, isGood: true, 3),
			new EconomicEvent(getRandomPlayerName() + " ha realizado un trabajo a puerta cerrada con el jefe de la compañía.", 1f, 0, isGood: true, Generator.RandomNumber(5, 15)),
			new EconomicEvent("Tus jefes están de mal humor. ¡Corran por sus vidas! Y trabajen el doble, que viva la explotación y el capitalismo.", 1.2f, -1, isGood: false, 0, () => daysUntilDeadline >= 3),
			new EconomicEvent("Un comprador especial con gustos peculiares apareció. ¡A vender!", Generator.RandomNumber(1.1f, 1.5f), 0, isGood: true, Generator.RandomNumber(35, 80)),
			new EconomicEvent("Problemas técnicos. La máquina de chatarra está en huelga... contra nosotros.", 1.1f, 0, isGood: false, 0),
			new EconomicEvent("Inflación. Hasta el aire que respiramos es más caro. ¡Y la cuota también!", 1.3f, 0, isGood: false, 0),
			new EconomicEvent("Deflación. Los precios bajan, pero no se confíen.", 0.8f, 0, isGood: true, 0),
			new EconomicEvent("Fusión de empresas. ¡Alguien vendió el alma al diablo!.", 2f, 0, isGood: false, 0, () => daysUntilDeadline >= 3, isRare: true),
			new EconomicEvent("Huelga de trabajadores. ¡¿Huelga, acaso somos los unicos que trabajamos en esta empresa?!.", 1f, -1, isGood: false, 0, () => daysUntilDeadline >= 2),
			new EconomicEvent("Bono de productividad. Un aplauso para el que no se durmió en el trabajo. Tomen algo extra.", 1f, 0, isGood: true, Generator.RandomNumber(7, 15), null, isRare: true),
			new EconomicEvent("Inspección sorpresa. ¡¿Quién dejó esto así?! Multa por vivir en un basurero.", 1f, 0, isGood: false, Generator.RandomNumber(-15, -5), () => objectsInShipRoom.Length > 12 && timeOfDayInstance.quotaFulfilled >= 15),
			new EconomicEvent("Mercado saturado. Los precios de la chatarra cayeron... ¡¿Nos vamos a declarar en bancarrota?!", 1.5f, 0, isGood: false, 0, () => daysUntilDeadline >= 2),
			new EconomicEvent("Nuevo competidor. Esa nueva compañía de chatarra nos está quitando el negocio. ¡¿Qué vamos a hacer?!", 1f, -1, isGood: false, 0, () => daysUntilDeadline >= 2),
			new EconomicEvent("Subvención gubernamental. ¡El tío Sam nos echa una mano!.", 0.9f, 2, isGood: true, Generator.RandomNumber(7, 15), () => daysUntilDeadline <= 2 && timeOfDayInstance.quotaFulfilled < timeOfDayInstance.profitQuota.PercentageOf(50m)),
			new EconomicEvent("Avería de maquinaria. La máquina dijo 'no' hoy, pero te damos más tiempo para que te recuperes del susto.", 1f, 1, isGood: false, 0),
			new EconomicEvent("Demanda sin precedentes. ¡La chatarra es el nuevo oro!", 1.55f, 0, isGood: false, 0, () => daysUntilDeadline >= 2),
			new EconomicEvent("Cambios regulatorios. Parece que alguien no leyó la letra pequeña... ¡Prepárense para las consecuencias!", 1.25f, 0, isGood: false, -45, () => daysUntilDeadline >= 2, isRare: true),
			new EconomicEvent("Desastre natural. La Madre Naturaleza nos odia. Cuota más alta y menos tiempo. ¡Buena suerte con eso!", 1.45f, -1, isGood: false, -80, () => daysUntilDeadline >= 3, isRare: true),
			new EconomicEvent("Inversión extranjera. ¡Al parecer alguien decidió lavar dinero con nuestra compañía!.", 0.75f, 0, isGood: true, 50, () => daysUntilDeadline <= 3 && timeOfDayInstance.quotaFulfilled < timeOfDayInstance.profitQuota.PercentageOf(70m), isRare: true),
			new EconomicEvent("Reorganización interna. Tu cuota se reduce temporalmente. ¡No se acostumbren!", 0.85f, 0, isGood: true, 0, () => daysUntilDeadline >= 2),
			new EconomicEvent("Robo de material. ¡¿Dónde están nuestros ahorros?!... Y tenemos menos tiempo, genial.", 1f, -1, isGood: false, -90, () => daysUntilDeadline >= 2, isRare: true),
			new EconomicEvent("Premio a la eficiencia. Sigan así y tal vez les demos una palmadita en la espalda...", 1f, 0, isGood: true, Generator.RandomNumber(2, 15), () => daysUntilDeadline >= 2, isRare: true),
			new EconomicEvent("Auditoría fiscal. Alguien olvidó declarar sus ganancias. ¡A pagar el pato!", 1f, 0, isGood: false, -65, () => daysUntilDeadline >= 2 && timeOfDayInstance.quotaFulfilled >= 65, isRare: true),
			new EconomicEvent("Uno de los pasajeros ha evadido impuestos y el gobierno no pudo saber cuál de todos era por lo que ha decidido multar a toda la nave.", 1f, 0, isGood: false, -75, () => daysUntilDeadline >= 2 && timeOfDayInstance.quotaFulfilled >= 75, isRare: true),
			new EconomicEvent(getRandomPlayerName() + " no se ha bajado correctamente de la nave y ha roto la escalera, habrá que pagar reparación.", 1f, 0, isGood: false, -75, () => daysUntilDeadline >= 2 && timeOfDayInstance.quotaFulfilled >= 75, isRare: true),
			new EconomicEvent("¡La competencia ha lanzado una campaña de desprestigio! Tu reputación (y tus ganancias) se ven afectadas.", 1.4f, 0, isGood: false, 0, () => daysUntilDeadline >= 2),
			new EconomicEvent("Se rumorea que un coleccionista excéntrico está buscando chatarra rara. ¡Precios altos si encuentras algo interesante!", 0.75f, 0, isGood: true, 0, () => daysUntilDeadline >= 2, isRare: true),
			new EconomicEvent("Un error contable inesperado a tu favor...", 1f, 0, isGood: true, Generator.RandomNumber(2, 45), () => daysUntilDeadline <= 3, isRare: true),
			new EconomicEvent("La galaxia entera está celebrando un festival de reciclaje. ¡La demanda ha aumentado!", 1.2f, 1, isGood: false, 0, () => daysUntilDeadline >= 1),
			new EconomicEvent("Has encontrado unas facturas que no habias entregado en un rincón remoto de la nave. ¡Es tu día de suerte!", 0.85f, 0, isGood: true, 0, () => daysUntilDeadline <= 2, isRare: true)
		};
		list.AddRange(new EconomicEvent[7]
		{
			new EconomicEvent("Mientras todos estaban distraídos " + randomPlayer?.playerUsername + " robo unos tornillos a una familia de ratoncitos que vivían en la fabrica.", 1f, 0, isGood: true, Generator.RandomNumber(5, 15), () => randomPlayer.isInsideFactory),
			new EconomicEvent($"{randomLowHealthPlayer?.playerUsername} fue diagnosticado con cancer tipo {Random.Range(3, 5)}. Hemos pagado el seguro.", 1f, 0, isGood: true, Generator.RandomNumber(-25, -8), delegate
			{
				int result2;
				if ((Object)(object)randomLowHealthPlayer != (Object)null)
				{
					PlayerControllerB obj3 = randomLowHealthPlayer;
					result2 = ((obj3 != null && obj3.health < 20) ? 1 : 0);
				}
				else
				{
					result2 = 0;
				}
				return (byte)result2 != 0;
			}),
			new EconomicEvent(randomLowHealthPlayer?.playerUsername + " ha perdido mucha sangre. Hemos tenido que pagar una transfusión.", 1f, 0, isGood: true, Generator.RandomNumber(-25, -8), delegate
			{
				int result;
				if ((Object)(object)randomLowHealthPlayer != (Object)null)
				{
					PlayerControllerB obj2 = randomLowHealthPlayer;
					result = ((obj2 != null && obj2.health < 20) ? 1 : 0);
				}
				else
				{
					result = 0;
				}
				return (byte)result != 0;
			}),
			new EconomicEvent(randomLowHealthPlayer?.playerUsername + " es el mejor guerrero de dios. La compañía le da un bono por su gran labor.", 1f, 0, isGood: true, Generator.RandomNumber(5, 15), () => (Object)(object)randomLowHealthPlayer != (Object)null),
			new EconomicEvent("Le hemos cobrado impuestos " + randomTypingChatPlayer?.playerUsername + " por utilizar el chat. Hoy en día ya nada es gratis.", 1f, 0, isGood: true, Generator.RandomNumber(-15, -5), () => (Object)(object)randomTypingChatPlayer != (Object)null),
			new EconomicEvent("Ha llegado a los oídos del jefe que " + randomDrowningDeadPlayer?.playerUsername + " se le ocurrió vivir como un pececito y no le salió bien. Os han multado.", 1f, 0, isGood: true, Generator.RandomNumber(-25, -10), () => (Object)(object)randomDrowningDeadPlayer != (Object)null),
			new EconomicEvent(randomInTerminalPlayer?.playerUsername + " ha usado mas electricidad en la Terminal que en su casa jugando este juego. ¡Hora de pagar la luz!", 1f, 0, isGood: true, Generator.RandomNumber(-25, -10), () => (Object)(object)randomInTerminalPlayer != (Object)null)
		});
		bool selectRareEvent = Random.value < 0.1f;
		List<EconomicEvent> list2 = list.Where((EconomicEvent e) => e.IsConditionMet() && e.isRare == selectRareEvent).ToList();
		if (list2.Count == 0)
		{
			EconomyMod.Logger.LogInfo((object)$"No se encontraron eventos que coincidieran con las condiciones. isRare: {selectRareEvent}");
			return;
		}
		EconomicEvent economicEvent = list2[Random.Range(0, list2.Count)];
		quotaMultiplier = Mathf.Clamp(quotaMultiplier * economicEvent.multiplier, 0.1f, 5f);
		daysToDeadlineExtension += economicEvent.daysExtension;
		daysToDeadlineExtension = Mathf.Clamp(daysToDeadlineExtension, -7, 7);
		string text = economicEvent.message;
		if (economicEvent.multiplier != 1f)
		{
			float num3 = (quotaMultiplier / num - 1f) * 100f;
			string text2 = num3.ToString("F0", CultureInfo.InvariantCulture);
			text = text + " Cuota " + ((num3 > 0f) ? "+" : "") + text2 + "%.";
		}
		if (economicEvent.daysExtension != 0)
		{
			text += string.Format(" Plazo: {0}{1} {2}", (economicEvent.daysExtension > 0) ? "+" : "", economicEvent.daysExtension, (Mathf.Abs(economicEvent.daysExtension) != 1) ? "días." : "día.");
		}
		if (economicEvent.quotaChange != 0)
		{
			text += string.Format(" Se {0} ${1} a tu cuenta.", (economicEvent.quotaChange > 0) ? "añadieron" : "restaron", economicEvent.quotaChange);
		}
		hudMessage = text;
		eventLog.Add($"Evento: {economicEvent.message} - Multiplicador: {quotaMultiplier}, Días extra: {daysToDeadlineExtension}, Cambio de Quota: {economicEvent.quotaChange}");
		EconomyMod.Logger.LogInfo((object)("Evento: " + text));
		EconomyModPatches.economicEvent.SendClients(economicEvent);
	}
}
public static class StringExtensions
{
	public static string RemoveDiacritics(this string text)
	{
		if (string.IsNullOrEmpty(text))
		{
			return text;
		}
		string text2 = text.Normalize(NormalizationForm.FormD);
		StringBuilder stringBuilder = new StringBuilder();
		string text3 = text2;
		foreach (char c in text3)
		{
			UnicodeCategory unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
			if (unicodeCategory != UnicodeCategory.NonSpacingMark)
			{
				stringBuilder.Append(c);
			}
		}
		return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
	}
}
public static class Generator
{
	private static readonly Random random = new Random();

	public static int RandomNumber(int minValue, int maxValue)
	{
		if (minValue >= maxValue)
		{
			throw new ArgumentException("minValue debe ser menor que maxValue");
		}
		return random.Next(minValue, maxValue + 1);
	}

	public static float RandomNumber(float minValue, float maxValue)
	{
		if (minValue >= maxValue)
		{
			throw new ArgumentException("minValue debe ser menor que maxValue");
		}
		double num = random.NextDouble();
		float num2 = (float)(num * (double)(maxValue - minValue) + (double)minValue);
		return (float)Math.Round(num2, 2);
	}

	public static int WeightedRandomNumber(int min, int max, int mode)
	{
		if (min >= max || mode < min || mode > max)
		{
			throw new ArgumentException("Invalid arguments");
		}
		double num = random.NextDouble();
		double a = ((!(num < (double)(mode - min) / (double)(max - min))) ? ((double)max - Math.Sqrt((1.0 - num) * (double)(max - mode) * (double)(max - min))) : ((double)min + Math.Sqrt(num * (double)(mode - min) * (double)(max - min))));
		return (int)Math.Round(a);
	}

	public static float WeightedRandomNumber(float min, float max, float mode)
	{
		if (min >= max || mode < min || mode > max)
		{
			throw new ArgumentException("Invalid arguments");
		}
		double num = random.NextDouble();
		double num2 = ((!(num < (double)(mode - min) / (double)(max - min))) ? ((double)max - Math.Sqrt((1.0 - num) * (double)(max - mode) * (double)(max - min))) : ((double)min + Math.Sqrt(num * (double)(mode - min) * (double)(max - min))));
		return (float)num2;
	}
}
public static class NumericExtensions
{
	public static T PercentageOf<T>(this T value, decimal percentage) where T : struct, IComparable, IFormattable, IConvertible
	{
		decimal num = Convert.ToDecimal(value);
		decimal num2 = num * (percentage / 100m);
		return (T)Convert.ChangeType(num2, typeof(T));
	}
}
public static class ProbabilityHelper
{
	public static bool Attempt(float probability)
	{
		if ((double)probability < 0.0 || (double)probability > 1.0)
		{
			throw new ArgumentOutOfRangeException("probability", "Probability must be between 0.0 and 1.0.");
		}
		Random random = new Random();
		double num = random.NextDouble();
		return num < (double)probability;
	}
}