using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using SpawnConfig.ExtendedClasses;
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: AssemblyCompany("Index154.SpawnConfig")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+04ce5db22d6ab11234845d01fd828f94c6058063")]
[assembly: AssemblyProduct("SpawnConfig")]
[assembly: AssemblyTitle("Index154.SpawnConfig")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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;
}
}
}
public class JsonManager
{
public static List<ExtendedGroupCounts> GetEGCListFromJSON(string path)
{
List<ExtendedGroupCounts> result = new List<ExtendedGroupCounts>();
if (File.Exists(path))
{
string text = File.ReadAllText(path);
if (text != null && text != "")
{
result = JsonConvert.DeserializeObject<List<ExtendedGroupCounts>>(text);
}
}
return result;
}
public static List<ExtendedEnemySetup> GetEESListFromJSON(string path)
{
List<ExtendedEnemySetup> result = new List<ExtendedEnemySetup>();
if (File.Exists(path))
{
string text = File.ReadAllText(path);
if (text != null && text != "")
{
result = JsonConvert.DeserializeObject<List<ExtendedEnemySetup>>(text);
}
}
return result;
}
public static string EESToJSON(List<ExtendedEnemySetup> eesList)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
StringBuilder stringBuilder = new StringBuilder();
StringWriter stringWriter = new StringWriter(stringBuilder);
JsonWriter val = (JsonWriter)new JsonTextWriter((TextWriter)stringWriter);
try
{
val.Formatting = (Formatting)1;
val.WriteStartArray();
foreach (ExtendedEnemySetup ees in eesList)
{
val.WriteStartObject();
val.WritePropertyName("name");
val.WriteValue(ees.name);
val.WritePropertyName("levelRangeCondition");
val.WriteValue(ees.levelRangeCondition);
val.WritePropertyName("minLevel");
val.WriteValue(ees.minLevel);
val.WritePropertyName("maxLevel");
val.WriteValue(ees.maxLevel);
val.WritePropertyName("runsPlayed");
val.WriteValue(ees.runsPlayed);
val.WritePropertyName("spawnObjects");
val.WriteStartArray();
foreach (string spawnObject in ees.spawnObjects)
{
val.WriteValue(spawnObject);
}
val.WriteEndArray();
val.WritePropertyName("difficulty1Weight");
val.WriteValue(ees.difficulty1Weight);
val.WritePropertyName("difficulty2Weight");
val.WriteValue(ees.difficulty2Weight);
val.WritePropertyName("difficulty3Weight");
val.WriteValue(ees.difficulty3Weight);
val.WritePropertyName("thisGroupOnly");
val.WriteValue(ees.thisGroupOnly);
val.WritePropertyName("alterAmountChance");
val.WriteValue(ees.alterAmountChance);
val.WritePropertyName("alterAmountMin");
val.WriteValue(ees.alterAmountMin);
val.WritePropertyName("alterAmountMax");
val.WriteValue(ees.alterAmountMax);
val.WriteEndObject();
}
val.WriteEndArray();
}
finally
{
((IDisposable)val)?.Dispose();
}
return stringBuilder.ToString();
}
public static string GroupCountsToJSON(List<ExtendedGroupCounts> gcList)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
StringBuilder stringBuilder = new StringBuilder();
StringWriter stringWriter = new StringWriter(stringBuilder);
JsonWriter val = (JsonWriter)new JsonTextWriter((TextWriter)stringWriter);
try
{
val.Formatting = (Formatting)1;
val.WriteStartArray();
foreach (ExtendedGroupCounts gc in gcList)
{
val.Formatting = (Formatting)1;
val.WriteStartObject();
val.WritePropertyName("level");
val.WriteValue(gc.level);
val.WritePropertyName("possibleGroupCounts");
val.WriteStartArray();
val.WriteStartArray();
val.Formatting = (Formatting)0;
val.WriteValue(gc.possibleGroupCounts[0][0]);
val.WriteValue(gc.possibleGroupCounts[0][1]);
val.WriteValue(gc.possibleGroupCounts[0][2]);
val.WriteEndArray();
val.Formatting = (Formatting)1;
val.WriteEndArray();
val.WriteEndObject();
}
val.WriteEndArray();
}
finally
{
((IDisposable)val)?.Dispose();
}
return stringBuilder.ToString();
}
}
namespace SpawnConfig
{
public class ConfigManager
{
internal ConfigEntry<bool> preventSpawns = null;
internal ConfigEntry<bool> addMissingGroups = null;
internal ConfigEntry<double> repeatMultiplier = null;
internal ConfigEntry<bool> ignoreInvalidGroups = null;
internal void Setup(ConfigFile configFile)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
preventSpawns = configFile.Bind<bool>("General", "Prevent enemy spawning", false, new ConfigDescription("Prevent enemy spawning entirely, turning the game into a no-stakes gathering simulator or for when you want to test something in peace", (AcceptableValueBase)null, Array.Empty<object>()));
addMissingGroups = configFile.Bind<bool>("General", "Re-add missing groups", true, new ConfigDescription("Whether the mod should update your custom SpawnGroups config at launch by adding all loaded enemy groups that are missing from it", (AcceptableValueBase)null, Array.Empty<object>()));
repeatMultiplier = configFile.Bind<double>("General", "Repeat spawn weight multiplier", 0.5, new ConfigDescription("All three weights of an enemy group will be multiplied by this value for the current level after having been selected once. Effectively reduces the chance of encountering multiple copies of the same group in one level. Set to 1.0 to \"disable\"", (AcceptableValueBase)null, Array.Empty<object>()));
ignoreInvalidGroups = configFile.Bind<bool>("General", "Ignore groups with invalid spawnObjects", true, new ConfigDescription("If set to true, any group containing a single invalid spawn object will be ignored completely. If set to false, only the individual spawn object will be ignored and the group can still spawn as long as it contains at least one valid enemy", (AcceptableValueBase)null, Array.Empty<object>()));
}
}
public class ListManager
{
public static Dictionary<string, EnemySetup> enemySetupsDict = new Dictionary<string, EnemySetup>();
public static Dictionary<string, GameObject> spawnObjectsDict = new Dictionary<string, GameObject>();
public static Dictionary<string, ExtendedEnemySetup> extendedSetups = new Dictionary<string, ExtendedEnemySetup>();
public static Dictionary<string, ExtendedSpawnObject> extendedSpawnObjects = new Dictionary<string, ExtendedSpawnObject>();
public static List<int> difficulty1Counts = new List<int>();
public static List<int> difficulty2Counts = new List<int>();
public static List<int> difficulty3Counts = new List<int>();
public static List<ExtendedGroupCounts> groupCountsList = new List<ExtendedGroupCounts>();
}
[BepInPlugin("Index154.SpawnConfig", "SpawnConfig", "1.1.1")]
public class SpawnConfig : BaseUnityPlugin
{
internal static ConfigManager configManager = null;
internal static ConfigFile Conf = null;
internal static readonly string configVersion = "1.0";
internal static readonly string exportPath = Path.Combine(Paths.ConfigPath, "SpawnConfig");
internal static readonly string spawnGroupsCfg = Path.Combine(exportPath, "SpawnGroups.json");
internal static readonly string explanationCfg = Path.Combine(exportPath, "SpawnGroups-Explained.json");
internal static readonly string defaultSpawnGroupsCfg = Path.Combine(exportPath, "Defaults", "SpawnGroups.json");
internal static readonly string groupsPerLevelCfg = Path.Combine(exportPath, "GroupsPerLevel.json");
internal static readonly string defaultGroupsPerLevelCfg = Path.Combine(exportPath, "Defaults", "GroupsPerLevel.json");
public static SpawnConfig Instance { get; private set; } = null;
internal static ManualLogSource Logger { get; private set; } = null;
internal static Harmony? Harmony { get; set; }
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
Instance = this;
configManager = new ConfigManager();
Conf = ((BaseUnityPlugin)this).Config;
configManager.Setup(((BaseUnityPlugin)this).Config);
Directory.CreateDirectory(exportPath);
Directory.CreateDirectory(Path.Combine(exportPath, "Defaults"));
Patch();
Logger.LogInfo((object)"Index154.SpawnConfig has loaded!");
}
internal static void Patch()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
if (Harmony == null)
{
Harmony = new Harmony("Index154.SpawnConfig");
}
Logger.LogDebug((object)"Patching...");
Harmony.PatchAll();
Logger.LogDebug((object)"Finished patching!");
}
internal static void Unpatch()
{
Logger.LogDebug((object)"Unpatching...");
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
Logger.LogDebug((object)"Finished unpatching!");
}
public static void ReadAndUpdateJSON()
{
List<ExtendedEnemyExplained> list = new List<ExtendedEnemyExplained>(1)
{
new ExtendedEnemyExplained()
};
File.WriteAllText(explanationCfg, JsonConvert.SerializeObject((object)list, (Formatting)1));
List<ExtendedEnemySetup> eESListFromJSON = JsonManager.GetEESListFromJSON(spawnGroupsCfg);
List<ExtendedGroupCounts> eGCListFromJSON = JsonManager.GetEGCListFromJSON(groupsPerLevelCfg);
bool flag = false;
List<ExtendedEnemySetup> eesList = ListManager.extendedSetups.Select<KeyValuePair<string, ExtendedEnemySetup>, ExtendedEnemySetup>((KeyValuePair<string, ExtendedEnemySetup> obj) => obj.Value).ToList();
File.WriteAllText(defaultSpawnGroupsCfg, JsonManager.EESToJSON(eesList));
if (eESListFromJSON.Count < 1)
{
Logger.LogInfo((object)"No custom spawn groups config found! Creating default file");
File.WriteAllText(spawnGroupsCfg, JsonManager.EESToJSON(eesList));
flag = true;
}
if (flag)
{
return;
}
foreach (ExtendedEnemySetup item in eESListFromJSON)
{
item.Update();
if (!ListManager.extendedSetups.ContainsKey(item.name))
{
}
}
Dictionary<string, ExtendedEnemySetup> dictionary = eESListFromJSON.ToDictionary((ExtendedEnemySetup obj) => obj.name);
foreach (KeyValuePair<string, ExtendedEnemySetup> extendedSetup in ListManager.extendedSetups)
{
if (!dictionary.ContainsKey(extendedSetup.Value.name) && configManager.addMissingGroups.Value)
{
Logger.LogInfo((object)("Adding missing entry to custom config: " + extendedSetup.Value.name));
dictionary.Add(extendedSetup.Value.name, extendedSetup.Value);
}
}
eESListFromJSON = dictionary.Values.ToList();
File.WriteAllText(spawnGroupsCfg, JsonManager.EESToJSON(eESListFromJSON));
ListManager.extendedSetups = eESListFromJSON.ToDictionary((ExtendedEnemySetup obj) => obj.name);
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "Index154.SpawnConfig";
public const string PLUGIN_NAME = "SpawnConfig";
public const string PLUGIN_VERSION = "1.1.1";
}
}
namespace SpawnConfig.Patches
{
[HarmonyPatch(typeof(EnemyDirector))]
public class EnemyDirectorPatch
{
public static bool setupDone = false;
public static int currentDifficultyPick = 3;
public static bool onlyOneSetup = false;
public static string PickEnemySimulation(List<EnemySetup> _enemiesList)
{
ListExtension.Shuffle<EnemySetup>((IList<EnemySetup>)_enemiesList);
EnemySetup val = null;
float num = -1f;
foreach (EnemySetup _enemies in _enemiesList)
{
float num2 = 100f;
if (Object.op_Implicit((Object)(object)_enemies.rarityPreset))
{
num2 = _enemies.rarityPreset.chance;
}
float num3 = Mathf.Max(0f, num2);
float num4 = Random.Range(0f, num3);
if (num4 > num)
{
val = _enemies;
num = num4;
}
}
return ((Object)val).name;
}
[HarmonyPatch("Start")]
[HarmonyPostfix]
public static void SetupOnStart(EnemyDirector __instance)
{
if (setupDone)
{
return;
}
List<EnemySetup>[] array = new List<EnemySetup>[3] { __instance.enemiesDifficulty3, __instance.enemiesDifficulty2, __instance.enemiesDifficulty1 };
int num = 3;
List<EnemySetup>[] array2 = array;
foreach (List<EnemySetup> list in array2)
{
foreach (EnemySetup item in list)
{
foreach (GameObject spawnObject in item.spawnObjects)
{
((Object)spawnObject).name = ((Object)spawnObject).name;
ExtendedSpawnObject extendedSpawnObject = new ExtendedSpawnObject(spawnObject);
if (!ListManager.spawnObjectsDict.ContainsKey(((Object)spawnObject).name))
{
ListManager.spawnObjectsDict.Add(((Object)spawnObject).name, spawnObject);
}
}
ExtendedEnemySetup extendedEnemySetup = new ExtendedEnemySetup(item, num);
if (!ListManager.extendedSetups.ContainsKey(((Object)item).name))
{
ListManager.extendedSetups.Add(extendedEnemySetup.name, extendedEnemySetup);
}
}
num--;
}
SpawnConfig.Logger.LogInfo((object)"Found the following enemy spawnObjects:");
foreach (KeyValuePair<string, GameObject> item2 in ListManager.spawnObjectsDict)
{
SpawnConfig.Logger.LogInfo((object)item2.Key);
}
for (float num2 = 0f; num2 < 1.1f; num2 += 0.1f)
{
ListManager.difficulty3Counts.Add((int)__instance.amountCurve3.Evaluate(num2));
ListManager.difficulty2Counts.Add((int)__instance.amountCurve2.Evaluate(num2));
ListManager.difficulty1Counts.Add((int)__instance.amountCurve1.Evaluate(num2));
}
for (int j = 0; j < ListManager.difficulty1Counts.Count; j++)
{
ListManager.groupCountsList.Add(new ExtendedGroupCounts(j));
}
SpawnConfig.ReadAndUpdateJSON();
List<string> list2 = new List<string>();
foreach (KeyValuePair<string, ExtendedEnemySetup> extendedSetup in ListManager.extendedSetups)
{
bool flag = false;
int num3 = 0;
List<int> list3 = new List<int>();
foreach (string spawnObject2 in extendedSetup.Value.spawnObjects)
{
if (!ListManager.spawnObjectsDict.ContainsKey(spawnObject2))
{
if (SpawnConfig.configManager.ignoreInvalidGroups.Value)
{
SpawnConfig.Logger.LogError((object)("Unable to resolve enemy name \"" + spawnObject2 + "\" in group \"" + extendedSetup.Value.name + "\"! This group will be ignored"));
flag = true;
}
else
{
SpawnConfig.Logger.LogError((object)("Unable to resolve enemy name \"" + spawnObject2 + "\" in group \"" + extendedSetup.Value.name + "\"! This enemy will be removed but the group can still spawn"));
list3.Add(num3);
}
}
num3++;
}
for (int num4 = list3.Count - 1; num4 > -1; num4--)
{
extendedSetup.Value.spawnObjects.RemoveAt(list3[num4]);
}
if (extendedSetup.Value.spawnObjects.Count < 1 && !flag)
{
flag = true;
SpawnConfig.Logger.LogError((object)("The group \"" + extendedSetup.Value.name + "\" contains no valid enemies! This group will be ignored"));
}
if (flag)
{
list2.Add(extendedSetup.Key);
}
}
foreach (string item3 in list2)
{
ListManager.extendedSetups.Remove(item3);
}
setupDone = true;
}
[HarmonyPatch("AmountSetup")]
[HarmonyPrefix]
public static void AmountSetupOverride(EnemyDirector __instance)
{
__instance.enemiesDifficulty1.Clear();
__instance.enemiesDifficulty2.Clear();
__instance.enemiesDifficulty3.Clear();
onlyOneSetup = false;
foreach (KeyValuePair<string, ExtendedEnemySetup> extendedSetup in ListManager.extendedSetups)
{
if (extendedSetup.Value.difficulty1Weight > 0f)
{
__instance.enemiesDifficulty1.Add(extendedSetup.Value.GetEnemySetup());
}
if (extendedSetup.Value.difficulty2Weight > 0f)
{
__instance.enemiesDifficulty2.Add(extendedSetup.Value.GetEnemySetup());
}
if (extendedSetup.Value.difficulty3Weight > 0f)
{
__instance.enemiesDifficulty3.Add(extendedSetup.Value.GetEnemySetup());
}
}
EnemySetup val = ScriptableObject.CreateInstance<EnemySetup>();
((Object)val).name = "Fallback";
val.spawnObjects = new List<GameObject>();
if (__instance.enemiesDifficulty1.Count < 1)
{
__instance.enemiesDifficulty1.Add(val);
}
if (__instance.enemiesDifficulty2.Count < 1)
{
__instance.enemiesDifficulty2.Add(val);
}
if (__instance.enemiesDifficulty3.Count < 1)
{
__instance.enemiesDifficulty3.Add(val);
}
}
[HarmonyPatch("PickEnemies")]
[HarmonyPrefix]
public static bool PickEnemiesOverride(List<EnemySetup> _enemiesList, EnemyDirector __instance)
{
if (_enemiesList == __instance.enemiesDifficulty1)
{
currentDifficultyPick = 1;
}
if (_enemiesList == __instance.enemiesDifficulty2)
{
currentDifficultyPick = 2;
}
if (_enemiesList == __instance.enemiesDifficulty3)
{
currentDifficultyPick = 3;
}
SpawnConfig.Logger.LogInfo((object)("Picking difficulty " + currentDifficultyPick + " setup..."));
SpawnConfig.Logger.LogInfo((object)"Enemy group weights:");
int num = DataDirector.instance.SettingValueFetch((Setting)31);
List<EnemySetup> list = new List<EnemySetup>();
float num2 = 0f;
foreach (EnemySetup _enemies in _enemiesList)
{
if ((!_enemies.levelsCompletedCondition || (RunManager.instance.levelsCompleted >= _enemies.levelsCompletedMin && RunManager.instance.levelsCompleted <= _enemies.levelsCompletedMax)) && num >= _enemies.runsPlayed)
{
float num3 = 1f;
if (ListManager.extendedSetups.ContainsKey(((Object)_enemies).name))
{
num3 = ListManager.extendedSetups[((Object)_enemies).name].GetWeight(currentDifficultyPick, __instance.enemyList);
}
if (!(num3 < 1f))
{
num2 += num3;
list.Add(_enemies);
SpawnConfig.Logger.LogInfo((object)(((Object)_enemies).name + " = " + num3));
}
}
}
EnemySetup val = null;
float num4 = Random.Range(1f, num2 + 1f);
SpawnConfig.Logger.LogInfo((object)("Selecting a group based on random number " + num4 + "..."));
foreach (EnemySetup item in list)
{
float num5 = 1f;
if (ListManager.extendedSetups.ContainsKey(((Object)item).name))
{
num5 = ListManager.extendedSetups[((Object)item).name].GetWeight(currentDifficultyPick, __instance.enemyList);
}
SpawnConfig.Logger.LogDebug((object)("=> " + ((Object)item).name + " = " + num5 + " / " + num4));
if (num5 >= num4)
{
SpawnConfig.Logger.LogInfo((object)("Selected: " + ((Object)item).name));
if (onlyOneSetup)
{
val = ScriptableObject.CreateInstance<EnemySetup>();
((Object)val).name = ((Object)item).name;
val.spawnObjects = new List<GameObject>();
}
else
{
val = item;
}
break;
}
num4 -= num5;
}
if (ListManager.extendedSetups.ContainsKey(((Object)val).name) && ListManager.extendedSetups[((Object)val).name].thisGroupOnly && !onlyOneSetup)
{
List<string> list2 = new List<string>();
int count = __instance.enemyList.Count;
foreach (EnemySetup enemy in __instance.enemyList)
{
list2.Add(((Object)enemy).name);
}
__instance.enemyList.Clear();
__instance.enemyList.Add(val);
onlyOneSetup = true;
for (int i = 0; i < count; i++)
{
EnemySetup val2 = ScriptableObject.CreateInstance<EnemySetup>();
((Object)val2).name = list2[i];
val2.spawnObjects = new List<GameObject>();
__instance.enemyList.Add(val2);
}
}
else
{
__instance.enemyList.Add(val);
}
return false;
}
}
[HarmonyPatch(typeof(LevelGenerator))]
public class LevelGeneratorPatch
{
public static int PickNonDirector(EnemySetup enemySetup)
{
int num = -1;
int num2 = 0;
int num3 = enemySetup.spawnObjects.Count;
while (num == -1)
{
int num4 = Random.Range(num2, num3);
if (!((Object)enemySetup.spawnObjects[num4]).name.Contains("Director"))
{
num = num4;
}
else if (num2 == num3)
{
num = num2;
}
else if (num4 == num2)
{
num2++;
}
else if (num4 == num3)
{
num3--;
}
}
return num;
}
[HarmonyPatch("EnemySpawn")]
[HarmonyPrefix]
public static void LogAndModifySpawns(EnemySetup enemySetup, Vector3 position, LevelGenerator __instance)
{
bool flag = false;
bool flag2 = false;
int num = 0;
foreach (GameObject spawnObject in enemySetup.spawnObjects)
{
if (((Object)spawnObject).name.Contains("Gnome") && !flag)
{
flag = true;
num++;
}
else if (((Object)spawnObject).name.Contains("Bang") && !flag2)
{
flag2 = true;
num++;
}
}
if (flag)
{
enemySetup.spawnObjects.Insert(0, ListManager.spawnObjectsDict["Enemy - Gnome Director"]);
}
if (flag2)
{
enemySetup.spawnObjects.Insert(0, ListManager.spawnObjectsDict["Enemy - Bang Director"]);
}
if (ListManager.extendedSetups.ContainsKey(((Object)enemySetup).name))
{
int num2 = (int)Math.Round(1.0 / ListManager.extendedSetups[((Object)enemySetup).name].alterAmountChance);
if (num2 < 1)
{
num2 = 1;
}
int num3 = Random.Range(1, num2 + 1);
if (num3 <= 1 && enemySetup.spawnObjects.Count > 0)
{
int i = Random.Range(ListManager.extendedSetups[((Object)enemySetup).name].alterAmountMin, ListManager.extendedSetups[((Object)enemySetup).name].alterAmountMax + 1);
if (i > 0)
{
while (i > 0)
{
enemySetup.spawnObjects.Add(enemySetup.spawnObjects[PickNonDirector(enemySetup)]);
i--;
}
}
else if (i < 0)
{
for (; i < 0; i++)
{
if (enemySetup.spawnObjects.Count <= 1)
{
break;
}
enemySetup.spawnObjects.RemoveAt(PickNonDirector(enemySetup));
}
}
}
}
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (GameObject spawnObject2 in enemySetup.spawnObjects)
{
if (dictionary.ContainsKey(((Object)spawnObject2).name))
{
dictionary[((Object)spawnObject2).name] = dictionary[((Object)spawnObject2).name] + 1;
}
else
{
dictionary.Add(((Object)spawnObject2).name, 1);
}
}
string text = "";
foreach (KeyValuePair<string, int> item in dictionary)
{
if (text != "")
{
text += ", ";
}
text = text + item.Key + " x " + item.Value;
}
if (text == "")
{
text = "No spawns or they were prevented for this level";
}
SpawnConfig.Logger.LogInfo((object)("Attempting to spawn: [" + ((Object)enemySetup).name + "] (" + text.Replace("Enemy - ", "") + ")"));
if (SpawnConfig.configManager.preventSpawns.Value)
{
enemySetup.spawnObjects.Clear();
SpawnConfig.Logger.LogInfo((object)"Forcibly prevented all spawns!");
}
}
}
}
namespace SpawnConfig.ExtendedClasses
{
public class ExtendedEnemyExplained
{
public string name = "Name of the enemy group. Must be unique";
public string levelRangeCondition = "Whether to apply the minLevel and maxLevel conditions to this enemy group (see fields below). Accepted values for this are false and true";
public string minLevel = "If levelRangeCondition is true then this group can not spawn on levels lower than this number";
public string maxLevel = "If levelRangeCondition is true then this group can not spawn on levels higher than this number";
public string runsPlayed = "The group can only spawn if the host player's total sum of runs played is larger than this number";
public string[] spawnObjects = new string[5] { "The name of an enemy that should be spawned when this group is picked", "Another one", "You can put as many as you want", "See the mod's description for a list of enemy names. Here's one valid example entry:", "Enemy - Hunter" };
public string difficulty1Weight = "The weight for the group to spawn in difficulty tier 1";
public string difficulty2Weight = "The weight for the group to spawn in difficulty tier 2";
public string difficulty3Weight = "The weight for the group to spawn in difficulty tier 3";
public string thisGroupOnly = "If this is set to true then this group being selected for spawning will prevent any other groups from spawning on the level";
public string alterAmountChance = "Chance for the group to have more or less enemies in it on a given level. A value of 0.5 is equivalent to 50% while 1.0 is 100% for example. Set to 0 to disable. If this chance triggers then the game will pick a random number between alterAmountMin and alterAmountMax (see below). The result determines how many enemies will be added to the group or how many will be removed from it (if the number is negative) for the duration of the current level. If your group has multiple types of enemies then it is random which of them you may get more or less of";
public string alterAmountMin = "Minimum number of enemies to add if alterAmountChance triggers. Make it a negative value to remove enemies";
public string alterAmountMax = "Maximum number of enemies to add if alterAmountChance triggers. Make it a negative value to remove enemies";
}
public class ExtendedEnemySetup
{
public string name = "Nameless";
public bool levelsCompletedCondition = false;
public int levelsCompletedMax = 10;
public int levelsCompletedMin = 0;
public bool levelRangeCondition = false;
public int minLevel = 0;
public int maxLevel = 0;
public int runsPlayed = 0;
public List<string> spawnObjects = new List<string>();
public float difficulty1Weight = 0f;
public float difficulty2Weight = 0f;
public float difficulty3Weight = 0f;
public bool thisGroupOnly = false;
public double alterAmountChance = 0.0;
public int alterAmountMin = 0;
public int alterAmountMax = 0;
public ExtendedEnemySetup()
{
}
public ExtendedEnemySetup(EnemySetup enemySetup, int difficulty)
{
name = ((Object)enemySetup).name;
if (enemySetup.levelsCompletedCondition)
{
levelRangeCondition = true;
minLevel = enemySetup.levelsCompletedMin + 1;
maxLevel = enemySetup.levelsCompletedMax + 1;
}
runsPlayed = enemySetup.runsPlayed;
spawnObjects = (from obj in enemySetup.spawnObjects
where !((Object)obj).name.Contains("Director")
select ((Object)obj).name).ToList();
float num = 100f;
if (Object.op_Implicit((Object)(object)enemySetup.rarityPreset))
{
if (enemySetup.rarityPreset.chance == 60f)
{
num = 1.5f;
}
SpawnConfig.Logger.LogDebug((object)(name + " = " + enemySetup.rarityPreset.chance));
}
difficulty1Weight = ((difficulty == 1) ? num : 0f);
difficulty2Weight = ((difficulty == 2) ? num : 0f);
difficulty3Weight = ((difficulty == 3) ? num : 0f);
}
public EnemySetup GetEnemySetup()
{
EnemySetup val = ScriptableObject.CreateInstance<EnemySetup>();
((Object)val).name = name;
val.spawnObjects = new List<GameObject>();
val.levelsCompletedCondition = levelRangeCondition;
val.levelsCompletedMin = minLevel - 1;
val.levelsCompletedMax = maxLevel - 1;
val.runsPlayed = runsPlayed;
foreach (string spawnObject in spawnObjects)
{
val.spawnObjects.Add(ListManager.spawnObjectsDict[spawnObject]);
}
return val;
}
public float GetWeight(int difficulty, List<EnemySetup> enemyList)
{
float num = difficulty1Weight;
switch (difficulty)
{
case 2:
num = difficulty2Weight;
break;
case 3:
num = difficulty3Weight;
break;
}
if (enemyList.Select((EnemySetup obj) => ((Object)obj).name).ToList().Contains(name))
{
num = (float)((double)num * SpawnConfig.configManager.repeatMultiplier.Value);
}
if (num < 0f)
{
num = 0f;
}
return num;
}
public void UpdateWithDefaults(ExtendedEnemySetup defaultSetup)
{
PropertyInfo[] properties = defaultSetup.GetType().GetProperties();
PropertyInfo[] array = properties;
foreach (PropertyInfo propertyInfo in array)
{
object value = propertyInfo.GetValue(defaultSetup);
object value2 = propertyInfo.GetValue(this);
object value3 = propertyInfo.GetValue(ListManager.extendedSetups[defaultSetup.name]);
if (value == value2 && value3 != value)
{
SpawnConfig.Logger.LogInfo((object)("Updating unmodified property " + propertyInfo?.ToString() + ": " + value?.ToString() + " => " + value3));
propertyInfo.SetValue(this, value3);
}
}
}
public void Update()
{
if (levelsCompletedCondition)
{
levelRangeCondition = true;
}
minLevel = levelsCompletedMin;
maxLevel = levelsCompletedMax;
if (!levelRangeCondition && maxLevel == 10)
{
maxLevel = 0;
}
levelsCompletedCondition = false;
}
}
public class ExtendedGroupCounts
{
public int level = 1;
public List<List<int>> possibleGroupCounts = new List<List<int>>();
public ExtendedGroupCounts(int i)
{
level = i + 1;
possibleGroupCounts.Add(new List<int>(3)
{
ListManager.difficulty1Counts[i],
ListManager.difficulty2Counts[i],
ListManager.difficulty3Counts[i]
});
}
}
public class ExtendedSpawnObject
{
public string name = "Nameless";
public bool disabled = false;
public int biggerGroupChance = 0;
public int groupIncreaseAmount = 0;
[JsonIgnore]
public bool alteredGroupSize = false;
public ExtendedSpawnObject(GameObject spawnObject)
{
name = ((Object)spawnObject).name;
}
public GameObject GetSpawnObject()
{
return ListManager.spawnObjectsDict[name];
}
}
}