using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
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("LethalUnrandomizer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LethalUnrandomizer")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6c25caf0-1388-40bc-bddb-6fdbfa57c098")]
[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 LethalUnrandomizer
{
internal class ConfigHandler
{
private string keyframeSetRegex = "[0-9.]+:[0-9.]+$";
private ConfigEntry<bool> ForceWeatherCfg;
private ConfigEntry<int> ForcedWeatherTypeCfg;
private ConfigEntry<bool> ForceMeteorsCfg;
private ConfigEntry<bool> ForceInfestationsCfg;
private ConfigEntry<int> ForcedInfestationTypeCfg;
private ConfigEntry<bool> ForceLowestScrapValueCfg;
private ConfigEntry<bool> ForceLowestScrapAmountCfg;
private ConfigEntry<string> ChangeLandmineAmtKeyframesCfg;
private ConfigEntry<string> ChangeTurretAmtKeyframesCfg;
private ConfigEntry<string> ChangeSpikeTrapAmtKeyframesCfg;
private ConfigEntry<bool> ChangeLandmineSpawnrateCfg;
private ConfigEntry<bool> ChangeTurretSpawnrateCfg;
private ConfigEntry<bool> ChangeSpikeTrapSpawnrateCfg;
private ConfigEntry<bool> WorstLuckRandomLightningCfg;
internal bool ForceWeather
{
get
{
return ForceWeatherCfg.Value;
}
set
{
ForceWeatherCfg.Value = value;
}
}
internal int ForcedWeatherType
{
get
{
if (ForcedWeatherTypeCfg.Value < -1 || ForcedWeatherTypeCfg.Value > 5)
{
return (int)((ConfigEntryBase)ForcedWeatherTypeCfg).DefaultValue;
}
return ForcedWeatherTypeCfg.Value;
}
set
{
ForcedWeatherTypeCfg.Value = value;
}
}
internal bool ForceMeteors
{
get
{
return ForceMeteorsCfg.Value;
}
set
{
ForceMeteorsCfg.Value = value;
}
}
internal bool ForceInfestations
{
get
{
return ForceInfestationsCfg.Value;
}
set
{
ForceInfestationsCfg.Value = value;
}
}
internal int ForcedInfestationType
{
get
{
if (ForcedInfestationTypeCfg.Value < 0 || ForcedInfestationTypeCfg.Value > 2)
{
return (int)((ConfigEntryBase)ForcedInfestationTypeCfg).DefaultValue;
}
return ForcedInfestationTypeCfg.Value;
}
set
{
ForcedInfestationTypeCfg.Value = value;
}
}
internal bool ForceLowestScrapValue
{
get
{
return ForceLowestScrapValueCfg.Value;
}
set
{
ForceLowestScrapValueCfg.Value = value;
}
}
internal bool ForceLowestScrapAmount
{
get
{
return ForceLowestScrapAmountCfg.Value;
}
set
{
ForceLowestScrapAmountCfg.Value = value;
}
}
internal string ChangeLandmineAmtKeyframes
{
get
{
if (!Regex.IsMatch(ChangeLandmineAmtKeyframesCfg.Value, keyframeSetRegex))
{
return (string)((ConfigEntryBase)ChangeLandmineAmtKeyframesCfg).DefaultValue;
}
return ChangeLandmineAmtKeyframesCfg.Value;
}
set
{
ChangeLandmineAmtKeyframesCfg.Value = value;
}
}
internal string ChangeTurretAmtKeyframes
{
get
{
if (!Regex.IsMatch(ChangeTurretAmtKeyframesCfg.Value, keyframeSetRegex))
{
return (string)((ConfigEntryBase)ChangeTurretAmtKeyframesCfg).DefaultValue;
}
return ChangeTurretAmtKeyframesCfg.Value;
}
set
{
ChangeTurretAmtKeyframesCfg.Value = value;
}
}
internal string ChangeSpikeTrapAmtKeyframes
{
get
{
if (!Regex.IsMatch(ChangeSpikeTrapAmtKeyframesCfg.Value, keyframeSetRegex))
{
return (string)((ConfigEntryBase)ChangeSpikeTrapAmtKeyframesCfg).DefaultValue;
}
return ChangeSpikeTrapAmtKeyframesCfg.Value;
}
set
{
ChangeSpikeTrapAmtKeyframesCfg.Value = value;
}
}
internal bool ChangeLandmineSpawnrate
{
get
{
return ChangeLandmineSpawnrateCfg.Value;
}
set
{
ChangeLandmineSpawnrateCfg.Value = value;
}
}
internal bool ChangeTurretSpawnrate
{
get
{
return ChangeTurretSpawnrateCfg.Value;
}
set
{
ChangeTurretSpawnrateCfg.Value = value;
}
}
internal bool ChangeSpikeTrapSpawnrate
{
get
{
return ChangeSpikeTrapSpawnrateCfg.Value;
}
set
{
ChangeSpikeTrapSpawnrateCfg.Value = value;
}
}
internal bool WorstLuckRandomLightning
{
get
{
return WorstLuckRandomLightningCfg.Value;
}
set
{
WorstLuckRandomLightningCfg.Value = value;
}
}
public ConfigHandler(ConfigFile Config)
{
ForceWeatherCfg = Config.Bind<bool>("Weather Modifiers", "Force Weather", false, "Forces every moon to have weather type specified by 'forced weather type' (does NOT include FIRST DAY).");
ForcedWeatherTypeCfg = Config.Bind<int>("Weather Modifiers", "Forced Weather Type", 5, "Weather IDs: -1 = clear, 0 = dust clouds (unused), 1 = rainy, 2 = stormy, 3 = foggy, 4 = flooded, 5 = eclipse.");
ForceMeteorsCfg = Config.Bind<bool>("Special Event Modifiers", "Force Meteors", false, "Forces every day to have a meteor shower.");
ForceInfestationsCfg = Config.Bind<bool>("Special Event Modifiers", "Force Infestations", false, "Attempts to force every day to have a hording bug or nutcracker infestation specified by 'forced infestation type'. If the selected moon cannot spawn infested enemy type, the infestation will be canceled.");
ForcedInfestationTypeCfg = Config.Bind<int>("Special Event Modifiers", "Forced Infestation Type", 0, "Infestation Settings: 0 = random (25% nutcracker, 75% hording bug), 1 = nutcracker, 2 = hording bug.");
ForceLowestScrapValueCfg = Config.Bind<bool>("Inside Generation Modifiers", "Force Lowest Scrap Value", false, "Force all inside scrap to roll their minimum value.");
ForceLowestScrapAmountCfg = Config.Bind<bool>("Inside Generation Modifiers", "Force Lowest Scrap Amount", false, "Force all moons to roll their minimum scrap amount.");
ChangeLandmineAmtKeyframesCfg = Config.Bind<string>("Trap Spawning Modifiers", "Set Keyframes for Landmine Spawning", "0:5,1:20", "Set keyframes for landmine spawing. Make \"orderd pairs\" using the syntax '<time>:<value>' where '<time>' is a x-value (input) between 0-1 on the graph and '<value>' is a y-value (output) on the graph that represents the amount of landmines to spawn when randomly rolling the coressponding x-value. Use commas \",\" to seperate keyframes. EXAMPLE: \"0:10,1:20\" (when rolling a 0, 10 landmines spawn, when rolling a 0.5, 15 landmines spawn assuming linear interpolation and when rolling a 1, 20 landmines spawn)");
ChangeTurretAmtKeyframesCfg = Config.Bind<string>("Trap Spawning Modifiers", "Set Keyframes for Turret Spawning", "0:5,1:20", "Set keyframes for turret spawing. Make \"orderd pairs\" using the syntax '<time>:<value>' where '<time>' is a x-value (input) between 0-1 on the graph and '<value>' is a y-value (output) on the graph that represents the amount of turrets to spawn when randomly rolling the coressponding x-value. Use commas \",\" to seperate keyframes. EXAMPLE: \"0:10,1:20\" (when rolling a 0, 10 turrets spawn, when rolling a 0.5, 15 turrets spawn assuming linear interpolation and when rolling a 1, 20 turrets spawn)");
ChangeSpikeTrapAmtKeyframesCfg = Config.Bind<string>("Trap Spawning Modifiers", "Set Keyframes for Spike Trap Spawning", "0:5,1:20", "Set keyframes for spike trap spawing. Make \"orderd pairs\" using the syntax '<time>:<value>' where '<time>' is a x-value (input) between 0-1 on the graph and '<value>' is a y-value (output) on the graph that represents the amount of spike traps to spawn when randomly rolling the coressponding x-value. Use commas \",\" to seperate keyframes. EXAMPLE: \"0:10,1:20\" (when rolling a 0, 10 spike traps spawn, when rolling a 0.5, 15 spike traps spawn assuming linear interpolation and when rolling a 1, 20 spike traps spawn)");
ChangeLandmineSpawnrateCfg = Config.Bind<bool>("Trap Spawning Modifiers", "Enable Custom Landmine Spawnrate", false, "Enables / disables \"Set Keyframes for Landmine Spawning\"");
ChangeTurretSpawnrateCfg = Config.Bind<bool>("Trap Spawning Modifiers", "Enable Custom Turret Spawnrate", false, "Enables / disables \"Set Keyframes for Turret Spawning\"");
ChangeSpikeTrapSpawnrateCfg = Config.Bind<bool>("Trap Spawning Modifiers", "Enable Custom Spike Trap Spawnrate", false, "Enables / disables \"Set Keyframes for Spike Trap Spawning\"");
WorstLuckRandomLightningCfg = Config.Bind<bool>("Weather Modifiers", "Force Worst Luck Random Lightning", false, "Forces random lightning to always strike a player if it can (glitchy) and makes random lightning have as low of a cooldown as possible");
}
}
[BepInPlugin("Aliki.LethalUnrandomizer", "Lethal Unrandomizer", "0.1.0.0")]
public class UnrandomizerModBase : BaseUnityPlugin
{
private const string modGUID = "Aliki.LethalUnrandomizer";
private const string modName = "Lethal Unrandomizer";
private const string modVersion = "0.1.0.0";
private readonly Harmony harmonyOBJ = new Harmony("Aliki.LethalUnrandomizer");
internal static UnrandomizerModBase Instance;
internal ManualLogSource mlsOBJ;
internal ConfigHandler configHandlerOBJ;
internal RoundManager currentRound;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
mlsOBJ = Logger.CreateLogSource("Aliki.LethalUnrandomizer");
mlsOBJ.LogInfo((object)"Unrandomizer is awake and unrandomizing the randoms (._. )");
harmonyOBJ.PatchAll();
configHandlerOBJ = new ConfigHandler(((BaseUnityPlugin)this).Config);
}
}
}
namespace LethalUnrandomizer.Patches
{
[HarmonyPatch(typeof(RoundManager))]
internal class RoundManagerPatch
{
[HarmonyPatch("Start")]
[HarmonyPrefix]
private static void roundManagerReferenceFetchPatch(ref RoundManager __instance)
{
UnrandomizerModBase.Instance.currentRound = __instance;
}
[HarmonyPatch("RefreshEnemiesList")]
[HarmonyPostfix]
private static void infestationAndSetCurrentLevelPatch(ref SelectableLevel ___currentLevel, ref int ___enemyRushIndex, ref float ___currentMaxInsidePower)
{
if (!UnrandomizerModBase.Instance.configHandlerOBJ.ForceInfestations)
{
return;
}
Random random = new Random();
switch (UnrandomizerModBase.Instance.configHandlerOBJ.ForcedInfestationType)
{
case 0:
if (random.Next(0, 100) < 25)
{
___enemyRushIndex = infestIndex(___currentLevel, "Nutcracker");
if (___enemyRushIndex != -1)
{
___currentMaxInsidePower = 20f;
break;
}
___enemyRushIndex = infestIndex(___currentLevel, "Hoarding bug");
if (___enemyRushIndex != -1)
{
___currentMaxInsidePower = 30f;
}
}
else
{
___enemyRushIndex = infestIndex(___currentLevel, "Hoarding bug");
if (___enemyRushIndex != -1)
{
___currentMaxInsidePower = 30f;
}
}
break;
case 1:
___enemyRushIndex = infestIndex(___currentLevel, "Nutcracker");
if (___enemyRushIndex != -1)
{
___currentMaxInsidePower = 20f;
break;
}
___enemyRushIndex = infestIndex(___currentLevel, "Hoarding bug");
if (___enemyRushIndex != -1)
{
___currentMaxInsidePower = 30f;
}
break;
default:
___enemyRushIndex = infestIndex(___currentLevel, "Hoarding bug");
if (___enemyRushIndex != -1)
{
___currentMaxInsidePower = 30f;
}
break;
}
static int infestIndex(SelectableLevel currentLevel, string name)
{
int result = -1;
for (int i = 0; i < currentLevel.Enemies.Count; i++)
{
if (currentLevel.Enemies[i].enemyType.enemyName.Equals(name))
{
result = i;
break;
}
}
return result;
}
}
[HarmonyPatch("SpawnScrapInLevel")]
[HarmonyPrefix]
private static void setAllItemsMinValue(ref SelectableLevel ___currentLevel)
{
if (!UnrandomizerModBase.Instance.configHandlerOBJ.ForceLowestScrapValue)
{
return;
}
foreach (SpawnableItemWithRarity item in ___currentLevel.spawnableScrap)
{
item.spawnableItem.maxValue = item.spawnableItem.minValue;
}
}
[HarmonyPatch("SpawnScrapInLevel")]
[HarmonyPrefix]
private static void rollMinScrapAmount(ref SelectableLevel ___currentLevel)
{
if (UnrandomizerModBase.Instance.configHandlerOBJ.ForceLowestScrapAmount)
{
___currentLevel.maxScrap = ___currentLevel.minScrap;
}
}
[HarmonyPatch("SpawnMapObjects")]
[HarmonyPrefix]
private static void changeTrapCount(ref SelectableLevel ___currentLevel)
{
if (UnrandomizerModBase.Instance.configHandlerOBJ.ChangeLandmineSpawnrate)
{
mapObjAdjustKeyframes("landmine", UnrandomizerModBase.Instance.configHandlerOBJ.ChangeLandmineAmtKeyframes, ___currentLevel);
}
if (UnrandomizerModBase.Instance.configHandlerOBJ.ChangeTurretSpawnrate)
{
mapObjAdjustKeyframes("turretcontainer", UnrandomizerModBase.Instance.configHandlerOBJ.ChangeTurretAmtKeyframes, ___currentLevel);
}
if (UnrandomizerModBase.Instance.configHandlerOBJ.ChangeSpikeTrapSpawnrate)
{
mapObjAdjustKeyframes("spikerooftraphazard", UnrandomizerModBase.Instance.configHandlerOBJ.ChangeSpikeTrapAmtKeyframes, ___currentLevel);
}
}
public static void mapObjAdjustKeyframes(string objName, string keyframes, SelectableLevel currentLevel)
{
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
int num = -1;
for (int i = 0; i < currentLevel.spawnableMapObjects.Length; i++)
{
if (((Object)currentLevel.spawnableMapObjects[i].prefabToSpawn).name.ToLower().Replace(" ", "").Equals(objName))
{
num = i;
}
}
if (num != -1)
{
string[] array = keyframes.Split(",".ToCharArray());
Keyframe[] array2 = (Keyframe[])(object)new Keyframe[array.Length];
for (int j = 0; j < array2.Length; j++)
{
array2[j] = new Keyframe(float.Parse(array[j].Split(":".ToCharArray())[0]), float.Parse(array[j].Split(":".ToCharArray())[1]));
}
currentLevel.spawnableMapObjects[num].numberToSpawn.keys = array2;
}
}
}
[HarmonyPatch(typeof(StormyWeather))]
internal class StormyWeatherPatch
{
public static Random rand = new Random(39802);
[HarmonyPatch("DetermineNextStrikeInterval")]
[HarmonyPostfix]
private static void strikeIntervalPatch(ref float ___randomThunderTime, ref float ___timeAtLastStrike)
{
if (UnrandomizerModBase.Instance.configHandlerOBJ.WorstLuckRandomLightning)
{
___randomThunderTime = ___timeAtLastStrike;
___randomThunderTime += Mathf.Clamp(-1.25f, 0.6f, 110f) / Mathf.Clamp(TimeOfDay.Instance.currentWeatherVariable, 1f, 100f);
}
}
[HarmonyPatch("LightningStrikeRandom")]
[HarmonyPrefix]
private static bool randomStrikeSkipMethodPatch()
{
if (UnrandomizerModBase.Instance.configHandlerOBJ.WorstLuckRandomLightning)
{
return false;
}
return true;
}
[HarmonyPatch("LightningStrikeRandom")]
[HarmonyPostfix]
private static void randomStrikeTargetsPlayerPatch(ref StormyWeather __instance)
{
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_0257: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Unknown result type (might be due to invalid IL or missing references)
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
//IL_0233: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_0241: Unknown result type (might be due to invalid IL or missing references)
//IL_0248: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: Unknown result type (might be due to invalid IL or missing references)
if (!UnrandomizerModBase.Instance.configHandlerOBJ.WorstLuckRandomLightning)
{
return;
}
GameObject[] allPlayerObjects = StartOfRound.Instance.allPlayerObjects;
PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
int[] array = new int[3];
for (int i = 0; i < array.Length; i++)
{
if (!allPlayerScripts[i].isInsideFactory && !allPlayerScripts[i].isPlayerDead && allPlayerScripts[i].AllowPlayerDeath())
{
array[i] = i;
}
else
{
array[i] = -1;
}
}
int num = rand.Next(0, array.Length);
int num2 = 0;
while (array[num] == -1)
{
num = rand.Next(0, array.Length);
num2++;
if (num2 > 10)
{
array[0] = 0;
num = 0;
break;
}
}
Vector3 val = allPlayerObjects[array[num]].transform.position;
Vector3 position = UnrandomizerModBase.Instance.currentRound.GetClosestNode(val, true).position;
if (Math.Sqrt(Math.Pow(val.x - position.x, 2.0) + Math.Pow(val.z - position.z, 2.0)) > 15.0)
{
Vector2 val2 = default(Vector2);
((Vector2)(ref val2))..ctor(val.x - position.x, val.z - position.z);
Vector2 val3 = default(Vector2);
((Vector2)(ref val3))..ctor((float)Math.Sign(val2.x), (float)Math.Sign(val2.y));
double num3 = (Math.Pow(val2.x, 2.0) + Math.Pow(val2.y, 2.0)) / Math.Pow(15.0, 2.0);
Vector2 val4 = new Vector2((float)Math.Sqrt(Math.Pow(val2.x, 2.0) / num3), (float)Math.Sqrt(Math.Pow(val2.y, 2.0) / num3)) * val3;
val = position + new Vector3(val4.x, 0f, val4.y);
}
__instance.LightningStrike(val, false);
}
}
[HarmonyPatch(typeof(TimeOfDay))]
internal class TimeOfDayPatch
{
[HarmonyPatch("DecideRandomDayEvents")]
[HarmonyPrefix]
private static void meteorPatch(ref int ___overrideMeteorChance)
{
if (UnrandomizerModBase.Instance.configHandlerOBJ.ForceMeteors)
{
___overrideMeteorChance = 1000;
}
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal class StartOfRoundPatch
{
[HarmonyPatch("SetPlanetsWeather")]
[HarmonyPostfix]
private static void weatherPatch(ref SelectableLevel[] ___levels)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (UnrandomizerModBase.Instance.configHandlerOBJ.ForceWeather)
{
SelectableLevel[] array = ___levels;
foreach (SelectableLevel val in array)
{
val.currentWeather = (LevelWeatherType)UnrandomizerModBase.Instance.configHandlerOBJ.ForcedWeatherType;
}
}
}
}
}