using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
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 GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using com.github.zehsteam.CoilHeadSettings.Data;
using com.github.zehsteam.CoilHeadSettings.Dependencies;
using com.github.zehsteam.CoilHeadSettings.Patches;
[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("com.github.zehsteam.CoilHeadSettings")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("This mod lets you configure the CoilHead enemy. Power Level, Movement Speed, Attack Damage, Attack Speed, Probability Curve, and per moon Spawn Weight and Max Spawn Count. (StarlancerAIFix compatibility to configure spawning inside and outside)")]
[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly: AssemblyInformationalVersion("2.0.1+2e426ebe7f73baa2baa90d59e45f720a6944edff")]
[assembly: AssemblyProduct("CoilHeadSettings")]
[assembly: AssemblyTitle("com.github.zehsteam.CoilHeadSettings")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace com.github.zehsteam.CoilHeadSettings
{
internal static class ConfigHelper
{
public static void SkipAutoGen()
{
if (LethalConfigProxy.Enabled)
{
LethalConfigProxy.SkipAutoGen();
}
}
public static ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, bool requiresRestart, string description, AcceptableValueBase acceptableValues = null, Action<T> settingChanged = null, ConfigFile configFile = null)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
if (configFile == null)
{
configFile = ((BaseUnityPlugin)Plugin.Instance).Config;
}
ConfigEntry<T> configEntry = ((acceptableValues == null) ? configFile.Bind<T>(section, key, defaultValue, description) : configFile.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, Array.Empty<object>())));
if (settingChanged != null)
{
configEntry.SettingChanged += delegate
{
settingChanged?.Invoke(configEntry.Value);
};
}
if (LethalConfigProxy.Enabled)
{
if (acceptableValues == null)
{
LethalConfigProxy.AddConfig<T>(configEntry, requiresRestart);
}
else
{
LethalConfigProxy.AddConfigSlider<T>(configEntry, requiresRestart);
}
}
return configEntry;
}
public static void AddButton(string section, string name, string description, string buttonText, Action callback)
{
if (LethalConfigProxy.Enabled)
{
LethalConfigProxy.AddButton(section, name, description, buttonText, callback);
}
}
public static Dictionary<ConfigDefinition, string> GetOrphanedConfigEntries(ConfigFile configFile = null)
{
if (configFile == null)
{
configFile = ((BaseUnityPlugin)Plugin.Instance).Config;
}
PropertyInfo property = ((object)configFile).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
return (Dictionary<ConfigDefinition, string>)property.GetValue(configFile, null);
}
public static void SetConfigEntryValue<T>(ConfigEntry<T> configEntry, string value)
{
if (typeof(T) == typeof(int) && int.TryParse(value, out var result))
{
configEntry.Value = (T)(object)result;
return;
}
if (typeof(T) == typeof(float) && float.TryParse(value, out var result2))
{
configEntry.Value = (T)(object)result2;
return;
}
if (typeof(T) == typeof(double) && double.TryParse(value, out var result3))
{
configEntry.Value = (T)(object)result3;
return;
}
if (typeof(T) == typeof(bool) && bool.TryParse(value, out var result4))
{
configEntry.Value = (T)(object)result4;
return;
}
if (typeof(T) == typeof(string))
{
configEntry.Value = (T)(object)value;
return;
}
throw new InvalidOperationException($"Unsupported type: {typeof(T)}");
}
public static void ClearUnusedEntries(ConfigFile configFile = null)
{
if (configFile == null)
{
configFile = ((BaseUnityPlugin)Plugin.Instance).Config;
}
Dictionary<ConfigDefinition, string> orphanedConfigEntries = GetOrphanedConfigEntries(configFile);
if (orphanedConfigEntries != null)
{
orphanedConfigEntries.Clear();
configFile.Save();
}
}
}
internal class ConfigManager
{
public ConfigEntry<bool> General_ExtendedLogging { get; private set; }
public ConfigEntry<float> Enemy_PowerLevel { get; private set; }
public ConfigEntry<float> Enemy_MovementSpeed { get; private set; }
public ConfigEntry<int> Enemy_AttackDamage { get; private set; }
public ConfigEntry<float> Enemy_AttackSpeed { get; private set; }
public ConfigEntry<string> Enemy_ProbabilityCurve { get; private set; }
public ConfigManager()
{
BindConfigs();
SetupChangedEvents();
MigrateOldConfigSettings();
}
private void BindConfigs()
{
ConfigHelper.SkipAutoGen();
General_ExtendedLogging = ConfigHelper.Bind("General", "ExtendedLogging", defaultValue: false, requiresRestart: false, "Enable extended logging.");
Enemy_PowerLevel = ConfigHelper.Bind("Enemy", "PowerLevel", 1f, requiresRestart: false, "The power level of Coil-Head.");
Enemy_MovementSpeed = ConfigHelper.Bind("Enemy", "MovementSpeed", 14.5f, requiresRestart: false, "The movement speed of Coil-Head.");
Enemy_AttackDamage = ConfigHelper.Bind("Enemy", "AttackDamage", 90, requiresRestart: false, "The attack damage of Coil-Head.");
Enemy_AttackSpeed = ConfigHelper.Bind("Enemy", "AttackSpeed", 5f, requiresRestart: false, "The number of times Coil-Head will attack per second.");
Enemy_ProbabilityCurve = ConfigHelper.Bind("Enemy", "ProbabilityCurve", "1.0, 1.0, 1.0", requiresRestart: false, "Determines how likely Coil-Head is to spawn throughout the day. Accepts an array of floats with each entry separated by a comma.");
}
private void SetupChangedEvents()
{
Enemy_PowerLevel.SettingChanged += Enemy_PowerLevel_SettingChanged;
Enemy_MovementSpeed.SettingChanged += delegate
{
SpringManAIPatch.SettingsChanged();
};
Enemy_ProbabilityCurve.SettingChanged += Enemy_ProbabilityCurve_SettingChanged;
}
private void Enemy_PowerLevel_SettingChanged(object sender, EventArgs e)
{
EnemyHelper.SetPowerLevel("Spring", Enemy_PowerLevel.Value);
}
private void Enemy_ProbabilityCurve_SettingChanged(object sender, EventArgs e)
{
EnemyHelper.SetProbabilityCurve("Spring", Utils.ToFloatsArray(Enemy_ProbabilityCurve.Value));
}
private void MigrateOldConfigSettings()
{
foreach (KeyValuePair<ConfigDefinition, string> orphanedConfigEntry in ConfigHelper.GetOrphanedConfigEntries())
{
MigrateOldConfigSetting(orphanedConfigEntry.Key.Section, orphanedConfigEntry.Key.Key, orphanedConfigEntry.Value);
}
}
private void MigrateOldConfigSetting(string section, string key, string value)
{
if (section == "General Settings")
{
if (key == "ExtendedLogging")
{
ConfigHelper.SetConfigEntryValue<bool>(General_ExtendedLogging, value);
}
}
if (section == "Coil-Head Settings")
{
switch (key)
{
case "PowerLevel":
ConfigHelper.SetConfigEntryValue<float>(Enemy_PowerLevel, value);
break;
case "MovementSpeed":
ConfigHelper.SetConfigEntryValue<float>(Enemy_MovementSpeed, value);
break;
case "AttackDamage":
ConfigHelper.SetConfigEntryValue<int>(Enemy_AttackDamage, value);
break;
case "AttackSpeed":
ConfigHelper.SetConfigEntryValue<float>(Enemy_AttackSpeed, value);
break;
}
}
}
}
internal static class EnemyDataManager
{
public const string EnemyName = "Spring";
public const string EnemyDisplayName = "Coil-Head";
private static bool _initialized;
public static List<EnemyData> EnemyDataList { get; private set; } = new List<EnemyData>();
public static void Initialize()
{
if (!_initialized)
{
_initialized = true;
InitializeEnemyDataList();
}
}
private static void InitializeEnemyDataList()
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Plugin.Logger.LogError((object)"Failed to initialize enemy data list. StartOfRound Instance is null. (EnemyName: \"Spring\")");
return;
}
EnemyType enemyType = EnemyHelper.GetEnemyType("Spring");
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)"Failed to initialize enemy data list. EnemyType is null. (EnemyName: \"Spring\")");
return;
}
enemyType.PowerLevel = Plugin.ConfigManager.Enemy_PowerLevel.Value;
EnemyHelper.SetProbabilityCurve("Spring", Utils.ToFloatsArray(Plugin.ConfigManager.Enemy_ProbabilityCurve.Value));
SelectableLevel[] levels = StartOfRound.Instance.levels;
foreach (SelectableLevel val in levels)
{
if (val.spawnEnemiesAndScrap)
{
AddEnemyData(val);
}
}
foreach (EnemyData enemyData in EnemyDataList)
{
int value = enemyData.ConfigData.SpawnWeight.Value;
if (enemyData.ConfigData.SpawnInside == null || enemyData.ConfigData.SpawnInside.Value)
{
LevelHelper.AddEnemyToLevel(enemyData.PlanetName, "Spring", value, EnemyListType.Inside);
}
else
{
LevelHelper.RemoveEnemyFromLevel(enemyData.PlanetName, "Spring", EnemyListType.Inside);
}
if (enemyData.ConfigData.SpawnOutside != null && enemyData.ConfigData.SpawnOutside.Value)
{
LevelHelper.AddEnemyToLevel(enemyData.PlanetName, "Spring", value, EnemyListType.Outside);
}
else
{
LevelHelper.RemoveEnemyFromLevel(enemyData.PlanetName, "Spring", EnemyListType.Outside);
}
}
ConfigHelper.ClearUnusedEntries();
}
public static void AddEnemyData(SelectableLevel level)
{
if (HasEnemyData(level.PlanetName))
{
Plugin.Logger.LogWarning((object)("Failed to add enemy data for level \"" + level.PlanetName + "\". Enemy data already exists for SelectableLevel."));
return;
}
EnemyType enemyType = EnemyHelper.GetEnemyType("Spring");
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to add enemy data for level \"" + level.PlanetName + "\". EnemyType is null"));
return;
}
int spawnWeight;
bool flag = LevelHelper.LevelHasEnemy(level.PlanetName, "Spring", EnemyListType.Inside, out spawnWeight);
int spawnWeight2;
bool flag2 = LevelHelper.LevelHasEnemy(level.PlanetName, "Spring", EnemyListType.Outside, out spawnWeight2);
int spawnWeight3 = 0;
if (flag && flag2)
{
spawnWeight3 = Mathf.Max(spawnWeight, spawnWeight2);
}
else if (flag)
{
spawnWeight3 = spawnWeight;
}
else if (flag2)
{
spawnWeight3 = spawnWeight2;
}
EnemyConfigDataDefault defaultConfigValues = new EnemyConfigDataDefault(spawnWeight3, enemyType.MaxCount, flag, flag2);
EnemyData enemyData = new EnemyData(level.PlanetName, defaultConfigValues);
enemyData.BindConfigs();
EnemyDataList.Add(enemyData);
}
public static EnemyData GetEnemyData(string planetName)
{
foreach (EnemyData enemyData in EnemyDataList)
{
if (enemyData.PlanetName == planetName)
{
return enemyData;
}
}
return null;
}
public static bool HasEnemyData(string planetName)
{
return GetEnemyData(planetName) != null;
}
public static void SetEnemyDataForCurrentLevel()
{
EnemyData enemyData = GetEnemyData(LevelHelper.CurrentPlanetName);
if (enemyData == null)
{
Plugin.Logger.LogError((object)("Failed to set enemy data for current level. EnemyData is null. (PlanetName: \"" + LevelHelper.CurrentPlanetName + "\")"));
}
else
{
EnemyHelper.SetMaxSpawnCount("Spring", enemyData.ConfigData.MaxSpawnCount.Value, LevelHelper.CurrentPlanetName);
}
}
}
public enum EnemyListType
{
Inside,
Outside,
Daytime
}
internal static class EnemyHelper
{
public static void SetPowerLevel(string enemyName, float powerLevel)
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to set enemy power level. StartOfRound Instance is null. (EnemyName: \"{enemyName}\", PowerLevel: {powerLevel})");
return;
}
EnemyType enemyType = GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to set enemy power level. EnemyType is null. (EnemyName: \"{enemyName}\", PowerLevel: {powerLevel})");
return;
}
enemyType.PowerLevel = powerLevel;
Plugin.Instance.LogInfoExtended($"Set enemy power level. (EnemyName: \"{enemyName}\", PowerLevel: {powerLevel})");
}
public static void SetSpawnWeight(string enemyName, int spawnWeight, EnemyListType enemyListType, string planetName)
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to set enemy spawn weight. StartOfRound Instance is null. (EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)}, PlanetName: \"{planetName}\")");
return;
}
EnemyType enemyType = GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to set enemy spawn weight. EnemyType is null. (EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)}, PlanetName: \"{planetName}\")");
return;
}
SelectableLevel levelByName = LevelHelper.GetLevelByName(planetName);
if ((Object)(object)levelByName == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to set enemy spawn weight. SelectableLevel is null. (EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)}, PlanetName: \"{planetName}\")");
return;
}
if (!LevelHelper.LevelHasEnemy(planetName, enemyName, enemyListType))
{
Plugin.Logger.LogError((object)$"Failed to set enemy spawn weight. SelectableLevel does not contain enemy. (EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)}, PlanetName: \"{planetName}\")");
return;
}
List<SpawnableEnemyWithRarity> enemyList = LevelHelper.GetEnemyList(levelByName, enemyListType);
foreach (SpawnableEnemyWithRarity item in enemyList)
{
if ((Object)(object)item.enemyType == (Object)(object)enemyType)
{
item.rarity = spawnWeight;
break;
}
}
Plugin.Instance.LogInfoExtended($"Set enemy spawn weight. (EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)}, PlanetName: \"{planetName}\")");
}
public static void SetMaxSpawnCount(string enemyName, int maxSpawnCount, string planetName)
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to set enemy max spawn count. StartOfRound Instance is null. (EnemyName: \"{enemyName}\", MaxSpawnCount: {maxSpawnCount}, PlanetName: \"{planetName}\")");
return;
}
if (!LevelHelper.IsCurrentLevel(planetName))
{
Plugin.Logger.LogError((object)$"Failed to set enemy max spawn count. Planet name is not the current planet name. (EnemyName: \"{enemyName}\", MaxSpawnCount: {maxSpawnCount}, PlanetName: \"{planetName}\")");
return;
}
EnemyType enemyType = GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to set enemy max spawn count. EnemyType is null. (EnemyName: \"{enemyName}\", MaxSpawnCount: {maxSpawnCount}, PlanetName: \"{planetName}\")");
return;
}
enemyType.MaxCount = maxSpawnCount;
Plugin.Instance.LogInfoExtended($"Set enemy max spawn count. (EnemyName: \"{enemyName}\", MaxSpawnCount: {maxSpawnCount}, PlanetName: \"{planetName}\")");
}
public static void SetProbabilityCurve(string enemyName, float[] values)
{
if (values == null)
{
Plugin.Logger.LogError((object)("Failed to set enemy probability curve. Values are null. (EnemyName: \"" + enemyName + "\")"));
return;
}
if (values.Length == 0)
{
Plugin.Logger.LogError((object)("Failed to set enemy probability curve. Values are empty. (EnemyName: \"" + enemyName + "\")"));
return;
}
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to set enemy probability curve. StartOfRound Instance is null. (EnemyName: \"" + enemyName + "\", Values: " + string.Join(", ", values) + ")"));
return;
}
EnemyType enemyType = GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to set enemy probability curve. EnemyType is null. (EnemyName: \"" + enemyName + "\", Values: " + string.Join(", ", values) + ")"));
return;
}
AnimationCurve val = Utils.CreateAnimationCurve(values);
if (val == null)
{
Plugin.Logger.LogError((object)("Failed to set enemy probability curve. AnimationCurve is invalid. (EnemyName: \"" + enemyName + "\", Values: " + string.Join(", ", values) + ")"));
}
else
{
enemyType.probabilityCurve = val;
Plugin.Instance.LogInfoExtended("Set enemy probability curve. (EnemyName: \"" + enemyName + "\", Values: " + string.Join(", ", values) + ")");
}
}
public static EnemyType GetEnemyType(string enemyName)
{
foreach (EnemyType enemyType in GetEnemyTypes())
{
if (enemyType.enemyName == enemyName)
{
return enemyType;
}
}
try
{
EnemyType val = Resources.FindObjectsOfTypeAll<EnemyType>().Single((EnemyType x) => x.enemyName == enemyName);
if (IsValidEnemyType(val) && NetworkUtils.IsNetworkPrefab(val.enemyPrefab))
{
Plugin.Instance.LogInfoExtended("Found EnemyType \"" + val.enemyName + "\" from Resources.");
return val;
}
}
catch
{
}
return null;
}
public static List<EnemyType> GetEnemyTypes()
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
return new List<EnemyType>();
}
HashSet<EnemyType> hashSet = new HashSet<EnemyType>(new EnemyTypeComparer());
SelectableLevel[] levels = StartOfRound.Instance.levels;
foreach (SelectableLevel val in levels)
{
IEnumerable<EnemyType> enumerable = (from e in val.Enemies.Concat(val.DaytimeEnemies).Concat(val.OutsideEnemies)
select e.enemyType).Where(IsValidEnemyType);
foreach (EnemyType item in enumerable)
{
hashSet.Add(item);
}
}
return hashSet.ToList();
}
public static bool IsValidEnemyType(EnemyType enemyType)
{
if ((Object)(object)enemyType == (Object)null)
{
return false;
}
if (string.IsNullOrWhiteSpace(enemyType.enemyName))
{
return false;
}
if ((Object)(object)enemyType.enemyPrefab == (Object)null)
{
return false;
}
return true;
}
}
public class EnemyTypeComparer : IEqualityComparer<EnemyType>
{
public bool Equals(EnemyType x, EnemyType y)
{
if ((Object)(object)x == (Object)null || (Object)(object)y == (Object)null)
{
return false;
}
return x.enemyName == y.enemyName;
}
public int GetHashCode(EnemyType obj)
{
return obj.enemyName?.GetHashCode() ?? 0;
}
}
internal static class LevelHelper
{
public static string CurrentPlanetName
{
get
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Plugin.Logger.LogError((object)"Failed to get current planet name. StartOfRound Instance is null.");
return string.Empty;
}
return StartOfRound.Instance.currentLevel.PlanetName;
}
}
public static SelectableLevel GetLevelByName(string planetName)
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
return null;
}
SelectableLevel[] levels = StartOfRound.Instance.levels;
foreach (SelectableLevel val in levels)
{
if (val.PlanetName == planetName)
{
return val;
}
}
return null;
}
public static bool IsCurrentLevel(string planetName)
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to check is current level. StartOfRound Instance is null. (PlanetName: \"" + planetName + "\")"));
return false;
}
return StartOfRound.Instance.currentLevel.PlanetName == planetName;
}
public static List<SpawnableEnemyWithRarity> GetEnemyList(SelectableLevel level, EnemyListType enemyListType)
{
if ((Object)(object)level == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to get enemy list. SelectableLevel is null. (EnemyListType: " + Utils.GetEnumName(enemyListType) + ")"));
return new List<SpawnableEnemyWithRarity>();
}
if (1 == 0)
{
}
List<SpawnableEnemyWithRarity> result = enemyListType switch
{
EnemyListType.Inside => level.Enemies,
EnemyListType.Outside => level.OutsideEnemies,
EnemyListType.Daytime => level.DaytimeEnemies,
_ => new List<SpawnableEnemyWithRarity>(),
};
if (1 == 0)
{
}
return result;
}
public static bool LevelHasEnemy(string planetName, string enemyName, EnemyListType enemyListType)
{
int spawnWeight;
return LevelHasEnemy(planetName, enemyName, enemyListType, out spawnWeight);
}
public static bool LevelHasEnemy(string planetName, string enemyName, EnemyListType enemyListType, out int spawnWeight)
{
spawnWeight = 0;
SelectableLevel levelByName = GetLevelByName(planetName);
if ((Object)(object)levelByName == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to check if level has enemy. SelectableLevel is null. (PlanetName: \"" + planetName + "\", EnemyName: \"" + enemyName + "\", EnemyListType: " + Utils.GetEnumName(enemyListType) + ")"));
return false;
}
EnemyType enemyType = EnemyHelper.GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to check if level has enemy. EnemyType is null. (PlanetName: \"" + planetName + "\", EnemyName: \"" + enemyName + "\", EnemyListType: " + Utils.GetEnumName(enemyListType) + ")"));
return false;
}
List<SpawnableEnemyWithRarity> enemyList = GetEnemyList(levelByName, enemyListType);
foreach (SpawnableEnemyWithRarity item in enemyList)
{
if ((Object)(object)item.enemyType == (Object)(object)enemyType)
{
spawnWeight = item.rarity;
return true;
}
}
return false;
}
public static void AddEnemyToLevel(string planetName, string enemyName, int spawnWeight, EnemyListType enemyListType)
{
//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_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Expected O, but got Unknown
if (LevelHasEnemy(planetName, enemyName, enemyListType))
{
Plugin.Instance.LogWarningExtended($"Failed to add enemy to level. SelectableLevel already contains enemy. (PlanetName: \"{planetName}\", EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)})");
return;
}
SelectableLevel levelByName = GetLevelByName(planetName);
if ((Object)(object)levelByName == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to add enemy to level. SelectableLevel is null. (PlanetName: \"{planetName}\", EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)})");
return;
}
EnemyType enemyType = EnemyHelper.GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)$"Failed to add enemy to level. EnemyType is null. (PlanetName: \"{planetName}\", EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)})");
return;
}
List<SpawnableEnemyWithRarity> enemyList = GetEnemyList(levelByName, enemyListType);
SpawnableEnemyWithRarity item = new SpawnableEnemyWithRarity
{
enemyType = enemyType,
rarity = spawnWeight
};
enemyList.Add(item);
Plugin.Instance.LogInfoExtended($"Added enemy to level. (PlanetName: \"{planetName}\", EnemyName: \"{enemyName}\", SpawnWeight: {spawnWeight}, EnemyListType: {Utils.GetEnumName(enemyListType)})");
}
public static void RemoveEnemyFromLevel(string planetName, string enemyName, EnemyListType enemyListType)
{
if (!LevelHasEnemy(planetName, enemyName, enemyListType))
{
Plugin.Instance.LogWarningExtended("Failed to remove enemy from level. SelectableLevel does not contain enemy. (PlanetName: \"" + planetName + "\", EnemyName: \"" + enemyName + "\", EnemyListType: " + Utils.GetEnumName(enemyListType) + ")");
return;
}
SelectableLevel levelByName = GetLevelByName(planetName);
if ((Object)(object)levelByName == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to remove enemy from level. SelectableLevel is null. (PlanetName: \"" + planetName + "\", EnemyName: \"" + enemyName + "\", EnemyListType: " + Utils.GetEnumName(enemyListType) + ")"));
return;
}
EnemyType enemyType = EnemyHelper.GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.Logger.LogError((object)("Failed to remove enemy from level. EnemyType is null. (PlanetName: \"" + planetName + "\", EnemyName: \"" + enemyName + "\", EnemyListType: " + Utils.GetEnumName(enemyListType) + ")"));
return;
}
List<SpawnableEnemyWithRarity> enemyList = GetEnemyList(levelByName, enemyListType);
int num = -1;
for (int i = 0; i < enemyList.Count; i++)
{
if ((Object)(object)enemyList[i].enemyType == (Object)(object)enemyType)
{
num = i;
break;
}
}
if (num <= -1)
{
Plugin.Instance.LogWarningExtended("Failed to remove enemy from level. Could not find EnemyType in SelectableLevel. (PlanetName: \"" + planetName + "\", EnemyName: \"" + enemyName + "\", EnemyListType: " + Utils.GetEnumName(enemyListType) + ")");
}
else
{
enemyList.RemoveAt(num);
Plugin.Instance.LogInfoExtended("Removed enemy from level. (PlanetName: \"" + planetName + "\", EnemyName: \"" + enemyName + "\", EnemyListType: " + Utils.GetEnumName(enemyListType) + ")");
}
}
}
internal static class NetworkUtils
{
public static bool IsServer
{
get
{
if ((Object)(object)NetworkManager.Singleton == (Object)null)
{
return false;
}
return NetworkManager.Singleton.IsServer;
}
}
public static bool IsHost
{
get
{
if ((Object)(object)NetworkManager.Singleton == (Object)null)
{
return false;
}
return NetworkManager.Singleton.IsHost;
}
}
public static ulong GetLocalClientId()
{
return NetworkManager.Singleton.LocalClientId;
}
public static bool IsLocalClientId(ulong clientId)
{
return clientId == GetLocalClientId();
}
public static bool IsNetworkPrefab(GameObject prefab)
{
foreach (NetworkPrefab prefab2 in NetworkManager.Singleton.NetworkConfig.Prefabs.Prefabs)
{
if ((Object)(object)prefab2.Prefab == (Object)(object)prefab)
{
return true;
}
}
return false;
}
}
[BepInPlugin("com.github.zehsteam.CoilHeadSettings", "CoilHeadSettings", "2.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class Plugin : BaseUnityPlugin
{
private readonly Harmony _harmony = new Harmony("com.github.zehsteam.CoilHeadSettings");
internal static Plugin Instance { get; private set; }
internal static ManualLogSource Logger { get; private set; }
internal static ConfigManager ConfigManager { get; private set; }
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
Logger = Logger.CreateLogSource("com.github.zehsteam.CoilHeadSettings");
Logger.LogInfo((object)"CoilHeadSettings has awoken!");
_harmony.PatchAll(typeof(StartOfRoundPatch));
_harmony.PatchAll(typeof(RoundManagerPatch));
_harmony.PatchAll(typeof(EnemyAIPatch));
_harmony.PatchAll(typeof(SpringManAIPatch));
ConfigManager = new ConfigManager();
}
public void LogInfoExtended(object data)
{
if (ConfigManager.General_ExtendedLogging.Value)
{
Logger.LogInfo(data);
}
}
public void LogWarningExtended(object data)
{
if (ConfigManager.General_ExtendedLogging.Value)
{
Logger.LogWarning(data);
}
}
}
public static class Utils
{
public static string GetEnumName(object e)
{
try
{
return Enum.GetName(e.GetType(), e);
}
catch
{
return string.Empty;
}
}
public static AnimationCurve CreateAnimationCurve(float[] values)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
if (values == null || values.Length == 0)
{
return null;
}
AnimationCurve val = new AnimationCurve();
if (values.Length == 1)
{
val.AddKey(new Keyframe(0f, values[0]));
val.AddKey(new Keyframe(1f, values[0]));
return val;
}
float num = 1f / (float)values.Length - 1f;
for (int i = 0; i < values.Length; i++)
{
float num2 = Mathf.Clamp(num * (float)i, 0f, 1f);
val.AddKey(num2, values[i]);
}
return val;
}
public static float[] ToFloatsArray(string text)
{
if (string.IsNullOrWhiteSpace(text))
{
return Array.Empty<float>();
}
List<float> list = new List<float>();
string[] array = (from x in text.Split(',')
select x.Trim()).ToArray();
string[] array2 = array;
foreach (string s in array2)
{
if (float.TryParse(s, out var result))
{
list.Add(result);
}
}
return list.ToArray();
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.github.zehsteam.CoilHeadSettings";
public const string PLUGIN_NAME = "CoilHeadSettings";
public const string PLUGIN_VERSION = "2.0.1";
}
}
namespace com.github.zehsteam.CoilHeadSettings.Patches
{
[HarmonyPatch(typeof(EnemyAI))]
internal static class EnemyAIPatch
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void StartPatch(ref EnemyAI __instance)
{
EnemyAI obj = __instance;
SpringManAI val = (SpringManAI)(object)((obj is SpringManAI) ? obj : null);
if ((Object)(object)val != (Object)null)
{
SpringManAIPatch.Start(val);
}
}
}
[HarmonyPatch(typeof(RoundManager))]
internal static class RoundManagerPatch
{
[HarmonyPatch("LoadNewLevel")]
[HarmonyPostfix]
private static void LoadNewLevelPatch()
{
EnemyDataManager.SetEnemyDataForCurrentLevel();
}
}
[HarmonyPatch(typeof(SpringManAI))]
internal static class SpringManAIPatch
{
private static int _attackDamage => Plugin.ConfigManager.Enemy_AttackDamage.Value;
private static float _hitPlayerTimer => 1f / Plugin.ConfigManager.Enemy_AttackSpeed.Value;
public static void Start(SpringManAI springManAI)
{
if (!((Object)(object)springManAI == (Object)null))
{
springManAI.currentChaseSpeed = Plugin.ConfigManager.Enemy_MovementSpeed.Value;
}
}
[HarmonyPatch("OnCollideWithPlayer")]
[HarmonyPrefix]
private static bool OnCollideWithPlayerPatch(ref SpringManAI __instance, Collider other)
{
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
if (!__instance.stoppingMovement && ((EnemyAI)__instance).currentBehaviourStateIndex == 1 && !(__instance.hitPlayerTimer >= 0f) && !__instance.setOnCooldown && !((double)(Time.realtimeSinceStartup - __instance.timeAtLastCooldown) < 0.45))
{
PlayerControllerB val = ((EnemyAI)__instance).MeetsStandardPlayerCollisionConditions(other, false, false);
if ((Object)(object)val != (Object)null)
{
__instance.hitPlayerTimer = _hitPlayerTimer;
val.DamagePlayer(_attackDamage, true, true, (CauseOfDeath)6, 2, false, default(Vector3));
val.JumpToFearLevel(1f, true);
__instance.timeSinceHittingPlayer = Time.realtimeSinceStartup;
}
}
return false;
}
public static void SettingsChanged()
{
SpringManAI[] array = Object.FindObjectsByType<SpringManAI>((FindObjectsSortMode)0);
foreach (SpringManAI val in array)
{
val.currentChaseSpeed = Plugin.ConfigManager.Enemy_MovementSpeed.Value;
}
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal static class StartOfRoundPatch
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void StartPatch()
{
EnemyDataManager.Initialize();
}
}
}
namespace com.github.zehsteam.CoilHeadSettings.Dependencies
{
internal static class LethalConfigProxy
{
public const string PLUGIN_GUID = "ainavt.lc.lethalconfig";
public static bool Enabled => Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig");
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void SkipAutoGen()
{
LethalConfigManager.SkipAutoGen();
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void AddConfig<T>(ConfigEntry<T> configEntry, bool requiresRestart = false)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Expected O, but got Unknown
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
if (!(configEntry is ConfigEntry<string> val))
{
if (!(configEntry is ConfigEntry<bool> val2))
{
if (!(configEntry is ConfigEntry<float> val3))
{
if (!(configEntry is ConfigEntry<int> val4))
{
throw new NotSupportedException($"Unsupported type: {typeof(T)}");
}
LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(val4, requiresRestart));
}
else
{
LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(val3, requiresRestart));
}
}
else
{
LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(val2, requiresRestart));
}
}
else
{
LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(val, requiresRestart));
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void AddConfigSlider<T>(ConfigEntry<T> configEntry, bool requiresRestart = false)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
if (!(configEntry is ConfigEntry<float> val))
{
if (!(configEntry is ConfigEntry<int> val2))
{
throw new NotSupportedException($"Slider not supported for type: {typeof(T)}");
}
LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(val2, requiresRestart));
}
else
{
LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(val, requiresRestart));
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void AddButton(string section, string name, string description, string buttonText, Action callback)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem(section, name, description, buttonText, (GenericButtonHandler)delegate
{
callback?.Invoke();
}));
}
}
internal static class StarlancerAIFixProxy
{
public const string PLUGIN_GUID = "AudioKnight.StarlancerAIFix";
public static bool Enabled => Chainloader.PluginInfos.ContainsKey("AudioKnight.StarlancerAIFix");
}
}
namespace com.github.zehsteam.CoilHeadSettings.Data
{
public class EnemyConfigData
{
public EnemyConfigDataDefault DefaultValues { get; private set; }
public ConfigEntry<int> SpawnWeight { get; private set; }
public ConfigEntry<int> MaxSpawnCount { get; private set; }
public ConfigEntry<bool> SpawnInside { get; private set; }
public ConfigEntry<bool> SpawnOutside { get; private set; }
public EnemyData EnemyData { get; private set; }
public EnemyConfigData()
{
DefaultValues = new EnemyConfigDataDefault();
}
public EnemyConfigData(EnemyConfigDataDefault defaultValues)
{
DefaultValues = defaultValues;
}
public void BindConfigs(EnemyData enemyData)
{
if (DefaultValues == null)
{
EnemyConfigDataDefault enemyConfigDataDefault2 = (DefaultValues = new EnemyConfigDataDefault());
}
if (enemyData != null)
{
EnemyData = enemyData;
string planetName = EnemyData.PlanetName;
SpawnWeight = ConfigHelper.Bind(planetName, "SpawnWeight", DefaultValues.SpawnWeight, requiresRestart: false, "The spawn weight of Coil-Head.");
MaxSpawnCount = ConfigHelper.Bind(planetName, "MaxSpawnCount", DefaultValues.MaxSpawnCount, requiresRestart: false, "The max amount of Coil-Head that can spawn.");
SpawnWeight.SettingChanged += SpawnWeight_SettingChanged;
MaxSpawnCount.SettingChanged += MaxSpawnCount_SettingChanged;
if (StarlancerAIFixProxy.Enabled)
{
SpawnInside = ConfigHelper.Bind(planetName, "SpawnInside", DefaultValues.SpawnInside, requiresRestart: false, "If enabled, Coil-Head will be able to spawn inside.");
SpawnOutside = ConfigHelper.Bind(planetName, "SpawnOutside", DefaultValues.SpawnOutside, requiresRestart: false, "If enabled, Coil-Head will be able to spawn outside.");
SpawnInside.SettingChanged += SpawnInside_SettingChanged;
SpawnOutside.SettingChanged += SpawnOutside_SettingChanged;
}
}
}
private void SpawnWeight_SettingChanged(object sender, EventArgs e)
{
if (SpawnInside == null || SpawnInside.Value)
{
EnemyHelper.SetSpawnWeight("Spring", SpawnWeight.Value, EnemyListType.Inside, EnemyData.PlanetName);
}
if (SpawnOutside != null && SpawnOutside.Value)
{
EnemyHelper.SetSpawnWeight("Spring", SpawnWeight.Value, EnemyListType.Outside, EnemyData.PlanetName);
}
}
private void MaxSpawnCount_SettingChanged(object sender, EventArgs e)
{
EnemyHelper.SetMaxSpawnCount("Spring", MaxSpawnCount.Value, EnemyData.PlanetName);
}
private void SpawnInside_SettingChanged(object sender, EventArgs e)
{
if (SpawnInside.Value)
{
LevelHelper.AddEnemyToLevel(EnemyData.PlanetName, "Spring", SpawnWeight.Value, EnemyListType.Inside);
}
else
{
LevelHelper.RemoveEnemyFromLevel(EnemyData.PlanetName, "Spring", EnemyListType.Inside);
}
}
private void SpawnOutside_SettingChanged(object sender, EventArgs e)
{
if (SpawnOutside.Value)
{
LevelHelper.AddEnemyToLevel(EnemyData.PlanetName, "Spring", SpawnWeight.Value, EnemyListType.Outside);
}
else
{
LevelHelper.RemoveEnemyFromLevel(EnemyData.PlanetName, "Spring", EnemyListType.Outside);
}
}
}
public class EnemyConfigDataDefault
{
public int SpawnWeight = 1;
public int MaxSpawnCount = 5;
public bool SpawnInside = true;
public bool SpawnOutside = false;
public EnemyConfigDataDefault()
{
}
public EnemyConfigDataDefault(int spawnWeight, int maxSpawnCount, bool spawnInside, bool spawnOutside)
{
SpawnWeight = spawnWeight;
MaxSpawnCount = maxSpawnCount;
SpawnInside = spawnInside;
SpawnOutside = spawnOutside;
}
}
public class EnemyData
{
public string PlanetName { get; private set; }
public EnemyConfigData ConfigData { get; private set; }
public EnemyData(string planetName, EnemyConfigDataDefault defaultConfigValues = null)
{
PlanetName = planetName;
ConfigData = new EnemyConfigData(defaultConfigValues);
}
public void BindConfigs()
{
if (ConfigData == null)
{
ConfigData = new EnemyConfigData();
}
ConfigData.BindConfigs(this);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}