Decompiled source of SpawnWeightOverrides v2.0.0

SpawnWeightOverrides.dll

Decompiled 4 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalLevelLoader;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SpawnWeightOverrides")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2664facdac8ab07d4d1ce8abe8bb895a04038a1d")]
[assembly: AssemblyProduct("SpawnWeightOverrides")]
[assembly: AssemblyTitle("SpawnWeightOverrides")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 SpawnWeightOverrides
{
	public class ConfigManager
	{
		public static ConfigFile configFile;

		public static List<string> activeConfigs = new List<string>();

		public static void InitConfig()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, "SpawnWeightOverrides.cfg");
			configFile = new ConfigFile(text, true);
		}

		public static int MakeScrapPercentageConfig(string modName)
		{
			ConfigEntry<int> val = configFile.Bind<int>("(2. Scrap) " + modName + ": Spawn weights", "Percentage of original spawn weights", 100, "Percentage of the original spawn weights for all scrap items in mod: " + modName);
			if (val.Value >= 0)
			{
				return val.Value;
			}
			return -1;
		}

		public static bool MakeAddEnemyToAllLevelsConfig(string enemyName)
		{
			ConfigEntry<bool> val = configFile.Bind<bool>("(1. Enemy) " + enemyName, "Forcibly add enemy to all levels", false, "If true, this enemy will be added to all level spawn pools");
			return val.Value;
		}

		public static int MakeEnemyRarityConfig(string enemyName)
		{
			ConfigEntry<int> val = configFile.Bind<int>("(1. Enemy) " + enemyName, "Spawn weight for this enemy for all moons", -1, "Leave at -1 for default, any positive (or 0) integer otherwise");
			if (val.Value >= 0)
			{
				return val.Value;
			}
			return -1;
		}

		public static float MakePowerLevelConfig(string enemyName)
		{
			ConfigEntry<int> val = configFile.Bind<int>("(1. Enemy) " + enemyName, "Power level (number that affects how often all enemies spawn)", -1, "Leave blank for default, any positive nonzero integer otherwise.\n3 is standard for powerful enemies. Higher generally means you'll see less of this enemy, and less enemies in general");
			if (val.Value > 0)
			{
				return val.Value;
			}
			return -1f;
		}

		public static int MakeGroupSizeConfig(string enemyName)
		{
			ConfigEntry<int> val = configFile.Bind<int>("(1. Enemy) " + enemyName, "Group size (how many in each spawn)", -1, "Leave blank for default, any positive nonzero integer otherwise.\nNumber of this enemy that will spawn in each group\nOnly affects outdoor enemies");
			if (val.Value > 0)
			{
				return val.Value;
			}
			return -1;
		}

		public static int MakeMaxCountConfig(string enemyName)
		{
			ConfigEntry<int> val = configFile.Bind<int>("(1. Enemy) " + enemyName, "Max count (how many groups to spawn)", -1, "Leave blank for default, any positive nonzero integer otherwise\nMaximum number of groups of this enemy that can spawn in a day");
			if (val.Value > 0)
			{
				return val.Value;
			}
			return -1;
		}
	}
	public class EnemyRarity
	{
		public static List<string> LLEnemies = new List<string>();

		public static List<string> LLLEnemies = new List<string>();

		public static void GetEnemyInfo()
		{
			if (Plugin.LLExists)
			{
				GetEnemyInfoLL();
			}
			if (Plugin.LLLExists)
			{
				GetEnemyInfoLLL();
			}
		}

		public static void GetEnemyInfoLL()
		{
			foreach (SpawnableEnemy spawnableEnemy in Enemies.spawnableEnemies)
			{
				string enemyName = spawnableEnemy.enemy.enemyName;
				if (!LLEnemies.Contains(enemyName))
				{
					LLEnemies.Add(enemyName);
					ConfigManager.MakeEnemyRarityConfig(enemyName);
					ConfigManager.MakeMaxCountConfig(enemyName);
					ConfigManager.MakeGroupSizeConfig(enemyName);
					ConfigManager.MakePowerLevelConfig(enemyName);
					ConfigManager.MakeAddEnemyToAllLevelsConfig(enemyName);
				}
			}
		}

		public static void GetEnemyInfoLLL()
		{
			foreach (ExtendedMod extendedMod in PatchedContent.ExtendedMods)
			{
				foreach (ExtendedEnemyType extendedEnemyType in extendedMod.ExtendedEnemyTypes)
				{
					string enemyName = extendedEnemyType.EnemyType.enemyName;
					if (!LLLEnemies.Contains(enemyName))
					{
						LLLEnemies.Add(enemyName);
						ConfigManager.MakeEnemyRarityConfig(enemyName);
						ConfigManager.MakeMaxCountConfig(enemyName);
						ConfigManager.MakeGroupSizeConfig(enemyName);
						ConfigManager.MakePowerLevelConfig(enemyName);
						ConfigManager.MakeAddEnemyToAllLevelsConfig(enemyName);
					}
				}
			}
		}

		public static void ModifyEnemyValues()
		{
			if (Plugin.LLExists)
			{
				AddRequestedEnemiesToAllLevels(LLEnemies);
				MatchEnemiesAndModify(LLEnemies);
			}
			if (Plugin.LLLExists)
			{
				AddRequestedEnemiesToAllLevels(LLLEnemies);
				MatchEnemiesAndModify(LLLEnemies);
			}
		}

		public static void MatchEnemiesAndModify(List<string> moddedEnemies)
		{
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				List<List<SpawnableEnemyWithRarity>> list = new List<List<SpawnableEnemyWithRarity>>(3) { val.Enemies, val.OutsideEnemies, val.DaytimeEnemies };
				foreach (List<SpawnableEnemyWithRarity> item in list)
				{
					foreach (SpawnableEnemyWithRarity item2 in item)
					{
						if (moddedEnemies.Contains(item2.enemyType.enemyName))
						{
							Logs.Log.LogDebug((object)("Modifying enemy " + item2.enemyType.enemyName + " (" + ((moddedEnemies == LLEnemies) ? "LethalLib" : "LethalLevelLoader") + ") for " + val.PlanetName + "..."));
							UpdateRarityForLevel(item2);
							UpdateMaxCountForLevel(item2);
							UpdateGroupSizeForLevel(item2);
							UpdatePowerLevelForLevel(item2);
						}
					}
				}
			}
		}

		public static void UpdateRarityForLevel(SpawnableEnemyWithRarity spawnableEnemyWithRarity)
		{
			string enemyName = spawnableEnemyWithRarity.enemyType.enemyName;
			int num = ConfigManager.MakeEnemyRarityConfig(enemyName);
			if (num == -1)
			{
				Logs.Log.LogDebug((object)("Default or otherwise invalid rarity config entry used for '" + enemyName + "', using this EnemyType's defaults"));
				return;
			}
			int rarity = spawnableEnemyWithRarity.rarity;
			spawnableEnemyWithRarity.rarity = num;
			Logs.Log.LogDebug((object)$"Enemy {enemyName} (rarity: {rarity} -> {num})");
		}

		public static void UpdatePowerLevelForLevel(SpawnableEnemyWithRarity spawnableEnemyWithRarity)
		{
			string enemyName = spawnableEnemyWithRarity.enemyType.enemyName;
			float num = ConfigManager.MakePowerLevelConfig(enemyName);
			if (num < 0f)
			{
				Logs.Log.LogDebug((object)("Default or otherwise invalid power level config entry used for '" + enemyName + "', using this EnemyType's default"));
				return;
			}
			float powerLevel = spawnableEnemyWithRarity.enemyType.PowerLevel;
			spawnableEnemyWithRarity.enemyType.PowerLevel = num;
			Logs.Log.LogDebug((object)$"Enemy {enemyName} (power level: {powerLevel} -> {num})");
		}

		public static void UpdateGroupSizeForLevel(SpawnableEnemyWithRarity spawnableEnemyWithRarity)
		{
			string enemyName = spawnableEnemyWithRarity.enemyType.enemyName;
			int num = ConfigManager.MakeGroupSizeConfig(enemyName);
			if (num == -1)
			{
				Logs.Log.LogDebug((object)("Default or otherwise invalid group size config entry used for '" + enemyName + "', using this EnemyType's default"));
				return;
			}
			int spawnInGroupsOf = spawnableEnemyWithRarity.enemyType.spawnInGroupsOf;
			spawnableEnemyWithRarity.enemyType.spawnInGroupsOf = num;
			Logs.Log.LogDebug((object)$"Enemy {enemyName} (group size: {spawnInGroupsOf} -> {num})");
		}

		public static void UpdateMaxCountForLevel(SpawnableEnemyWithRarity spawnableEnemyWithRarity)
		{
			string enemyName = spawnableEnemyWithRarity.enemyType.enemyName;
			int num = ConfigManager.MakeMaxCountConfig(enemyName);
			if (num == -1)
			{
				Logs.Log.LogDebug((object)("Default or otherwise invalid max count config entry used for '" + enemyName + "', using this EnemyType's default"));
				return;
			}
			int maxCount = spawnableEnemyWithRarity.enemyType.MaxCount;
			spawnableEnemyWithRarity.enemyType.MaxCount = num;
			Logs.Log.LogDebug((object)$"Enemy {enemyName} (max count: {maxCount} -> {num})");
		}

		public static void AddRequestedEnemiesToAllLevels(List<string> moddedEnemies)
		{
			Dictionary<string, SpawnableEnemyWithRarity> dictionary = new Dictionary<string, SpawnableEnemyWithRarity>();
			List<string> list = new List<string>();
			foreach (string moddedEnemy in moddedEnemies)
			{
				if (ConfigManager.MakeAddEnemyToAllLevelsConfig(moddedEnemy))
				{
					list.Add(moddedEnemy);
				}
			}
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				List<List<SpawnableEnemyWithRarity>> list2 = new List<List<SpawnableEnemyWithRarity>>(3) { val.Enemies, val.OutsideEnemies, val.DaytimeEnemies };
				foreach (List<SpawnableEnemyWithRarity> item in list2)
				{
					foreach (SpawnableEnemyWithRarity item2 in item)
					{
						if (!dictionary.ContainsKey(item2.enemyType.enemyName))
						{
							dictionary.Add(item2.enemyType.enemyName, item2);
						}
					}
				}
			}
			SelectableLevel[] levels2 = StartOfRound.Instance.levels;
			foreach (SelectableLevel val2 in levels2)
			{
				List<List<SpawnableEnemyWithRarity>> list3 = new List<List<SpawnableEnemyWithRarity>>(3) { val2.Enemies, val2.OutsideEnemies, val2.DaytimeEnemies };
				int num = 0;
				foreach (List<SpawnableEnemyWithRarity> item3 in list3)
				{
					num++;
					List<string> list4 = new List<string>();
					foreach (SpawnableEnemyWithRarity item4 in item3)
					{
						list4.Add(item4.enemyType.enemyName);
					}
					foreach (string item5 in list)
					{
						if (!list4.Contains(item5) && dictionary.TryGetValue(item5, out var value))
						{
							if (num == 1 && !value.enemyType.isOutsideEnemy && !value.enemyType.isDaytimeEnemy)
							{
								item3.Add(value);
							}
							else if (num == 2 && value.enemyType.isOutsideEnemy)
							{
								item3.Add(value);
							}
							else if (num == 3 && value.enemyType.isDaytimeEnemy)
							{
								item3.Add(value);
							}
						}
					}
				}
			}
		}
	}
	public class ItemRarity
	{
		public static Dictionary<string, List<string>> LLScrapItems = new Dictionary<string, List<string>>();

		public static Dictionary<string, List<string>> LLLScrapItems = new Dictionary<string, List<string>>();

		public static void GetModdedScrapInfo()
		{
			if (Plugin.LLExists)
			{
				GetScrapInfoLL();
			}
			if (Plugin.LLLExists)
			{
				GetScrapInfoLLL();
			}
		}

		public static void ModifyAllLevelScrapRarity(string LLorLLL)
		{
			Dictionary<string, List<string>> dictionary = ((LLorLLL == "LL") ? LLScrapItems : LLLScrapItems);
			string text = ((LLorLLL == "LL") ? "LethalLib" : "LethalLevelLoader");
			foreach (KeyValuePair<string, List<string>> item in dictionary)
			{
				string key = item.Key;
				int num = ConfigManager.MakeScrapPercentageConfig(key);
				if (num == 100)
				{
					Logs.Log.LogDebug((object)("Default or otherwise invalid scrap rarity config entry used for '" + key + "' (" + text + "), using this item's defaults"));
					continue;
				}
				SelectableLevel[] levels = StartOfRound.Instance.levels;
				foreach (SelectableLevel val in levels)
				{
					foreach (SpawnableItemWithRarity item2 in val.spawnableScrap)
					{
						string text2 = GenerateItemID(item2.spawnableItem);
						foreach (string item3 in item.Value)
						{
							if (item3 == text2)
							{
								int rarity = item2.rarity;
								int num2 = (item2.rarity = (int)Math.Floor((double)rarity * ((double)num / 100.0)));
								Logs.Log.LogDebug((object)$"Scrap item in mod {key} ({text}) for {val.PlanetName}: {item2.spawnableItem.itemName} (rarity: {rarity} -> {num2})");
							}
						}
					}
				}
			}
		}

		public static void GetScrapInfoLL()
		{
			foreach (ScrapItem scrapItem in Items.scrapItems)
			{
				string modName = scrapItem.modName;
				string item = GenerateItemID(scrapItem.item);
				if (!LLScrapItems.ContainsKey(modName))
				{
					LLScrapItems[modName] = new List<string>();
					ConfigManager.MakeScrapPercentageConfig(modName);
				}
				LLScrapItems[modName].Add(item);
			}
		}

		public static void GetScrapInfoLLL()
		{
			foreach (ExtendedMod extendedMod in PatchedContent.ExtendedMods)
			{
				string modName = extendedMod.ModName;
				if (!LLLScrapItems.ContainsKey(modName))
				{
					LLLScrapItems[modName] = new List<string>();
					ConfigManager.MakeScrapPercentageConfig(modName);
				}
				foreach (ExtendedItem extendedItem in extendedMod.ExtendedItems)
				{
					LLLScrapItems[modName].Add(GenerateItemID(extendedItem.Item));
				}
			}
		}

		public static void ModifyScrapRarity()
		{
			if (Plugin.LLExists)
			{
				ModifyAllLevelScrapRarity("LL");
			}
			if (Plugin.LLLExists)
			{
				ModifyAllLevelScrapRarity("LLL");
			}
		}

		private static string GenerateItemID(Item item)
		{
			return item.itemName + item.weight + item.maxValue + item.minValue;
		}
	}
	public class Logs
	{
		public static ManualLogSource Log = Logger.CreateLogSource("SpawnWeightOverrides");
	}
	[HarmonyPatch]
	public class Patches
	{
		public static bool scrapIsModified;

		public static bool infoIsObtained;

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		[HarmonyAfter(new string[] { "imabatby.lethallevelloader", "evaisa.lethallib" })]
		public static void Patch_StartOfRound_Awake()
		{
			if (!infoIsObtained)
			{
				ItemRarity.GetModdedScrapInfo();
				EnemyRarity.GetEnemyInfo();
				infoIsObtained = true;
			}
		}

		[HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")]
		[HarmonyPrefix]
		[HarmonyBefore(new string[] { "imabatby.lethallevelloader" })]
		public static void Patch_RoundManager_SpawnScrapInLevel()
		{
			if (!scrapIsModified)
			{
				ItemRarity.ModifyScrapRarity();
				scrapIsModified = true;
			}
		}

		[HarmonyPatch(typeof(RoundManager), "BeginEnemySpawning")]
		[HarmonyPrefix]
		public static void Patch_RoundManager_BeginEnemySpawning()
		{
			EnemyRarity.ModifyEnemyValues();
		}
	}
	public static class PluginMetadata
	{
		public const string PLUGIN_VERSION = "2.0.0";

		public const string PLUGIN_NAME = "SpawnWeightOverrides";

		public const string PLUGIN_AUTHOR = "hoffr";

		public const string PLUGIN_GUID = "hoffr.SpawnWeightOverrides";
	}
	[BepInPlugin("hoffr.SpawnWeightOverrides", "SpawnWeightOverrides", "2.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("Lethal Company.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		public static bool LLExists;

		public static bool LLLExists;

		private void Awake()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (Chainloader.PluginInfos.ContainsKey("evaisa.lethallib"))
			{
				LLExists = true;
			}
			if (Chainloader.PluginInfos.ContainsKey("imabatby.lethallevelloader"))
			{
				LLLExists = true;
			}
			if (!LLExists && !LLLExists)
			{
				Logs.Log.LogInfo((object)"Neither LethalLib nor LethalLevelLoader are present, nothing to do this session.");
			}
			new Harmony("hoffr.SpawnWeightOverrides").PatchAll(Assembly.GetExecutingAssembly());
			Logs.Log.LogInfo((object)"SpawnWeightOverrides v2.0.0 loaded.");
			ConfigManager.InitConfig();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "SpawnWeightOverrides";

		public const string PLUGIN_NAME = "SpawnWeightOverrides";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}