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 HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using com.github.zehsteam.OnlyMaskedPlayerEnemies.Dependencies;
using com.github.zehsteam.OnlyMaskedPlayerEnemies.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.OnlyMaskedPlayerEnemies")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("This mod will make only Masked Player Enemies spawn.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+75838dab1e333823f423656df26bc03233caafbb")]
[assembly: AssemblyProduct("OnlyMaskedPlayerEnemies")]
[assembly: AssemblyTitle("com.github.zehsteam.OnlyMaskedPlayerEnemies")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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.OnlyMaskedPlayerEnemies
{
internal static class ConfigHelper
{
public static void SetModIcon(Sprite sprite)
{
if (LethalConfigProxy.Enabled)
{
LethalConfigProxy.SetModIcon(sprite);
}
}
public static void SetModDescription(string description)
{
if (LethalConfigProxy.Enabled)
{
LethalConfigProxy.SetModDescription(description);
}
}
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);
}
}
}
internal class ConfigManager
{
public ConfigEntry<int> MaxSpawnCount { get; private set; }
public ConfigEntry<bool> Hourly_Enabled { get; private set; }
public ConfigEntry<int> Hourly_SpawnCount { get; private set; }
public ConfigEntry<float> Hourly_SpawnChance { get; private set; }
public ConfigManager()
{
BindConfigs();
SetupChangedEvents();
ClearUnusedEntries();
}
private void BindConfigs()
{
ConfigHelper.SkipAutoGen();
MaxSpawnCount = ConfigHelper.Bind("Masked Player Enemy Settings", "MaxSpawnCount", 100, requiresRestart: false, "The max spawn count for Masked player enemies.");
Hourly_Enabled = ConfigHelper.Bind("Hourly Spawn Settings", "Enabled", defaultValue: false, requiresRestart: false, "If enabled, Masked player enemies will force spawn hourly.");
Hourly_SpawnCount = ConfigHelper.Bind("Hourly Spawn Settings", "SpawnCount", 4, requiresRestart: false, "The amount of Masked player enemies to try and spawn.");
Hourly_SpawnChance = ConfigHelper.Bind("Hourly Spawn Settings", "SpawnChance", 50f, requiresRestart: false, "The percent chance a Masked player enemy will spawn hourly.");
}
private void SetupChangedEvents()
{
MaxSpawnCount.SettingChanged += MaxSpawnCount_SettingChanged;
}
private void MaxSpawnCount_SettingChanged(object sender, EventArgs e)
{
EnemyHelper.SetOnlyEnemyMasked();
}
private void ClearUnusedEntries()
{
ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null);
dictionary.Clear();
config.Save();
}
}
internal static class EnemyHelper
{
public static void SetOnlyEnemyMasked()
{
SetOnlyEnemy("Masked");
}
public static void SetOnlyEnemy(string enemyName)
{
if (!((Object)(object)StartOfRound.Instance == (Object)null))
{
SelectableLevel[] levels = StartOfRound.Instance.levels;
foreach (SelectableLevel level in levels)
{
SetOnlyEnemyForLevel(level, enemyName, 10000, Plugin.ConfigManager.MaxSpawnCount.Value);
}
}
}
private static void SetOnlyEnemyForLevel(SelectableLevel level, string enemyName, int rarity, int maxSpawnCount)
{
SetOnlyEnemyForList(ref level.Enemies, enemyName, rarity, maxSpawnCount);
SetOnlyEnemyForList(ref level.OutsideEnemies, enemyName, rarity, maxSpawnCount);
}
private static void SetOnlyEnemyForList(ref List<SpawnableEnemyWithRarity> spawnableEnemyWithRarities, string enemyName, int rarity, int maxSpawnCount)
{
bool flag = false;
foreach (SpawnableEnemyWithRarity spawnableEnemyWithRarity in spawnableEnemyWithRarities)
{
if (spawnableEnemyWithRarity.enemyType.enemyName == enemyName)
{
flag = true;
spawnableEnemyWithRarity.rarity = rarity;
spawnableEnemyWithRarity.enemyType.MaxCount = maxSpawnCount;
Plugin.logger.LogMessage((object)$"Set enemy \"{enemyName}\" rarity to {rarity}.");
}
else
{
spawnableEnemyWithRarity.rarity = 0;
Plugin.logger.LogInfo((object)$"Set enemy \"{spawnableEnemyWithRarity.enemyType.enemyName}\" rarity to {spawnableEnemyWithRarity.rarity}.");
}
}
if (!flag)
{
AddEnemyToList(ref spawnableEnemyWithRarities, enemyName, rarity, maxSpawnCount);
}
}
private static void AddEnemyToList(ref List<SpawnableEnemyWithRarity> spawnableEnemyWithRarities, string enemyName, int rarity, int maxSpawnCount)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
EnemyType enemyType = GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.logger.LogError((object)("Failed to add enemy \"" + enemyName + "\" to list."));
return;
}
SpawnableEnemyWithRarity val = new SpawnableEnemyWithRarity();
val.rarity = rarity;
val.enemyType = enemyType;
val.enemyType.MaxCount = maxSpawnCount;
spawnableEnemyWithRarities.Add(val);
Plugin.logger.LogInfo((object)("Added enemy \"" + enemyName + "\" to list."));
}
public static void SpawnEnemyOnServer(string enemyName)
{
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
if (!NetworkUtils.IsServer)
{
Plugin.logger.LogError((object)"Failed to spawn enemy. Only the host can spawn enemies.");
return;
}
EnemyType enemyType = GetEnemyType(enemyName);
if ((Object)(object)enemyType == (Object)null)
{
Plugin.logger.LogError((object)("Failed to spawn \"" + enemyName + "\" enemy. EnemyType is null."));
return;
}
if ((Object)(object)enemyType.enemyPrefab == (Object)null)
{
Plugin.logger.LogError((object)("Failed to spawn \"" + enemyName + "\" enemy. EnemyType.enemyPrefab is null."));
return;
}
Plugin.logger.LogInfo((object)("Trying to spawn \"" + enemyName + "\" enemy."));
Vector3 randomSpawnPosition = GetRandomSpawnPosition();
float num = Random.Range(0f, 360f);
RoundManager.Instance.SpawnEnemyGameObject(randomSpawnPosition, num, -1, enemyType);
Plugin.logger.LogInfo((object)$"Spawned \"{enemyName}\" enemy at position: (x: {randomSpawnPosition.x}, y: {randomSpawnPosition.y}, z: {randomSpawnPosition.z})");
}
private static Vector3 GetRandomSpawnPosition()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)RoundManager.Instance == (Object)null)
{
return Vector3.zero;
}
if (Utils.RandomPercent(50f))
{
return GetRandomSpawnPositionInside();
}
return GetRandomSpawnPositionOutside();
}
private static Vector3 GetRandomSpawnPositionInside()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
if (RoundManager.Instance.insideAINodes == null || RoundManager.Instance.insideAINodes.Length == 0)
{
return Vector3.zero;
}
GameObject[] array = RoundManager.Instance.insideAINodes.Where((GameObject _) => (Object)(object)_ != (Object)null).ToArray();
if (array.Length == 0)
{
return Vector3.zero;
}
return array[Random.Range(0, array.Length)].transform.position;
}
private static Vector3 GetRandomSpawnPositionOutside()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
if (RoundManager.Instance.outsideAINodes == null || RoundManager.Instance.outsideAINodes.Length == 0)
{
return Vector3.zero;
}
GameObject[] array = RoundManager.Instance.outsideAINodes.Where((GameObject _) => (Object)(object)_ != (Object)null).ToArray();
if (array.Length == 0)
{
return Vector3.zero;
}
return array[Random.Range(0, array.Length)].transform.position;
}
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.logger.LogInfo((object)("Found EnemyType \"" + val.enemyName + "\" from Resources."));
return val;
}
}
catch
{
}
return null;
}
public static List<EnemyType> GetEnemyTypes()
{
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 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.OnlyMaskedPlayerEnemies", "OnlyMaskedPlayerEnemies", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class Plugin : BaseUnityPlugin
{
private readonly Harmony harmony = new Harmony("com.github.zehsteam.OnlyMaskedPlayerEnemies");
internal static Plugin Instance;
internal static ManualLogSource logger;
internal static ConfigManager ConfigManager;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
logger = Logger.CreateLogSource("com.github.zehsteam.OnlyMaskedPlayerEnemies");
logger.LogInfo((object)"OnlyMaskedPlayerEnemies has awoken!");
harmony.PatchAll(typeof(StartOfRoundPatch));
harmony.PatchAll(typeof(RoundManagerPatch));
ConfigManager = new ConfigManager();
}
}
internal static class Utils
{
public static bool RandomPercent(float percent)
{
if (percent <= 0f)
{
return false;
}
if (percent >= 100f)
{
return true;
}
return Random.value * 100f <= percent;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.github.zehsteam.OnlyMaskedPlayerEnemies";
public const string PLUGIN_NAME = "OnlyMaskedPlayerEnemies";
public const string PLUGIN_VERSION = "1.0.1";
}
}
namespace com.github.zehsteam.OnlyMaskedPlayerEnemies.Patches
{
[HarmonyPatch(typeof(RoundManager))]
internal static class RoundManagerPatch
{
[HarmonyPatch("AdvanceHourAndSpawnNewBatchOfEnemies")]
[HarmonyPostfix]
private static void AdvanceHourAndSpawnNewBatchOfEnemiesPatch()
{
if (!NetworkUtils.IsServer || !Plugin.ConfigManager.Hourly_Enabled.Value)
{
return;
}
Plugin.logger.LogInfo((object)"Trying to force spawn Masked player enemies hourly.");
EnemyType enemyType = EnemyHelper.GetEnemyType("Masked");
if ((Object)(object)enemyType == (Object)null)
{
Plugin.logger.LogError((object)"Failed to force spawn Masked player enemies hourly. EnemyType is null.");
return;
}
int value = Plugin.ConfigManager.Hourly_SpawnCount.Value;
int value2 = Plugin.ConfigManager.MaxSpawnCount.Value;
if (enemyType.numberSpawned >= value2)
{
Plugin.logger.LogWarning((object)$"Failed to force spawn Masked player enemies hourly. Max spawn count of {value2} has been reached.");
return;
}
for (int i = 0; i < value; i++)
{
if (enemyType.numberSpawned >= value2)
{
Plugin.logger.LogWarning((object)$"Failed to force spawn Masked player enemies hourly. Max spawn count of {value2} has been reached.");
break;
}
if (Utils.RandomPercent(Plugin.ConfigManager.Hourly_SpawnChance.Value))
{
EnemyHelper.SpawnEnemyOnServer("Masked");
}
}
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal static class StartOfRoundPatch
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void StartPatch()
{
EnemyHelper.SetOnlyEnemyMasked();
}
}
}
namespace com.github.zehsteam.OnlyMaskedPlayerEnemies.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 SetModIcon(Sprite sprite)
{
LethalConfigManager.SetModIcon(sprite);
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void SetModDescription(string description)
{
LethalConfigManager.SetModDescription(description);
}
[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();
}));
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}