using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using On;
using Repo_SpawnSystem.NetcodePatcher;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("MMHOOK_Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: AssemblyCompany("bcs4313")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("A weighted Enemy and Item spawn system, like the one in Lethal Company.")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+de30a7b4fd06f505c14721da353043ab3517b186")]
[assembly: AssemblyProduct("Repo_SpawnSystem")]
[assembly: AssemblyTitle("Repo_SpawnSystem")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
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 Repo_SpawnSystem
{
[BepInPlugin("Repo_SpawnSystem", "Repo_SpawnSystem", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public class EnemyConfig
{
public ConfigEntry<float> spawnBaseWeight;
public ConfigEntry<int> spawnLevelMin;
public ConfigEntry<int> spawnLevelMax;
public ConfigEntry<string> spawnLevelCurve;
public ConfigEntry<string> spawnRawCurve;
public EnemyConfig(ConfigFile cfg, EnemySetup enemy)
{
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Expected O, but got Unknown
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Expected O, but got Unknown
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01f7: Expected O, but got Unknown
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Expected O, but got Unknown
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_022f: Expected O, but got Unknown
//IL_025c: Unknown result type (might be due to invalid IL or missing references)
//IL_0266: Expected O, but got Unknown
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Expected O, but got Unknown
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
if ((Object)(object)enemy.rarityPreset != (Object)null)
{
if (enemy.rarityPreset.chance >= 0f && enemy.rarityPreset.chance <= 500f)
{
spawnBaseWeight = cfg.Bind<float>(((Object)enemy).name, ((Object)enemy).name + " base spawn weight", enemy.rarityPreset.chance, new ConfigDescription("Determines how 'common' the enemy is relative to others. The higher the number the more likely the enemy will spawn", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
}
else
{
spawnBaseWeight = cfg.Bind<float>(((Object)enemy).name, ((Object)enemy).name + " base spawn weight", 0f, new ConfigDescription("Determines how 'common' the enemy is relative to others. The higher the number the more likely the enemy will spawn", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
}
}
else
{
spawnBaseWeight = cfg.Bind<float>(((Object)enemy).name, ((Object)enemy).name + " base spawn weight", 100f, new ConfigDescription("Determines how 'common' the enemy is relative to others. The higher the number the more likely the enemy will spawn", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
}
spawnLevelMin = cfg.Bind<int>(((Object)enemy).name, ((Object)enemy).name + " min level to spawn in", enemy.levelsCompletedMin + 1, new ConfigDescription("The earliest level the enemy can spawn in, assuming the first level is level 1.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
if (enemy.levelsCompletedMax >= 8)
{
spawnLevelMax = cfg.Bind<int>(((Object)enemy).name, ((Object)enemy).name + " max level to spawn in", 100, new ConfigDescription("The highest level the enemy can spawn in, assuming the first level is level 1.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
}
else
{
spawnLevelMax = cfg.Bind<int>(((Object)enemy).name, ((Object)enemy).name + " max level to spawn in", enemy.levelsCompletedMax - 1, new ConfigDescription("The highest level the enemy can spawn in, assuming the first level is level 1.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
}
spawnLevelCurve = cfg.Bind<string>(((Object)enemy).name, ((Object)enemy).name + " spawn weight level curve", "1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0", new ConfigDescription("A custom level curve. Each comma separated number represents a multiplier to the enemy spawn weight. So 1.0,5.0,2.0 would mean 1x spawnrate for level one, 5x for level 2, and 2x for level 3 respectively. The multipliers will 'loop around' to starting values if the end is reached, keeping things fresh.", (AcceptableValueBase)null, Array.Empty<object>()));
spawnRawCurve = cfg.Bind<string>(((Object)enemy).name, ((Object)enemy).name + " spawn amount level curve", "0,0,0", new ConfigDescription("A custom level curve. Each comma separated number represents a fixed amount of spawns for the enemy (int). So 1,3,0 would force the enemy to spawn once on level 1, 3 times on level 2, and 0 times on level 3. The multipliers will 'loop around' to starting values if the end is reached, keeping things fresh. These spawns are additive, not taking away from the base enemy spawns.", (AcceptableValueBase)null, Array.Empty<object>()));
}
}
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static hook_PickEnemies <>9__11_0;
public static hook_AmountSetup <>9__11_1;
internal void <hookIntoEnemyDirector>b__11_0(orig_PickEnemies orig, EnemyDirector self, List<EnemySetup> _enemiesList)
{
orig.Invoke(self, _enemiesList);
LogDebug("REPO SpawnSystem: Overriding Enemy Director selections...");
self.enemyList.Clear();
float num = (float)spawnCurveBase.Value + spawnCurveAdditive.Value * (float)RunManager.instance.levelsCompleted;
int num2 = (int)Math.Round(num);
LogDebug("REPO SpawnSystem: Spawn Amount = " + num2);
List<EnemySetup> list = new List<EnemySetup>();
for (int i = 0; i < num2; i++)
{
self.enemyList.Add(SelectWeightedEnemySetup(RunManager.instance.levelsCompleted + 1, globalEnemyConfigs));
}
}
internal void <hookIntoEnemyDirector>b__11_1(orig_AmountSetup orig, EnemyDirector self)
{
orig.Invoke(self);
float num = (float)spawnCurveBase.Value + spawnCurveAdditive.Value * (float)RunManager.instance.levelsCompleted;
int num2 = (int)Math.Round(num);
int num3 = RunManager.instance.levelsCompleted + 1;
foreach (EnemyConfig globalEnemyConfig in globalEnemyConfigs)
{
string[] array = globalEnemyConfig.spawnRawCurve.Value.Split(',');
if (array.Length == 0)
{
continue;
}
int num4 = (num3 - 1) % array.Length;
if (!int.TryParse(array[num4].Trim(), out var result) || result <= 0)
{
continue;
}
for (int i = 0; i < result; i++)
{
EnemySetup val = FindEnemyByName(((ConfigEntryBase)globalEnemyConfig.spawnBaseWeight).Definition.Section);
if ((Object)(object)val != (Object)null)
{
self.enemyList.Add(val);
num2++;
}
}
}
self.totalAmount = num2;
}
}
public static Harmony _harmony;
public static ManualLogSource Logger;
public static List<EnemyConfig> globalEnemyConfigs;
public static ConfigEntry<int> spawnCurveBase;
public static ConfigEntry<float> spawnCurveAdditive;
public static void LogDebug(string text)
{
Logger.LogInfo((object)text);
}
public static void LogProduction(string text)
{
Logger.LogInfo((object)text);
}
private void Awake()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
spawnCurveBase = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy Spawn Rate Scaling", "Enemy Spawns Base Amount", 2, new ConfigDescription("Base amount of monsters to spawn in per level (flat quantity)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
spawnCurveAdditive = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy Spawn Rate Scaling", "Enemy Spawns Linear Scaling", 1f, new ConfigDescription("Adds additional monster spawns per level completed. Scales linearly (total spawns in level = base spawns + linear_scaling * levels_completed). Spawns round by the decimal, so a value of 2.55 would equal 3 monster spawns in game.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
Type[] array = types;
foreach (Type type in array)
{
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo[] array2 = methods;
foreach (MethodInfo methodInfo in array2)
{
object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
if (customAttributes.Length != 0)
{
methodInfo.Invoke(null, null);
}
}
}
Random.InitState((int)DateTime.Now.Ticks);
hookIntoEnemySetups();
hookIntoEnemyDirector();
Logger.LogInfo((object)"Plugin Repo_SpawnSystem is loaded!");
}
public void hookIntoEnemySetups()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
EnemyDirector.Awake += (hook_Awake)delegate(orig_Awake orig, EnemyDirector self)
{
orig.Invoke(self);
List<EnemySetup> list = new List<EnemySetup>();
foreach (EnemySetup item in self.enemiesDifficulty1)
{
if (!list.Contains(item))
{
list.Add(item);
}
}
foreach (EnemySetup item2 in self.enemiesDifficulty2)
{
if (!list.Contains(item2))
{
list.Add(item2);
}
}
foreach (EnemySetup item3 in self.enemiesDifficulty3)
{
if (!list.Contains(item3))
{
list.Add(item3);
}
}
globalEnemyConfigs = new List<EnemyConfig>();
foreach (EnemySetup item4 in list)
{
globalEnemyConfigs.Add(new EnemyConfig(((BaseUnityPlugin)this).Config, item4));
}
};
}
public static EnemySetup FindEnemyByName(string name)
{
List<EnemySetup>[] array = new List<EnemySetup>[3]
{
EnemyDirector.instance.enemiesDifficulty1,
EnemyDirector.instance.enemiesDifficulty2,
EnemyDirector.instance.enemiesDifficulty3
};
foreach (List<EnemySetup> list in array)
{
EnemySetup val = list.Find((EnemySetup e) => ((Object)e).name == name);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
return null;
}
public void hookIntoEnemyDirector()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
object obj = <>c.<>9__11_0;
if (obj == null)
{
hook_PickEnemies val = delegate(orig_PickEnemies orig, EnemyDirector self, List<EnemySetup> _enemiesList)
{
orig.Invoke(self, _enemiesList);
LogDebug("REPO SpawnSystem: Overriding Enemy Director selections...");
self.enemyList.Clear();
float num5 = (float)spawnCurveBase.Value + spawnCurveAdditive.Value * (float)RunManager.instance.levelsCompleted;
int num6 = (int)Math.Round(num5);
LogDebug("REPO SpawnSystem: Spawn Amount = " + num6);
List<EnemySetup> list = new List<EnemySetup>();
for (int j = 0; j < num6; j++)
{
self.enemyList.Add(SelectWeightedEnemySetup(RunManager.instance.levelsCompleted + 1, globalEnemyConfigs));
}
};
<>c.<>9__11_0 = val;
obj = (object)val;
}
EnemyDirector.PickEnemies += (hook_PickEnemies)obj;
object obj2 = <>c.<>9__11_1;
if (obj2 == null)
{
hook_AmountSetup val2 = delegate(orig_AmountSetup orig, EnemyDirector self)
{
orig.Invoke(self);
float num = (float)spawnCurveBase.Value + spawnCurveAdditive.Value * (float)RunManager.instance.levelsCompleted;
int num2 = (int)Math.Round(num);
int num3 = RunManager.instance.levelsCompleted + 1;
foreach (EnemyConfig globalEnemyConfig in globalEnemyConfigs)
{
string[] array = globalEnemyConfig.spawnRawCurve.Value.Split(',');
if (array.Length != 0)
{
int num4 = (num3 - 1) % array.Length;
if (int.TryParse(array[num4].Trim(), out var result) && result > 0)
{
for (int i = 0; i < result; i++)
{
EnemySetup val3 = FindEnemyByName(((ConfigEntryBase)globalEnemyConfig.spawnBaseWeight).Definition.Section);
if ((Object)(object)val3 != (Object)null)
{
self.enemyList.Add(val3);
num2++;
}
}
}
}
}
self.totalAmount = num2;
};
<>c.<>9__11_1 = val2;
obj2 = (object)val2;
}
EnemyDirector.AmountSetup += (hook_AmountSetup)obj2;
}
public static EnemySetup SelectWeightedEnemySetup(int currentLevel, List<EnemyConfig> spawnTargets)
{
List<(EnemyConfig, float)> list = new List<(EnemyConfig, float)>();
foreach (EnemyConfig spawnTarget in spawnTargets)
{
int value = spawnTarget.spawnLevelMin.Value;
int value2 = spawnTarget.spawnLevelMax.Value;
if (currentLevel < value || currentLevel > value2)
{
continue;
}
float num = 1f;
string[] array = spawnTarget.spawnLevelCurve.Value.Split(',');
if (array.Length != 0)
{
int num2 = (currentLevel - 1) % array.Length;
if (float.TryParse(array[num2], out var result))
{
num = result;
}
}
float num3 = spawnTarget.spawnBaseWeight.Value * num;
if (num3 > 0f)
{
list.Add((spawnTarget, num3));
}
}
if (list.Count == 0)
{
return null;
}
float num4 = 0f;
foreach (var item in list)
{
num4 += item.Item2;
}
float num5 = Random.Range(0f, num4);
foreach (var (enemyConfig, num6) in list)
{
if (num5 < num6)
{
string name = ((ConfigEntryBase)enemyConfig.spawnBaseWeight).Definition.Section;
List<EnemySetup>[] array2 = new List<EnemySetup>[3]
{
EnemyDirector.instance.enemiesDifficulty1,
EnemyDirector.instance.enemiesDifficulty2,
EnemyDirector.instance.enemiesDifficulty3
};
foreach (List<EnemySetup> list2 in array2)
{
EnemySetup val = list2.Find((EnemySetup e) => ((Object)e).name == name);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
return null;
}
num5 -= num6;
}
string fallbackName = ((ConfigEntryBase)list[Random.Range(0, list.Count)].Item1.spawnBaseWeight).Definition.Section;
List<EnemySetup>[] array3 = new List<EnemySetup>[3]
{
EnemyDirector.instance.enemiesDifficulty1,
EnemyDirector.instance.enemiesDifficulty2,
EnemyDirector.instance.enemiesDifficulty3
};
foreach (List<EnemySetup> list3 in array3)
{
EnemySetup val2 = list3.Find((EnemySetup e) => ((Object)e).name == fallbackName);
if ((Object)(object)val2 != (Object)null)
{
return val2;
}
}
return null;
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "Repo_SpawnSystem";
public const string PLUGIN_NAME = "Repo_SpawnSystem";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace Repo_Randomizer
{
public class EntityDestructionManager
{
public static List<GameObject> destroyOnLeave = new List<GameObject>();
public static List<GameObject> destroyOnFail = new List<GameObject>();
public EntityDestructionManager()
{
Debug.Log((object)"Lethal Chaos: Invoked Entity Destruction Manager");
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}
namespace Repo_SpawnSystem.NetcodePatcher
{
[AttributeUsage(AttributeTargets.Module)]
internal class NetcodePatchedAssemblyAttribute : Attribute
{
}
}