using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
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 LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using YesFox.Compatibility;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("uk.1a3.yesfox")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.5.0")]
[assembly: AssemblyInformationalVersion("1.1.5+cf4f68ae76d9e9ab9db8e9a90e32fb905f4ee2a4")]
[assembly: AssemblyProduct("YesFox")]
[assembly: AssemblyTitle("uk.1a3.yesfox")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace YesFox
{
[BepInPlugin("uk.1a3.yesfox", "YesFox", "1.1.5")]
internal class Plugin : BaseUnityPlugin
{
private readonly Harmony harmony = new Harmony("uk.1a3.yesfox");
internal static List<GameObject> _networkPrefabs = new List<GameObject>();
internal static ConfigEntry<bool> Shroud_AllMoons;
internal static ConfigEntry<float> Shroud_SpawnChance_SameMoon;
internal static ConfigEntry<float> Shroud_SpawnChance_OtherMoons;
internal static ConfigEntry<float> Shroud_GrowChance_SameMoon;
internal static ConfigEntry<float> Shroud_GrowChance_OtherMoons;
internal static ConfigEntry<int> Shroud_MaximumIterations;
internal static ConfigEntry<float> Shroud_MinimumDistance;
internal static ConfigEntry<int> Fox_MinimumWeeds;
internal static ConfigEntry<int> Fox_SpawnChance;
internal static Dictionary<string, ConfigEntry<bool>> Shroud_MoonToggles = new Dictionary<string, ConfigEntry<bool>>();
internal static Dictionary<string, ConfigEntry<bool>> WeedOverridesEnabled = new Dictionary<string, ConfigEntry<bool>>();
internal static Dictionary<string, ConfigEntry<bool>> FoxOverridesEnabled = new Dictionary<string, ConfigEntry<bool>>();
internal static Dictionary<string, ConfigEntry<float>> Shroud_MoonSpawnChanceSameMoonOverrides = new Dictionary<string, ConfigEntry<float>>();
internal static Dictionary<string, ConfigEntry<float>> Shroud_MoonSpawnChanceOtherMoonsOverrides = new Dictionary<string, ConfigEntry<float>>();
internal static Dictionary<string, ConfigEntry<float>> Shroud_MoonGrowChanceSameMoonOverrides = new Dictionary<string, ConfigEntry<float>>();
internal static Dictionary<string, ConfigEntry<float>> Shroud_MoonGrowChanceOtherMoonsOverrides = new Dictionary<string, ConfigEntry<float>>();
internal static Dictionary<string, ConfigEntry<int>> Shroud_MoonMaxIterationOverrides = new Dictionary<string, ConfigEntry<int>>();
internal static Dictionary<string, ConfigEntry<float>> Shroud_MoonMinDistanceOverrides = new Dictionary<string, ConfigEntry<float>>();
internal static Dictionary<string, ConfigEntry<int>> Fox_MinimumWeedsOverrides = new Dictionary<string, ConfigEntry<int>>();
internal static Dictionary<string, ConfigEntry<int>> Fox_SpawnChanceOverrides = new Dictionary<string, ConfigEntry<int>>();
internal static ManualLogSource StaticLogger { get; private set; }
internal static ConfigFile StaticConfig { get; private set; }
public static GameObject BushWolfAddonPrefab { get; internal set; }
private void Awake()
{
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Expected O, but got Unknown
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Expected O, but got Unknown
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: Expected O, but got Unknown
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Expected O, but got Unknown
//IL_0205: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Expected O, but got Unknown
//IL_0242: Unknown result type (might be due to invalid IL or missing references)
//IL_024c: Expected O, but got Unknown
//IL_0295: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: Expected O, but got Unknown
StaticLogger = ((BaseUnityPlugin)this).Logger;
StaticConfig = ((BaseUnityPlugin)this).Config;
Assembly executingAssembly = Assembly.GetExecutingAssembly();
harmony.PatchAll(executingAssembly);
StaticLogger.LogInfo((object)"Patches Loaded");
AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "bush_wolf"));
if ((Object)(object)val == (Object)null)
{
StaticLogger.LogError((object)"[AssetBundle] Failed to load asset bundle: bush_wolf");
return;
}
BushWolfAddonPrefab = val.LoadAsset<GameObject>("Assets/LethalCompany/Game/Prefabs/EnemyAI/BushWolfEnemy.prefab");
if ((Object)(object)BushWolfAddonPrefab != (Object)null)
{
if (!_networkPrefabs.Contains(BushWolfAddonPrefab))
{
_networkPrefabs.Add(BushWolfAddonPrefab);
}
StaticLogger.LogInfo((object)"[AssetBundle] Successfully loaded prefab: BushWolfEnemy");
}
else
{
StaticLogger.LogError((object)"[AssetBundle] Failed to load prefab: BushWolfEnemy");
}
Shroud_AllMoons = ((BaseUnityPlugin)this).Config.Bind<bool>("Weed Spawning", "All Moons", false, "Should weeds be able to spawn on all moons excluding gordion?");
Shroud_SpawnChance_SameMoon = ((BaseUnityPlugin)this).Config.Bind<float>("Weed Spawning", "Spawn Chance (Current Moon)", 8.5f, new ConfigDescription("What should the chance for them to initially spawn the moon you are routed to be? Weeds attempt to spawn on all moons when you go into orbit after each day.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
Shroud_SpawnChance_OtherMoons = ((BaseUnityPlugin)this).Config.Bind<float>("Weed Spawning", "Spawn Chance (Other Moons)", 4f, new ConfigDescription("What should the chance for them to initially spawn on other moons be? Weeds attempt to spawn on all moons when you go into orbit after each day.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
Shroud_GrowChance_SameMoon = ((BaseUnityPlugin)this).Config.Bind<float>("Weed Spawning", "Growth Chance (Current Moon)", 100f, new ConfigDescription("What is the chance that weeds should grow another \"step\" after leaving a moon? This applies at the end of the day, only once the spawn chance has succeeded for the first time.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
Shroud_GrowChance_OtherMoons = ((BaseUnityPlugin)this).Config.Bind<float>("Weed Spawning", "Growth Chance (Other Moons)", 100f, new ConfigDescription("What is the chance that weeds should grow another \"step\" for all other moons? This applies at the end of the day, only once the spawn chance has succeeded for the first time.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
Shroud_MaximumIterations = ((BaseUnityPlugin)this).Config.Bind<int>("Weed Spawning", "Maximum Iterations", 20, new ConfigDescription("How many days in a row are additional weeds allowed to grow on the same moon?", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
Shroud_MinimumDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Weed Spawning", "Minimum Distance", 40f, new ConfigDescription("How many units away from the ship must the starting points for weed growth be?", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 70f), Array.Empty<object>()));
Fox_MinimumWeeds = ((BaseUnityPlugin)this).Config.Bind<int>("Fox Spawning", "Minimum Weeds", 31, "The minimum amount of weeds required to spawn");
Fox_SpawnChance = ((BaseUnityPlugin)this).Config.Bind<int>("Fox Spawning", "Spawn Chance", -1, new ConfigDescription("What should the spawn chance be? If left as -1 then it will be the same as vanilla (a higher chance the more weeds there are)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, 100), Array.Empty<object>()));
}
}
[HarmonyPatch]
internal static class HarmonyPatches
{
private static bool perMoonConfigsGenerated = false;
private static MoldSpreadManager _moldSpreadManager;
public static Random WeedEnemySpawnRandom;
public static List<SpawnableEnemyWithRarity> WeedEnemies = new List<SpawnableEnemyWithRarity>();
private static GameObject _moldAttractionPoint;
private static VehicleController vehicleController;
private static readonly MethodInfo MOLD_SPREAD_MANAGER_INSTANCE = AccessTools.DeclaredPropertyGetter(typeof(HarmonyPatches), "MoldSpreadManager");
private static readonly MethodInfo MOLD_ATTRACTION_POINT = AccessTools.DeclaredPropertyGetter(typeof(HarmonyPatches), "MoldAttractionPoint");
private static readonly MethodInfo FIND_MOLD_SPORES = AccessTools.Method(typeof(HarmonyPatches), "FindMoldSpores", (Type[])null, (Type[])null);
private static readonly MethodInfo FIND_GAME_OBJECT_WITH_TAG = AccessTools.Method(typeof(GameObject), "FindGameObjectWithTag", (Type[])null, (Type[])null);
private static readonly MethodInfo FIND_GAME_OBJECTS_WITH_TAG = AccessTools.Method(typeof(GameObject), "FindGameObjectsWithTag", (Type[])null, (Type[])null);
private static MoldSpreadManager MoldSpreadManager
{
get
{
if ((Object)(object)_moldSpreadManager == (Object)null)
{
_moldSpreadManager = Object.FindAnyObjectByType<MoldSpreadManager>();
}
return _moldSpreadManager;
}
}
private static GameObject MoldAttractionPoint
{
get
{
if ((Object)(object)_moldAttractionPoint == (Object)null)
{
_moldAttractionPoint = GameObject.FindGameObjectWithTag("MoldAttractionPoint");
}
return _moldAttractionPoint;
}
}
[HarmonyPatch(typeof(GameNetworkManager), "Start")]
[HarmonyPostfix]
private static void GameNetworkManager_Start(GameNetworkManager __instance)
{
if (__instance.gameVersionNum >= 64)
{
foreach (GameObject networkPrefab in Plugin._networkPrefabs)
{
if (!NetworkManager.Singleton.NetworkConfig.Prefabs.Contains(networkPrefab))
{
NetworkManager.Singleton.AddNetworkPrefab(networkPrefab);
}
}
}
else
{
foreach (GameObject networkPrefab2 in Plugin._networkPrefabs)
{
if (NetworkManager.Singleton.NetworkConfig.Prefabs.Contains(networkPrefab2))
{
NetworkManager.Singleton.RemoveNetworkPrefab(networkPrefab2);
}
}
}
if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility"))
{
LobbyCompatibility.Init(__instance.gameVersionNum);
}
}
private static T GetValue<T>(string planetName, Dictionary<string, ConfigEntry<bool>> overrideEnabledDict, Dictionary<string, ConfigEntry<T>> overrideValueDict, ConfigEntry<T> globalValue)
{
if (overrideEnabledDict.TryGetValue(planetName, out var value) && value.Value && overrideValueDict.TryGetValue(planetName, out var value2))
{
return value2.Value;
}
return globalValue.Value;
}
[HarmonyPatch(typeof(TimeOfDay), "OnDayChanged")]
[HarmonyPostfix]
public static void OnDayChanged(TimeOfDay __instance)
{
if (!((NetworkBehaviour)__instance).IsOwner || StartOfRound.Instance.isChallengeFile)
{
return;
}
Random random = new Random(StartOfRound.Instance.randomMapSeed + 32);
Terminal val = Object.FindAnyObjectByType<Terminal>();
for (int i = 0; i < StartOfRound.Instance.levels.Length; i++)
{
SelectableLevel val2 = StartOfRound.Instance.levels[i];
string planetName = val2.PlanetName;
ConfigEntry<bool> value;
bool flag = (Plugin.Shroud_MoonToggles.TryGetValue(planetName, out value) ? value.Value : val2.canSpawnMold);
if (i == 3 || (!flag && !Plugin.Shroud_AllMoons.Value))
{
Plugin.StaticLogger.LogInfo((object)$"Skipping level #{i} {val2.PlanetName} mold iterations");
continue;
}
int value2 = GetValue(planetName, Plugin.WeedOverridesEnabled, Plugin.Shroud_MoonMaxIterationOverrides, Plugin.Shroud_MaximumIterations);
if (val2.moldSpreadIterations > 0)
{
if (val2.moldSpreadIterations < value2)
{
float num = (((Object)(object)val2 == (Object)(object)StartOfRound.Instance.currentLevel) ? GetValue(planetName, Plugin.WeedOverridesEnabled, Plugin.Shroud_MoonGrowChanceSameMoonOverrides, Plugin.Shroud_GrowChance_SameMoon) : GetValue(planetName, Plugin.WeedOverridesEnabled, Plugin.Shroud_MoonGrowChanceOtherMoonsOverrides, Plugin.Shroud_GrowChance_OtherMoons));
if (random.NextDouble() <= (double)(num / 100f))
{
val2.moldSpreadIterations++;
Plugin.StaticLogger.LogInfo((object)$"Increasing level #{i} {val2.PlanetName} mold iterations by 1; risen to {val2.moldSpreadIterations}");
}
}
continue;
}
bool num2 = (Object)(object)val2 == (Object)(object)StartOfRound.Instance.currentLevel;
ConfigEntry<bool> value3;
bool flag2 = Plugin.WeedOverridesEnabled.TryGetValue(planetName, out value3) && value3.Value;
float num3;
if (num2)
{
num3 = GetValue(planetName, Plugin.WeedOverridesEnabled, Plugin.Shroud_MoonSpawnChanceSameMoonOverrides, Plugin.Shroud_SpawnChance_SameMoon) / 100f;
}
else
{
num3 = GetValue(planetName, Plugin.WeedOverridesEnabled, Plugin.Shroud_MoonSpawnChanceOtherMoonsOverrides, Plugin.Shroud_SpawnChance_OtherMoons) / 100f;
if (!flag2)
{
if (val.groupCredits < 200 && val2.levelID == 12)
{
num3 *= 1.25f;
}
else if (val.groupCredits < 500 && (val2.levelID == 7 || val2.levelID == 6 || val2.levelID >= 10) && (StartOfRound.Instance.currentLevel.levelID == 5 || StartOfRound.Instance.currentLevel.levelID == 8 || StartOfRound.Instance.currentLevel.levelID == 4 || StartOfRound.Instance.currentLevel.levelID <= 2))
{
num3 *= 0.5f;
}
}
}
if (random.NextDouble() <= (double)num3)
{
val2.moldSpreadIterations += random.Next(1, 3);
Plugin.StaticLogger.LogInfo((object)$"Increasing level #{i} {val2.PlanetName} mold iterations for the first time; risen to {val2.moldSpreadIterations}");
}
}
}
[HarmonyPatch(typeof(StartOfRound), "PlayerLoadedServerRpc")]
[HarmonyPostfix]
private static void PlayerLoadedServerRpc(StartOfRound __instance)
{
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_026b: Unknown result type (might be due to invalid IL or missing references)
//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
if (!((NetworkBehaviour)__instance).IsServer || __instance.currentLevel.moldSpreadIterations < 1)
{
return;
}
string planetName = __instance.currentLevel.PlanetName;
if (!(Plugin.Shroud_MoonToggles.TryGetValue(planetName, out var value) ? value.Value : __instance.currentLevel.canSpawnMold) && !Plugin.Shroud_AllMoons.Value)
{
__instance.currentLevel.moldSpreadIterations = 0;
__instance.currentLevel.moldStartPosition = -1;
return;
}
int value2 = GetValue(planetName, Plugin.WeedOverridesEnabled, Plugin.Shroud_MoonMaxIterationOverrides, Plugin.Shroud_MaximumIterations);
if (__instance.currentLevel.moldSpreadIterations > value2)
{
__instance.currentLevel.moldSpreadIterations = value2;
}
GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
if (array == null || array.Length < 1)
{
return;
}
Vector3 shipPos = StartOfRound.Instance.shipLandingPosition.position;
List<GameObject> list = new List<GameObject>();
list.AddRange(array.OrderBy((GameObject x) => Vector3.Distance(x.transform.position, shipPos)));
array = list.ToArray();
if (__instance.currentLevel.moldStartPosition >= 0 && __instance.currentLevel.moldStartPosition < array.Length)
{
float num = Vector3.Distance(array[__instance.currentLevel.moldStartPosition].transform.position, shipPos);
if (num >= 30f)
{
return;
}
Plugin.StaticLogger.LogInfo((object)$"Mold growth is starting from node #{__instance.currentLevel.moldStartPosition} which is too close to the ship ({num} < 30)");
}
float value3 = GetValue(planetName, Plugin.WeedOverridesEnabled, Plugin.Shroud_MoonMinDistanceOverrides, Plugin.Shroud_MinimumDistance);
int value4 = GetValue(planetName, Plugin.FoxOverridesEnabled, Plugin.Fox_MinimumWeedsOverrides, Plugin.Fox_MinimumWeeds);
Random random = new Random(__instance.randomMapSeed + 2017);
int moldSpreadIterations = __instance.currentLevel.moldSpreadIterations;
RaycastHit val = default(RaycastHit);
for (int i = 0; i < array.Length; i++)
{
float num2 = Vector3.Distance(array[i].transform.position, shipPos);
if (!(num2 >= value3) || (random.Next(100) >= 13 && array.Length - i >= 20))
{
continue;
}
Plugin.StaticLogger.LogDebug((object)$"Mold growth: outsideAINodes[{i}] is candidate (ship dist: {num2} > {value3})");
if (Physics.Raycast(array[i].transform.position, Vector3.down, ref val, 8f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
{
MoldSpreadManager.GenerateMold(array[i].transform.position, value2);
int count = MoldSpreadManager.generatedMold.Count;
MoldSpreadManager.RemoveAllMold();
if (count >= value4)
{
__instance.currentLevel.moldStartPosition = i;
__instance.currentLevel.moldSpreadIterations = moldSpreadIterations;
Plugin.StaticLogger.LogInfo((object)$"Mold growth: Selected outsideAINodes[{i}]: coords {array[i].transform.position}, dist {num2}");
return;
}
Plugin.StaticLogger.LogDebug((object)$"Mold growth: outsideAINodes[{i}] rejected (max weeds: {count} < {value4})");
}
else
{
Plugin.StaticLogger.LogDebug((object)$"Mold growth: outsideAINodes[{i}] rejected (no ground)");
}
}
__instance.currentLevel.moldSpreadIterations = 0;
__instance.currentLevel.moldStartPosition = -1;
Plugin.StaticLogger.LogInfo((object)("Level \"" + __instance.currentLevel.PlanetName + "\" has no valid AI nodes"));
}
[HarmonyPatch(typeof(StartOfRound), "Start")]
[HarmonyPrefix]
[HarmonyPriority(800)]
private static void StartOfRound_Start(StartOfRound __instance)
{
GeneratePerMoonConfigsIfNeeded(__instance);
GenerateWeedEnemiesList();
}
private static void GeneratePerMoonConfigsIfNeeded(StartOfRound startOfRoundInstance)
{
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Expected O, but got Unknown
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Expected O, but got Unknown
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Expected O, but got Unknown
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Expected O, but got Unknown
//IL_0266: Unknown result type (might be due to invalid IL or missing references)
//IL_0270: Expected O, but got Unknown
//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
//IL_02c0: Expected O, but got Unknown
//IL_031b: Unknown result type (might be due to invalid IL or missing references)
//IL_0325: Expected O, but got Unknown
//IL_0364: Unknown result type (might be due to invalid IL or missing references)
//IL_036e: Expected O, but got Unknown
if (perMoonConfigsGenerated || Plugin.StaticConfig == null)
{
return;
}
Plugin.StaticLogger.LogInfo((object)"Generating per-moon fox & weed configs...");
SelectableLevel[] levels = startOfRoundInstance.levels;
foreach (SelectableLevel val in levels)
{
if (val.levelID != 3 && val.spawnEnemiesAndScrap)
{
string planetName = val.PlanetName;
string text = new string(planetName.Where((char c) => char.IsLetterOrDigit(c) || char.IsWhiteSpace(c)).ToArray()).Trim();
string text2 = "Moon Overrides." + text;
Plugin.Shroud_MoonToggles.TryAdd(planetName, Plugin.StaticConfig.Bind<bool>(text2, "Enable Weed Spawning", val.canSpawnMold, "Controls whether weeds can spawn on " + planetName + " at all. This is the master switch for this moon."));
Plugin.WeedOverridesEnabled.TryAdd(planetName, Plugin.StaticConfig.Bind<bool>(text2, "Enable Weed Overrides", false, "Enable per-moon overrides for weed settings (spawn/growth chance, etc). If this is false, the global settings will be used."));
Plugin.Shroud_MoonSpawnChanceSameMoonOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<float>(text2, "Spawn Chance (While Routed)", Plugin.Shroud_SpawnChance_SameMoon.Value, new ConfigDescription("Override the weed spawn chance for " + planetName + " when you are currently routed to it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())));
Plugin.Shroud_MoonSpawnChanceOtherMoonsOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<float>(text2, "Spawn Chance (While Not Routed)", Plugin.Shroud_SpawnChance_OtherMoons.Value, new ConfigDescription("Override the weed spawn chance for " + planetName + " when you are routed to another moon.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())));
Plugin.Shroud_MoonGrowChanceSameMoonOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<float>(text2, "Growth Chance (While Routed)", Plugin.Shroud_GrowChance_SameMoon.Value, new ConfigDescription("Override the weed growth chance for " + planetName + " when you are currently routed to it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())));
Plugin.Shroud_MoonGrowChanceOtherMoonsOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<float>(text2, "Growth Chance (While Not Routed)", Plugin.Shroud_GrowChance_OtherMoons.Value, new ConfigDescription("Override the weed growth chance for " + planetName + " when you are routed to another moon.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())));
Plugin.Shroud_MoonMaxIterationOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<int>(text2, "Maximum Iterations", Plugin.Shroud_MaximumIterations.Value, new ConfigDescription("Override the global maximum weed iterations for " + planetName + ".", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())));
Plugin.Shroud_MoonMinDistanceOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<float>(text2, "Minimum Distance", Plugin.Shroud_MinimumDistance.Value, new ConfigDescription("Override the global minimum distance for weed growth on " + planetName + ".", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 70f), Array.Empty<object>())));
Plugin.FoxOverridesEnabled.TryAdd(planetName, Plugin.StaticConfig.Bind<bool>(text2, "Enable Fox Overrides", false, "Enable per-moon overrides for fox settings (minimum weeds, spawn chance). If this is false, the global settings will be used."));
Plugin.Fox_MinimumWeedsOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<int>(text2, "Fox Minimum Weeds", Plugin.Fox_MinimumWeeds.Value, new ConfigDescription("Override the minimum weeds required for a fox to spawn on " + planetName + ".", (AcceptableValueBase)null, Array.Empty<object>())));
Plugin.Fox_SpawnChanceOverrides.TryAdd(planetName, Plugin.StaticConfig.Bind<int>(text2, "Fox Spawn Chance", Plugin.Fox_SpawnChance.Value, new ConfigDescription("Override the spawn chance for a fox on " + planetName + ". Set to -1 to use the vanilla spawn logic.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, 100), Array.Empty<object>())));
}
}
perMoonConfigsGenerated = true;
}
public static void GenerateWeedEnemiesList()
{
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
//IL_01b0: Expected O, but got Unknown
WeedEnemies.Clear();
try
{
EnemyType val = ((IEnumerable<SpawnableEnemyWithRarity>)Object.FindAnyObjectByType<QuickMenuManager>()?.testAllEnemiesLevel?.OutsideEnemies).FirstOrDefault((Func<SpawnableEnemyWithRarity, bool>)delegate(SpawnableEnemyWithRarity x)
{
if (((Object)x.enemyType).name == "BushWolf")
{
GameObject enemyPrefab2 = x.enemyType.enemyPrefab;
if (enemyPrefab2 == null)
{
return false;
}
return enemyPrefab2.GetComponentsInChildren<SkinnedMeshRenderer>()?.Length > 0;
}
return false;
})?.enemyType;
if (!((Object)(object)val != (Object)null))
{
return;
}
if (GameNetworkManager.Instance.gameVersionNum >= 64 && (Object)(object)val.enemyPrefab != (Object)(object)Plugin.BushWolfAddonPrefab && (Object)(object)Plugin.BushWolfAddonPrefab != (Object)null)
{
if ((Object)(object)Plugin.BushWolfAddonPrefab.GetComponent<EnemyAI>() != (Object)null)
{
Plugin.BushWolfAddonPrefab.GetComponent<EnemyAI>().enemyType = val;
Plugin.StaticLogger.LogInfo((object)"[GenerateWeedEnemiesList] BushWolf: Replaced addon EnemyAI enemyType");
}
GameObject enemyPrefab = val.enemyPrefab;
SkinnedMeshRenderer val2 = ((enemyPrefab != null) ? ((IEnumerable<SkinnedMeshRenderer>)enemyPrefab.GetComponentsInChildren<SkinnedMeshRenderer>()).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer rend) => ((Renderer)rend).sharedMaterials.Length > 1)) : null);
SkinnedMeshRenderer[] componentsInChildren = Plugin.BushWolfAddonPrefab.GetComponentsInChildren<SkinnedMeshRenderer>();
if ((Object)(object)val2 != (Object)null)
{
SkinnedMeshRenderer[] array = componentsInChildren;
foreach (SkinnedMeshRenderer val3 in array)
{
Material[] array2 = (Material[])(object)new Material[(((Object)val3).name == "BodyLOD2") ? 1 : 2];
for (int j = 0; j < array2.Length; j++)
{
array2[j] = ((Renderer)val2).materials[j];
}
((Renderer)val3).materials = array2;
}
}
val.enemyPrefab = Plugin.BushWolfAddonPrefab;
Plugin.StaticLogger.LogInfo((object)"[GenerateWeedEnemiesList] BushWolf: Replaced original EnemyType prefab");
}
WeedEnemies.Add(new SpawnableEnemyWithRarity
{
enemyType = val,
rarity = 100
});
}
catch (Exception ex)
{
Plugin.StaticLogger.LogError((object)ex);
}
}
public static void SpawnWeedEnemies(int currentHour, SelectableLevel currentLevel)
{
int num = 0;
if ((Object)(object)MoldSpreadManager != (Object)null)
{
num = MoldSpreadManager.generatedMold.Count((GameObject x) => (Object)(object)x != (Object)null && x.activeSelf);
}
string planetName = currentLevel.PlanetName;
int value = GetValue(planetName, Plugin.FoxOverridesEnabled, Plugin.Fox_MinimumWeedsOverrides, Plugin.Fox_MinimumWeeds);
if (num < value)
{
Plugin.StaticLogger.LogDebug((object)$"Weed enemies attempted to spawn but were denied. Reason: WeedCount | Amount: {num}");
return;
}
int value2 = GetValue(planetName, Plugin.FoxOverridesEnabled, Plugin.Fox_SpawnChanceOverrides, Plugin.Fox_SpawnChance);
if (value2 >= 0)
{
int num2 = WeedEnemySpawnRandom.Next(1, 100);
if (num2 > value2)
{
Plugin.StaticLogger.LogDebug((object)$"Weed enemies attempted to spawn but were denied. Reason: SpawnChance | Amount: {num2}");
return;
}
}
else
{
int num3 = WeedEnemySpawnRandom.Next(0, 80);
if (num3 > num)
{
Plugin.StaticLogger.LogDebug((object)$"Weed enemies attempted to spawn but were denied. Reason: SpawnChance | Amount: {num3}");
return;
}
}
int num4 = WeedEnemySpawnRandom.Next(1, 3);
GameObject[] spawnPoints = GameObject.FindGameObjectsWithTag("OutsideAINode");
float timeUpToCurrentHour = TimeOfDay.Instance.lengthOfHours * (float)currentHour;
if (WeedEnemies.Count == 0)
{
GenerateWeedEnemiesList();
if (WeedEnemies.Count == 0)
{
Plugin.StaticLogger.LogError((object)"Weed enemies attempted to spawn but were denied. Reason: ListEmpty");
return;
}
}
for (int i = 0; i < num4; i++)
{
if (!SpawnRandomWeedEnemy(spawnPoints, timeUpToCurrentHour, num))
{
break;
}
}
}
public static bool SpawnRandomWeedEnemy(GameObject[] spawnPoints, float timeUpToCurrentHour, int numberOfWeeds)
{
//IL_0274: Unknown result type (might be due to invalid IL or missing references)
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
//IL_0280: Unknown result type (might be due to invalid IL or missing references)
//IL_0289: Unknown result type (might be due to invalid IL or missing references)
//IL_028f: Unknown result type (might be due to invalid IL or missing references)
//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
RoundManager.Instance.SpawnProbabilities.Clear();
int num = 0;
for (int i = 0; i < WeedEnemies.Count; i++)
{
EnemyType enemyType = WeedEnemies[i].enemyType;
if (RoundManager.Instance.firstTimeSpawningWeedEnemies)
{
enemyType.numberSpawned = 0;
}
if (enemyType.PowerLevel > RoundManager.Instance.currentMaxOutsidePower - RoundManager.Instance.currentOutsideEnemyPower || enemyType.numberSpawned >= enemyType.MaxCount || enemyType.spawningDisabled)
{
RoundManager.Instance.SpawnProbabilities.Add(0);
Plugin.StaticLogger.LogDebug((object)"A weed enemy attempted to spawn but was denied. Reason: Probability | Amount: 0");
continue;
}
int num2 = ((RoundManager.Instance.increasedOutsideEnemySpawnRateIndex == i) ? 100 : ((!enemyType.useNumberSpawnedFalloff) ? ((int)((float)WeedEnemies[i].rarity * enemyType.probabilityCurve.Evaluate(timeUpToCurrentHour / RoundManager.Instance.timeScript.totalTime))) : ((int)((float)WeedEnemies[i].rarity * (enemyType.probabilityCurve.Evaluate(timeUpToCurrentHour / RoundManager.Instance.timeScript.totalTime) * enemyType.numberSpawnedFalloff.Evaluate((float)enemyType.numberSpawned / 10f))))));
if (enemyType.spawnFromWeeds)
{
num2 = (int)Mathf.Clamp((float)num2 * ((float)numberOfWeeds / 60f), 0f, 200f);
}
RoundManager.Instance.SpawnProbabilities.Add(num2);
num += num2;
}
RoundManager.Instance.firstTimeSpawningWeedEnemies = false;
if (num <= 0)
{
Plugin.StaticLogger.LogDebug((object)$"A weed enemy attempted to spawn but was denied. Reason: SpawnRate | Amount: {num}");
return false;
}
bool result = false;
int randomWeightedIndex = RoundManager.Instance.GetRandomWeightedIndex(RoundManager.Instance.SpawnProbabilities.ToArray(), WeedEnemySpawnRandom);
EnemyType enemyType2 = WeedEnemies[randomWeightedIndex].enemyType;
float num3 = Mathf.Max(enemyType2.spawnInGroupsOf, 1);
for (int j = 0; (float)j < num3; j++)
{
float num4 = RoundManager.Instance.currentMaxOutsidePower - RoundManager.Instance.currentOutsideEnemyPower;
if (enemyType2.PowerLevel > num4)
{
Plugin.StaticLogger.LogDebug((object)$"A weed enemy attempted to spawn but was denied. Reason: PowerLevel | Amount: {num4}");
break;
}
RoundManager instance = RoundManager.Instance;
instance.currentOutsideEnemyPower += enemyType2.PowerLevel;
Vector3 position = spawnPoints[RoundManager.Instance.AnomalyRandom.Next(0, spawnPoints.Length)].transform.position;
position = RoundManager.Instance.GetRandomNavMeshPositionInBoxPredictable(position, 10f, default(NavMeshHit), RoundManager.Instance.AnomalyRandom, RoundManager.Instance.GetLayermaskForEnemySizeLimit(enemyType2), 1f);
position = RoundManager.Instance.PositionWithDenialPointsChecked(position, spawnPoints, enemyType2, -1f);
GameObject val = Object.Instantiate<GameObject>(enemyType2.enemyPrefab, position, Quaternion.Euler(Vector3.zero));
val.GetComponentInChildren<NetworkObject>().Spawn(true);
RoundManager.Instance.SpawnedEnemies.Add(val.GetComponent<EnemyAI>());
EnemyType enemyType3 = val.GetComponent<EnemyAI>().enemyType;
enemyType3.numberSpawned++;
result = true;
}
Plugin.StaticLogger.LogDebug((object)(enemyType2.enemyName + " attempted to spawn and was allowed"));
return result;
}
[HarmonyPatch(typeof(RoundManager), "InitializeRandomNumberGenerators")]
[HarmonyPostfix]
public static void InitializeRandomNumberGenerators(RoundManager __instance)
{
WeedEnemySpawnRandom = new Random(__instance.playersManager.randomMapSeed + 42);
}
[HarmonyPatch(typeof(RoundManager), "AdvanceHourAndSpawnNewBatchOfEnemies")]
[HarmonyPrefix]
public static void AdvanceHourAndSpawnNewBatchOfEnemies(RoundManager __instance)
{
if (GameNetworkManager.Instance.gameVersionNum >= 64)
{
SpawnWeedEnemies(__instance.currentHour + __instance.hourTimeBetweenEnemySpawnBatches, StartOfRound.Instance.currentLevel);
}
}
[HarmonyPatch(typeof(BushWolfEnemy), "GetBiggestWeedPatch")]
[HarmonyPrefix]
public static void Pre_GetBiggestWeedPatch(ref Collider[] ___nearbyColliders)
{
if ((___nearbyColliders == null || ___nearbyColliders.Length <= 10) && MoldSpreadManager?.generatedMold != null && (___nearbyColliders == null || MoldSpreadManager.generatedMold.Count > ___nearbyColliders.Length))
{
___nearbyColliders = (Collider[])(object)new Collider[MoldSpreadManager.generatedMold.Count];
}
}
[HarmonyPatch(typeof(BushWolfEnemy), "GetBiggestWeedPatch")]
[HarmonyPostfix]
public static void Post_GetBiggestWeedPatch(BushWolfEnemy __instance, bool __result)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
if (__result && (Object)(object)MoldAttractionPoint == (Object)null)
{
__instance.aggressivePosition = __instance.mostHiddenPosition;
}
}
[HarmonyPatch(typeof(MoldSpreadManager), "GenerateMold")]
[HarmonyPrefix]
private static void Pre_GenerateMold(MoldSpreadManager __instance, ref int __state)
{
__state = StartOfRound.Instance.currentLevel.moldStartPosition;
}
[HarmonyPatch(typeof(MoldSpreadManager), "GenerateMold")]
[HarmonyPostfix]
private static void Post_GenerateMold(MoldSpreadManager __instance, int __state, int iterations)
{
if (__instance.iterationsThisDay < 1 && iterations > 0)
{
Plugin.StaticLogger.LogInfo((object)$"Mold growth on \"{StartOfRound.Instance.currentLevel.PlanetName}\" erroneously reset from {iterations} iterations");
StartOfRound.Instance.currentLevel.moldSpreadIterations = iterations;
StartOfRound.Instance.currentLevel.moldStartPosition = __state;
}
}
[HarmonyPatch(typeof(MoldSpreadManager), "Start")]
[HarmonyPostfix]
private static void MoldSpreadManager_Start(MoldSpreadManager __instance)
{
if ((Object)(object)_moldSpreadManager == (Object)null)
{
_moldSpreadManager = __instance;
}
}
[HarmonyPatch(typeof(VehicleController), "Awake")]
[HarmonyPostfix]
private static void VehicleController_Awake(VehicleController __instance)
{
if ((Object)(object)vehicleController == (Object)null)
{
vehicleController = __instance;
}
}
[HarmonyPatch(typeof(BushWolfEnemy), "Update")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> CacheVehicleController(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> list = instructions.ToList();
for (int i = 0; i < list.Count; i++)
{
if (list[i].opcode == OpCodes.Call)
{
string text = list[i].operand.ToString();
if (text.Contains("FindObjectOfType") && text.Contains("VehicleController"))
{
list[i].opcode = OpCodes.Ldsfld;
list[i].operand = AccessTools.Field(typeof(HarmonyPatches), "vehicleController");
Plugin.StaticLogger.LogDebug((object)"Use cached VehicleController in Kidnapper Fox AI");
break;
}
}
}
return list;
}
[HarmonyPatch(typeof(GameNetworkManager), "SaveGameValues")]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")]
[HarmonyPatch(typeof(RoundManager), "SpawnRandomOutsideEnemy")]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPatch(typeof(StartOfRound), "ResetMoldStates")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> CacheMoldSpreadManager(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
{
List<CodeInstruction> list = instructions.ToList();
for (int i = 0; i < list.Count; i++)
{
if (list[i].opcode == OpCodes.Call)
{
string text = list[i].operand.ToString();
if (text.Contains("FindObjectOfType") && text.Contains("MoldSpreadManager"))
{
list[i].operand = MOLD_SPREAD_MANAGER_INSTANCE;
Plugin.StaticLogger.LogDebug((object)$"Use cached MoldSpreadManager in {__originalMethod.DeclaringType}.{__originalMethod.Name}");
}
}
}
return list;
}
public static GameObject[] FindMoldSpores()
{
if (MoldSpreadManager?.generatedMold == null)
{
return GameObject.FindGameObjectsWithTag("MoldSpore");
}
return MoldSpreadManager.generatedMold.Where((GameObject x) => (Object)(object)x != (Object)null && x.activeSelf).ToArray();
}
[HarmonyPatch(typeof(MoldSpreadManager), "GenerateMold")]
[HarmonyPatch(typeof(BushWolfEnemy), "GetBiggestWeedPatch")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> CacheMoldGameObjects(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
{
List<CodeInstruction> list = instructions.ToList();
for (int i = 1; i < list.Count; i++)
{
if (list[i].opcode == OpCodes.Call)
{
MethodInfo methodInfo = list[i].operand as MethodInfo;
if (methodInfo == FIND_GAME_OBJECT_WITH_TAG && list[i - 1].opcode == OpCodes.Ldstr && (string)list[i - 1].operand == "MoldAttractionPoint")
{
list[i].operand = MOLD_ATTRACTION_POINT;
list[i - 1].opcode = OpCodes.Nop;
Plugin.StaticLogger.LogDebug((object)$"Use cached MoldAttractionPoint in {__originalMethod.DeclaringType}.{__originalMethod.Name}");
}
else if (methodInfo == FIND_GAME_OBJECTS_WITH_TAG && list[i - 1].opcode == OpCodes.Ldstr && (string)list[i - 1].operand == "MoldSpore")
{
list[i].operand = FIND_MOLD_SPORES;
list[i - 1].opcode = OpCodes.Nop;
Plugin.StaticLogger.LogDebug((object)$"Use cached MoldSpore game objects in {__originalMethod.DeclaringType}.{__originalMethod.Name}");
}
}
}
return list;
}
}
internal static class MyPluginInfo
{
public const string PLUGIN_GUID = "uk.1a3.yesfox";
public const string PLUGIN_NAME = "YesFox";
public const string PLUGIN_VERSION = "1.1.5";
}
}
namespace YesFox.Compatibility
{
internal class LobbyCompatibility
{
public static void Init(int versionNum)
{
Plugin.StaticLogger.LogWarning((object)"LobbyCompatibility detected, registering plugin with LobbyCompatibility.");
Version version = Version.Parse("1.1.5");
PluginHelper.RegisterPlugin("uk.1a3.yesfox", version, (CompatibilityLevel)((versionNum < 64) ? 1 : 2), (VersionStrictness)2);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}