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";
}
}