using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EnhancedMonsters.Config;
using EnhancedMonsters.Monobehaviours;
using EnhancedMonsters.NetcodePatcher;
using EnhancedMonsters.Networking;
using EnhancedMonsters.Patches;
using EnhancedMonsters.Utils;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LethalLib.Modules;
using LethalSettings.UI;
using LethalSettings.UI.Components;
using MelanieMeliciousCooked;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyFileVersion("1.4.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace EnhancedMonsters
{
[BepInPlugin("com.velddev.enhancedmonsters", "Enhanced Monsters", "1.4.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInIncompatibility("Entity378.sellbodies")]
public class Plugin : BaseUnityPlugin
{
private static readonly Harmony harmony = new Harmony("com.velddev.enhancedmonsters");
[NotNull]
public static ManualLogSource? logger;
internal static Plugin Singleton
{
[return: NotNull]
get;
private set; }
public static GameObject EnemyToPropPrefab { get; private set; }
public static GameObject NetworkHandlerPrefab { get; private set; }
private void Awake()
{
Singleton = this;
logger = ((BaseUnityPlugin)this).Logger;
new LocalConfig(((BaseUnityPlugin)this).Config);
logger.LogInfo((object)"Local config initialized.");
logger.LogInfo((object)"This is (maybe) NOT an RPG mod. And hi btw.");
EnemiesDataManager.LoadEnemiesData();
new SyncedConfig(((BaseUnityPlugin)this).Config);
logger.LogInfo((object)"Enemies data loaded and ready to be synchronized.");
ApplyAllPatches();
logger.LogDebug((object)"All harmony patches have been applied (energistics).");
CreateThePrefab();
logger.LogDebug((object)"The Prefab have been created correctly");
CreateNetworkHandlerPrefab();
logger.LogDebug((object)"EnhancedMonstersNetworkHandler network prefab registered");
if ((Object)(object)FastResourcesManager.EnemyScrapIcon == (Object)null)
{
logger.LogError((object)"EnemyScrapIcon didn't load yet. Caution advised.");
}
else
{
logger.LogInfo((object)"EnemyScrapIcon loaded correctly and is ready to use !");
}
}
private static void ApplyAllPatches()
{
if (logger == null)
{
throw new NullReferenceException("logger is null. Cannot process further because it means that the mod was not initialized yet.");
}
logger.LogDebug((object)"Applying patches...");
harmony.PatchAll(typeof(EnemyAI_Patches));
harmony.PatchAll(typeof(MenuManager_Patches));
harmony.PatchAll(typeof(PlayerControllerB_Patches));
harmony.PatchAll(typeof(GameNetworkManager_Patches));
harmony.PatchAll(typeof(StartOfRound_Patches));
logger.LogDebug((object)"All Harmony patches applied.");
}
private static void CreateThePrefab()
{
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
GameObject val = NetworkPrefabs.CreateNetworkPrefab("EnemyAsProp");
val.tag = "PhysicsProp";
val.layer = 6;
NetworkObject component = val.GetComponent<NetworkObject>();
component.AutoObjectParentSync = false;
component.DontDestroyWithOwner = true;
BoxCollider val2 = val.AddComponent<BoxCollider>();
((Collider)val2).enabled = true;
((Collider)val2).isTrigger = true;
val2.size = new Vector3(1.5f, 1.5f, 1.5f);
val.AddComponent<EnemyScrap>();
val.AddComponent<AudioSource>();
val.AddComponent<OccludeAudio>();
val.AddComponent<AudioLowPassFilter>();
NetworkPrefabs.RegisterNetworkPrefab(val);
EnemyToPropPrefab = val;
}
private static void CreateNetworkHandlerPrefab()
{
GameObject val = NetworkPrefabs.CreateNetworkPrefab("EnhancedMonstersNetworkHandler");
NetworkObject component = val.GetComponent<NetworkObject>();
component.AutoObjectParentSync = false;
component.DontDestroyWithOwner = true;
val.AddComponent<EnhancedMonstersNetworkHandler>();
NetworkPrefabs.RegisterNetworkPrefab(val);
NetworkHandlerPrefab = val;
}
}
public static class PluginInfo
{
public const int ConfigVersion = 11;
public const string Version = "1.4.0";
public const string GUID = "com.velddev.enhancedmonsters";
public const string DisplayName = "Enhanced Monsters";
}
}
namespace EnhancedMonsters.Utils
{
public static class EnemiesDataManager
{
[JsonObject]
public class EnemyDataFile
{
public int Version { get; set; }
public Dictionary<string, EnemyData> EnemiesData { get; set; }
[JsonConstructor]
public EnemyDataFile(int version, Dictionary<string, EnemyData> enemiesData)
{
Version = version;
EnemiesData = enemiesData ?? new Dictionary<string, EnemyData>();
base..ctor();
}
}
public static readonly Dictionary<string, EnemyData> EnemiesData = new Dictionary<string, EnemyData>();
public static readonly Dictionary<string, EnemyData> DefaultEnemiesData = new Dictionary<string, EnemyData>
{
["Manticoil"] = new EnemyData(pickupable: true, 10, 20, 12f, "F", new EnemyData.EnemyMetadata(new Vec3(-0.25f, 0.25f, 0.15f), new Vec3(180f, 0f, -90f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)),
["Tulip Snake"] = new EnemyData(pickupable: true, 20, 30, 7f, "F", new EnemyData.EnemyMetadata(new Vec3(-0.15f, 0.1f, 0.11f), new Vec3(0f, 90f, 90f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)),
["Hoarding bug"] = new EnemyData(pickupable: true, 55, 90, 50f, "E", new EnemyData.EnemyMetadata(new Vec3(0.1f, 0.2f, -0.3f), new Vec3(0f, 0f, 90f), new Vec3(0f, 0f, 0f))),
["Puffer"] = new EnemyData(pickupable: true, 30, 60, 69f, "E", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))),
["Centipede"] = new EnemyData(pickupable: true, 45, 70, 35f, "D", new EnemyData.EnemyMetadata(new Vec3(-0.25f, 0.1f, 0f), new Vec3(0f, 0f, -90f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)),
["Baboon hawk"] = new EnemyData(pickupable: true, 75, 100, 105f, "D", new EnemyData.EnemyMetadata(new Vec3(-0.3f, 0.5f, 1.5f), new Vec3(0f, 0f, 90f), new Vec3(0f, 0f, 0f))),
["Bunker Spider"] = new EnemyData(pickupable: true, 70, 110, 75f, "C", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))),
["MouthDog"] = new EnemyData(pickupable: true, 175, 250, 250f, "C", new EnemyData.EnemyMetadata(new Vec3(-1.25f, -1f, -0.5f), new Vec3(180f, 0f, -90f), new Vec3(180f, 0f, 180f))),
["Crawler"] = new EnemyData(pickupable: true, 120, 160, 100f, "B", new EnemyData.EnemyMetadata(new Vec3(-0.5f, 0f, -1f), new Vec3(0f, 0f, -60f), new Vec3(0f, 0f, 0f))),
["Flowerman"] = new EnemyData(pickupable: true, 160, 190, 40f, "B", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 1.5f), new Vec3(0f, 90f, -90f), new Vec3(-90f, 0f, 0f), animateOnDeath: false)),
["Butler"] = new EnemyData(pickupable: true, 170, 199, 77f, "B", new EnemyData.EnemyMetadata(new Vec3(-0.5f, 0f, 1f), new Vec3(0f, 90f, -90f), new Vec3(-90f, 0f, 0f), animateOnDeath: false)),
["Nutcracker"] = new EnemyData(pickupable: true, 190, 220, 43f, "A", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 1.5f), new Vec3(0f, 90f, -90f), new Vec3(-90f, 0f, 0f), animateOnDeath: false)),
["Maneater"] = new EnemyData(pickupable: true, 250, 290, 42f, "S", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)),
["Docile Locust Bees"] = new EnemyData(pickupable: false, 0, 0, 0f, "F", new EnemyData.EnemyMetadata()),
["Red pill"] = new EnemyData(pickupable: false, 0, 0, 0f, "F", new EnemyData.EnemyMetadata()),
["Blob"] = new EnemyData(pickupable: false, 0, 0, 0f, "D", new EnemyData.EnemyMetadata()),
["Red Locust Bees"] = new EnemyData(pickupable: false, 0, 0, 0f, "C", new EnemyData.EnemyMetadata()),
["Butler Bees"] = new EnemyData(pickupable: false, 0, 0, 0f, "C", new EnemyData.EnemyMetadata()),
["Earth Leviathan"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()),
["Masked"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()),
["Clay Surgeon"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()),
["Spring"] = new EnemyData(pickupable: false, 0, 0, 0f, "A", new EnemyData.EnemyMetadata()),
["Jester"] = new EnemyData(pickupable: false, 0, 0, 0f, "S+", new EnemyData.EnemyMetadata()),
["RadMech"] = new EnemyData(pickupable: false, 0, 0, 0f, "S+", new EnemyData.EnemyMetadata()),
["Girl"] = new EnemyData(pickupable: false, 0, 0, 0f, "?", new EnemyData.EnemyMetadata()),
["Lasso"] = new EnemyData(pickupable: false, 0, 0, 0f, "dont exist haha", new EnemyData.EnemyMetadata()),
["ForestGiant"] = new EnemyData(pickupable: false, 0, 0, 0f, "S", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 90f, 0f), new Vec3(90f, 0f, 0f), animateOnDeath: false)),
["PinkGiant"] = new EnemyData(pickupable: false, 0, 0, 0f, "F", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 90f, 0f), new Vec3(0f, 0f, 0f), animateOnDeath: false)),
["Football"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()),
["Locker"] = new EnemyData(pickupable: false, 0, 0, 0f, "A", new EnemyData.EnemyMetadata()),
["Bush Wolf"] = new EnemyData(pickupable: true, 250, 320, 51f, "A", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))),
["PjonkGoose"] = new EnemyData(pickupable: true, 279, 340, 64f, "A", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f)))
};
public static string EnemiesDataFile = Path.Combine(Paths.ConfigPath, "EnhancedMonsters", "EnemiesData.json");
public static readonly Dictionary<string, GameObject> Enemies2Props = new Dictionary<string, GameObject>();
public static readonly List<Item> AllEnemiesScraps = new List<Item>();
public static void LoadEnemiesData()
{
if (!File.Exists(EnemiesDataFile))
{
Plugin.logger.LogWarning((object)"Enemy Data File did not exist!");
EnemiesData.ProperConcat(DefaultEnemiesData);
SaveEnemiesData();
return;
}
string text = File.ReadAllText(EnemiesDataFile);
Plugin.logger.LogDebug((object)text);
EnemyDataFile enemyDataFile = JsonConvert.DeserializeObject<EnemyDataFile>(text);
if (enemyDataFile == null)
{
Plugin.logger.LogWarning((object)"Enemy Data File seems to be empty or invalid.");
EnemiesData.ProperConcat(DefaultEnemiesData);
SaveEnemiesData();
}
else if (checked(11 - enemyDataFile.Version) > 1)
{
Plugin.logger.LogWarning((object)"Enemy Data File seems to be outdated. A new config file will be created.");
EnemiesData.ProperConcat(DefaultEnemiesData);
string text2 = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..", "..", "config", "EnhancedMonsters", "OLD_EnemiesData.json");
if (File.Exists(text2))
{
File.Delete(text2);
}
File.Move(EnemiesDataFile, text2);
SaveEnemiesData();
}
else
{
EnemiesData.ProperConcat(enemyDataFile.EnemiesData);
Plugin.logger.LogDebug((object)$"{enemyDataFile} => {EnemiesData.Count}");
EnemiesData.ProperConcat(DefaultEnemiesData);
Plugin.logger.LogDebug((object)$"{DefaultEnemiesData.Count} => {EnemiesData.Count}");
SaveEnemiesData();
}
}
public static void RegisterEnemy(string enemyName, bool sellable, int minPrice, int maxPrice, float mass, string rank, EnemyData.EnemyMetadata metadata, bool overrideRegister = false)
{
if (!EnemiesData.ContainsKey(enemyName))
{
EnemiesData.Add(enemyName, new EnemyData(sellable, minPrice, maxPrice, mass, rank, metadata));
}
else
{
if (!overrideRegister)
{
string name = Assembly.GetCallingAssembly().GetName().Name;
Plugin.logger.LogWarning((object)("Cannot register modded from mod " + name + " enemy " + enemyName + ": It is already registered (either from file or from ."));
return;
}
EnemiesData[enemyName] = new EnemyData(sellable, minPrice, maxPrice, mass, rank, metadata);
}
if (SyncedConfig.Instance == null || SyncedConfig.IsHost || !NetworkManager.Singleton.IsListening)
{
SyncedConfig.BroadcastSync();
}
}
internal static void RegisterEnemy(string enemyName, EnemyData enemyData)
{
if (SyncedConfig.IsHost || !NetworkManager.Singleton.IsListening)
{
if (EnemiesData != SyncedConfig.Instance.EnemiesData)
{
Plugin.logger.LogError((object)"Cannot update the mob configs. Somehow, the EnemiesData from the EnemiesDataManager and the one from the SyncedConfigs are not the same, even though they both are yours.");
}
else if (!EnemiesData.TryAdd(enemyName, enemyData))
{
Plugin.logger.LogDebug((object)("EnemyData '" + enemyName + "' already exists!"));
}
else
{
SyncedConfig.BroadcastSync();
}
}
}
public static void SaveEnemiesData()
{
if (!SyncedConfig.IsHost)
{
NetworkManager singleton = NetworkManager.Singleton;
if (singleton != null && singleton.IsListening)
{
return;
}
}
EnemyDataFile enemyDataFile = new EnemyDataFile(11, EnemiesData);
string contents = JsonConvert.SerializeObject((object)enemyDataFile, (Formatting)1);
if (!Directory.Exists(Path.GetDirectoryName(EnemiesDataFile)))
{
Directory.CreateDirectory(Path.GetDirectoryName(EnemiesDataFile));
}
File.WriteAllText(EnemiesDataFile, contents);
Plugin.logger.LogInfo((object)"Saved enemies data.");
}
public static void ScanAndRegisterUnknownEnemies()
{
EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>();
Plugin.logger.LogInfo((object)$"Scanning {array.Length} enemies for unknown entries");
EnemyAI[] array2 = array;
foreach (EnemyAI val in array2)
{
if (val == null)
{
Plugin.logger.LogWarning((object)"An enemy is null!");
}
else if (val.enemyType == null)
{
Plugin.logger.LogWarning((object)(((Object)val).name + " has a null enemyType (tf?)"));
}
else if (!SyncedConfig.Instance.EnemiesData.ContainsKey(val.enemyType.enemyName))
{
RegisterEnemy(val.enemyType.enemyName, new EnemyData(pickupable: true, 80, 250, 50f, "E", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))));
Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + val.enemyType.enemyName + "'"));
}
}
SaveEnemiesData();
}
public static void EnsureEnemy2PropPrefabs()
{
EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>();
EnemyAI[] array2 = array;
foreach (EnemyAI val in array2)
{
if ((Object)(object)val.enemyType == (Object)null)
{
Plugin.logger.LogWarning((object)("Entity " + ((Object)val).name + " have been skipped: This entity lacks an EnemyType !"));
continue;
}
string enemyName = val.enemyType.enemyName;
Plugin.logger.LogInfo((object)("Ensuring NetworkPrefab '" + enemyName + "'"));
if (!TryUpdateExistingPrefab(val, enemyName) && SyncedConfig.Instance.EnemiesData.TryGetValue(enemyName, out var value) && value.Pickupable)
{
GameObject visual = BuildVisualCopy(val);
GameObject val2 = BuildScrapPrefab(val, enemyName, visual, value);
if (!((Object)(object)val2 == (Object)null))
{
ScanNodeProperties componentInChildren = val2.GetComponentInChildren<ScanNodeProperties>();
Item enemyItem = BuildItemScriptable(enemyName, value, val2, componentInChildren);
RegisterPrefabAndItem(enemyName, val2, enemyItem);
}
}
}
if (FarmingAndCookingSupport.FarmingAndCookingLoaded)
{
FarmingAndCookingSupport.RegisterFarmingAndCookingBodies(AllEnemiesScraps);
}
}
private static bool TryUpdateExistingPrefab(EnemyAI enemy, string enemyName)
{
if (!Enemies2Props.TryGetValue(enemyName, out GameObject value))
{
return false;
}
EnemyData enemyData = SyncedConfig.Instance.EnemiesData[enemyName];
if (!enemyData.Pickupable)
{
Enemies2Props.Remove(enemyName);
return true;
}
EnemyScrap component = value.GetComponent<EnemyScrap>();
component.enemyType = enemy.enemyType;
((GrabbableObject)component).itemProperties.minValue = enemyData.MinValue;
((GrabbableObject)component).itemProperties.maxValue = enemyData.MaxValue;
((GrabbableObject)component).itemProperties.weight = enemyData.LCMass;
return true;
}
private static GameObject BuildVisualCopy(EnemyAI enemy)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(((Object)enemy).name + " neutralized");
foreach (Transform item in ((Component)enemy).transform)
{
Transform val2 = item;
if (!((Object)val2).name.StartsWith("MapDot") && !((Object)val2).name.StartsWith("Collider") && !((Object)val2).name.StartsWith("VoiceSFX") && !((Object)val2).name.StartsWith("CreatureSFX") && !((Object)val2).name.StartsWith("SeepingSFX") && !((Object)val2).name.StartsWith("CreatureVoice") && !((Object)val2).name.StartsWith("Ambience"))
{
Transform val3 = Object.Instantiate<Transform>(val2);
((Object)val3).name = ((Object)val2).name;
((Component)val3).transform.parent = val.transform;
}
}
val.RemoveComponentsInChildren<Collider>();
val.RemoveComponentsInChildren<AudioLowPassFilter>();
val.RemoveComponentsInChildren<AudioReverbFilter>();
val.RemoveComponentsInChildren<OccludeAudio>();
val.RemoveComponentsInChildren<EnemyAICollisionDetect>();
val.RemoveComponentsInChildren<AudioSource>();
val.RemoveComponentsInChildren<ParticleSystem>();
val.RemoveComponentsInChildren<ParticleSystemRenderer>();
val.transform.localScale = ((Component)enemy).transform.localScale;
return val;
}
private static GameObject BuildScrapPrefab(EnemyAI enemy, string enemyName, GameObject visual, EnemyData enemyData)
{
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
GameObject val = NetworkPrefabs.CloneNetworkPrefab(Plugin.EnemyToPropPrefab, "Dead " + enemyName);
visual.transform.parent = val.transform;
Plugin.logger.LogInfo((object)("Attached " + ((Object)visual).name + " to " + ((Object)visual.transform.parent).name));
EnemyScrap component = val.GetComponent<EnemyScrap>();
component.EnemyGameObject = visual;
CleanEnemyObj(component.EnemyGameObject);
((GrabbableObject)component).grabbable = true;
((GrabbableObject)component).grabbableToEnemies = false;
component.enemyType = enemy.enemyType;
BoxCollider component2 = val.GetComponent<BoxCollider>();
component2.size = enemyData.Metadata.CollisionExtents;
if (enemyName == "Bunker Spider")
{
val.AddComponent<SpiderArachnophobiaToggle>();
}
ScanNodeProperties componentInChildren = visual.GetComponentInChildren<ScanNodeProperties>();
if (!Object.op_Implicit((Object)(object)componentInChildren))
{
Plugin.logger.LogWarning((object)("Enemy '" + enemyName + "' has no ScanNodeProperties; corpse cannot be networked-scanned. Discarding scrap prefab."));
Object.Destroy((Object)(object)val);
return null;
}
Transform transform = ((Component)componentInChildren).gameObject.transform;
((Component)transform).transform.parent = val.transform;
((Component)transform).gameObject.AddComponent<BoxCollider>();
transform.localPosition = new Vector3(0f, 0f, 0f);
componentInChildren.maxRange = 13;
componentInChildren.minRange = 1;
componentInChildren.nodeType = 2;
componentInChildren.requiresLineOfSight = true;
componentInChildren.headerText = "Dead " + componentInChildren.headerText;
return val;
}
private static Item BuildItemScriptable(string enemyName, EnemyData enemyData, GameObject scrapPrefab, ScanNodeProperties scanNodeProperties)
{
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
Item val = ScriptableObject.CreateInstance<Item>();
EnemyScrap component = scrapPrefab.GetComponent<EnemyScrap>();
((GrabbableObject)component).itemProperties = val;
((Object)val).name = enemyName + " scrap";
val.itemName = scanNodeProperties.headerText;
val.saveItemVariable = true;
val.itemIcon = FastResourcesManager.EnemyScrapIcon;
val.minValue = enemyData.MinValue;
val.maxValue = enemyData.MaxValue;
val.allowDroppingAheadOfPlayer = true;
val.canBeGrabbedBeforeGameStart = true;
val.isScrap = true;
val.itemSpawnsOnGround = false;
val.twoHanded = enemyData.Metadata.TwoHanded;
val.requiresBattery = false;
val.twoHandedAnimation = enemyData.Metadata.TwoHanded;
val.weight = enemyData.LCMass;
val.spawnPrefab = scrapPrefab;
val.restingRotation = enemyData.Metadata.FloorRotation;
val.rotationOffset = enemyData.Metadata.HandRotation;
val.positionOffset = enemyData.Metadata.MeshOffset;
EnemyData enemyData2 = SyncedConfig.Default.EnemiesData[enemyName];
val.dropSFX = ResolveSfx(enemyData2.Metadata.DropSFX);
val.grabSFX = ResolveSfx(enemyData2.Metadata.GrabSFX);
val.pocketSFX = ResolveSfx(enemyData2.Metadata.PocketSFX);
return val;
}
private static AudioClip ResolveSfx(string sfxKey)
{
if (string.IsNullOrEmpty(sfxKey) || sfxKey == "none")
{
return null;
}
if (sfxKey == "default")
{
return FastResourcesManager.EnemyDropDefaultSound;
}
if (FastResourcesManager.CustomAudioClips.TryGetValue(sfxKey, out AudioClip value))
{
return value;
}
Plugin.logger.LogWarning((object)("Custom SFX '" + sfxKey + "' not found in CustomAudioClips. Using default. (File missing or coroutine still running?)"));
return FastResourcesManager.EnemyDropDefaultSound;
}
private static void RegisterPrefabAndItem(string enemyName, GameObject scrapPrefab, Item enemyItem)
{
NetworkPrefabs.RegisterNetworkPrefab(scrapPrefab);
NetworkManager singleton = NetworkManager.Singleton;
if ((Object)(object)singleton != (Object)null && !singleton.NetworkConfig.Prefabs.Contains(scrapPrefab))
{
singleton.AddNetworkPrefab(scrapPrefab);
}
Items.RegisterItem(enemyItem);
Items.RegisterScrap(enemyItem, 0, (LevelTypes)1);
AllEnemiesScraps.Add(enemyItem);
Enemies2Props.Add(enemyName, scrapPrefab);
Plugin.logger.LogInfo((object)("Registered NetworkPrefab '" + ((Object)scrapPrefab).name + "' (" + enemyItem.itemName + ")"));
}
public static void CleanEnemyObj(GameObject enemyObj)
{
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Expected O, but got Unknown
try
{
if (((Object)enemyObj).name.Contains("SandSpider"))
{
return;
}
int num = (Object.op_Implicit((Object)(object)Camera.main) ? Camera.main.cullingMask : 591075327);
Renderer[] componentsInChildren = enemyObj.GetComponentsInChildren<Renderer>(true);
Animator component = enemyObj.GetComponent<Animator>();
if ((Object)(object)component != (Object)null)
{
component.Update(0f);
}
Plugin.logger.LogInfo((object)("Starting cleanup on '" + ((Object)enemyObj).name + "'"));
Renderer[] array = componentsInChildren;
foreach (Renderer val in array)
{
if (!((Object)(object)val == (Object)null))
{
bool enabled = val.enabled;
bool flag = ((1 << ((Component)val).gameObject.layer) & num) != 0;
if (!enabled || !flag)
{
Plugin.logger.LogInfo((object)("Removing renderer '" + ((Object)val).name + "' from '" + ((Object)enemyObj).name + "'"));
Object.DestroyImmediate((Object)(object)val);
}
SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
if (val2 != null)
{
Mesh val3 = new Mesh();
val2.BakeMesh(val3);
}
}
}
Plugin.logger.LogInfo((object)("Cleanup completed on '" + ((Object)enemyObj).name + "'"));
}
catch (Exception arg)
{
Plugin.logger.LogError((object)$"ERROR cleaning '{((Object)enemyObj).name}': {arg}");
}
}
}
[Serializable]
[JsonObject(Description = "The value of a mob once killed, if it can be killed.")]
public record struct EnemyData
{
[Serializable]
[JsonObject(Description = "The metadata of a mob once killed, if it can be killed.")]
public record struct EnemyMetadata
{
public Vec3 MeshOffset;
public Vec3 HandRotation;
public Vec3 FloorRotation;
public Vec3 CollisionExtents;
public bool AnimateOnDeath;
public bool TwoHanded;
public string DropSFX;
public string GrabSFX;
public string PocketSFX;
public Dictionary<string, float> LootTable;
[JsonConstructor]
public EnemyMetadata()
{
DropSFX = "default";
GrabSFX = "none";
PocketSFX = "none";
MeshOffset = default(Vec3);
HandRotation = default(Vec3);
FloorRotation = default(Vec3);
CollisionExtents = new Vec3(1.5f, 1.5f, 1.5f);
AnimateOnDeath = false;
TwoHanded = true;
DropSFX = "default";
GrabSFX = "none";
PocketSFX = "none";
LootTable = new Dictionary<string, float>();
}
public EnemyMetadata(Vec3 meshOffset = default(Vec3), Vec3 handRotation = default(Vec3), Vec3 floorRotation = default(Vec3), bool animateOnDeath = true, bool twoHanded = true, Dictionary<string, float>? loots = null, string dropsfx = "default", string grabsfx = "none", string pocketsfx = "none", Vec3? collisionSize = null)
{
DropSFX = "default";
GrabSFX = "none";
PocketSFX = "none";
MeshOffset = meshOffset;
HandRotation = handRotation;
FloorRotation = floorRotation;
CollisionExtents = collisionSize ?? new Vec3(1.5f, 1.5f, 1.5f);
AnimateOnDeath = animateOnDeath;
TwoHanded = twoHanded;
DropSFX = dropsfx;
GrabSFX = grabsfx;
PocketSFX = pocketsfx;
LootTable = loots ?? new Dictionary<string, float>();
}
}
[JsonIgnore]
public readonly float LCMass => Mass / 105f + 1f;
public bool Pickupable;
public int MinValue;
public int MaxValue;
public float Mass;
public string Rank;
public EnemyMetadata Metadata;
[JsonConstructor]
public EnemyData()
{
Pickupable = true;
MinValue = 80;
MaxValue = 110;
Mass = 50f;
Rank = "C";
Metadata = new EnemyMetadata();
}
public EnemyData(bool pickupable = true, int minValue = 80, int maxValue = 250, float mass = 50f, string rank = "E", EnemyMetadata? metadata = null)
{
Pickupable = pickupable;
MinValue = minValue;
MaxValue = maxValue;
Mass = mass;
Rank = rank;
Metadata = metadata ?? new EnemyMetadata();
}
[CompilerGenerated]
private readonly bool PrintMembers(StringBuilder builder)
{
builder.Append("Pickupable = ");
builder.Append(Pickupable.ToString());
builder.Append(", MinValue = ");
builder.Append(MinValue.ToString());
builder.Append(", MaxValue = ");
builder.Append(MaxValue.ToString());
builder.Append(", Mass = ");
builder.Append(Mass.ToString());
builder.Append(", Rank = ");
builder.Append((object?)Rank);
builder.Append(", Metadata = ");
builder.Append(Metadata.ToString());
builder.Append(", LCMass = ");
builder.Append(LCMass.ToString());
return true;
}
}
[Serializable]
[JsonObject(Description = "A simple and flexible Vector3 structure.")]
public record struct Vec3
{
public float X;
public float Y;
public float Z;
[JsonConstructor]
public Vec3(float x, float y, float z)
{
Z = 0f;
X = x;
Y = y;
Z = z;
}
public static implicit operator Vector3(Vec3 v)
{
return new Vector3(v.X, v.Y, v.Z);
}
public static implicit operator Vector3(Vec3 v)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(v.X, v.Y, v.Z);
}
public static implicit operator Vec3(Vector3 v)
{
return new Vec3(v.X, v.Y, v.Z);
}
public static implicit operator Vec3(Vector3 v)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
return new Vec3(v.x, v.y, v.z);
}
public static Vec3 operator *(Vec3 l, float r)
{
return new Vec3(l.X * r, l.Y * r, l.Z * r);
}
public static Vec3 operator *(Vec3 l, Vec3 r)
{
return new Vec3(l.X * r.X, l.Y * r.Y, l.Z * r.Z);
}
public static Vec3 operator /(Vec3 l, float r)
{
return new Vec3(l.X / r, l.Y / r, l.Z / r);
}
public static Vec3 operator /(Vec3 l, Vec3 r)
{
return new Vec3(l.X / r.X, l.Y / r.Y, l.Z / r.Z);
}
public static Vec3 operator +(Vec3 l, Vec3 r)
{
return new Vec3(l.X + r.X, l.Y + r.Y, l.Z + r.Z);
}
public static Vec3 operator -(Vec3 l, Vec3 r)
{
return new Vec3(l.X - r.X, l.Y - r.Y, l.Z - r.Z);
}
public static Vec3 operator -(Vec3 s)
{
return new Vec3(0f - s.X, 0f - s.Y, 0f - s.Z);
}
public static float operator ~(Vec3 l)
{
return l.Length();
}
public readonly float Length()
{
return (float)Math.Sqrt(Math.Pow(X, 2.0) + Math.Pow(Y, 2.0) + Math.Pow(Z, 2.0));
}
public readonly void Deconstruct(out float x, out float y, out float z)
{
x = X;
y = Y;
z = Z;
}
public readonly void Deconstruct(out float x, out float y)
{
x = X;
y = Y;
}
}
internal static class FarmingAndCookingSupport
{
private const string FarmingAndCookingGuid = "MelanieMelicious.FarmAndCook";
private static bool? farmingAndCookingLoaded;
public static bool FarmingAndCookingLoaded
{
get
{
bool valueOrDefault = farmingAndCookingLoaded.GetValueOrDefault();
if (!farmingAndCookingLoaded.HasValue)
{
valueOrDefault = Chainloader.PluginInfos.ContainsKey("MelanieMelicious.FarmAndCook");
farmingAndCookingLoaded = valueOrDefault;
}
return farmingAndCookingLoaded.Value;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void RegisterFarmingAndCookingBodies(List<Item> bodies)
{
foreach (Item body in bodies)
{
Plugin.bodyHash.Add(body);
Plugin.logger.LogDebug((object)("Registered " + body.itemName + " for MelanieMeliciousCooked plugin."));
}
Plugin.logger.LogInfo((object)"Successfully registered all the corpses as grindable for the Farming & Cooking mod.");
}
}
internal static class FastResourcesManager
{
public static AssetBundle Resources;
public static readonly Dictionary<string, AudioClip> CustomAudioClips;
public static Sprite EnemyScrapIcon { get; private set; }
public static AudioClip EnemyDropDefaultSound { get; private set; }
public static string CustomSoundsFolder => Path.Combine(Paths.ConfigPath, "EnhancedMonsters", "CustomSFX");
static FastResourcesManager()
{
CustomAudioClips = new Dictionary<string, AudioClip>();
string name = Assembly.GetExecutingAssembly().GetManifestResourceNames()[0];
Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
Resources = AssetBundle.LoadFromStream(manifestResourceStream);
EnemyScrapIcon = Resources.LoadAsset<Sprite>("EnemyScrapItemIcon");
EnemyDropDefaultSound = Resources.LoadAsset<AudioClip>("BodyDrop");
LoadCustomSounds();
}
private static void LoadCustomSounds()
{
if (!Directory.Exists(CustomSoundsFolder))
{
Directory.CreateDirectory(CustomSoundsFolder);
Plugin.logger.LogInfo((object)("CustomSFX folder didn't exist, created at " + CustomSoundsFolder));
}
string[] files = Directory.GetFiles(CustomSoundsFolder, "*.wav", SearchOption.TopDirectoryOnly);
int num = 0;
string[] array = files;
foreach (string text in array)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
if (fileNameWithoutExtension == "default" || fileNameWithoutExtension == "none")
{
Plugin.logger.LogWarning((object)("Skipping '" + Path.GetFileName(text) + "': '" + fileNameWithoutExtension + "' is a reserved SFX key."));
continue;
}
if (CustomAudioClips.ContainsKey(fileNameWithoutExtension))
{
Plugin.logger.LogWarning((object)("Skipping '" + Path.GetFileName(text) + "': key '" + fileNameWithoutExtension + "' already loaded."));
continue;
}
try
{
AudioClip value = LoadWav(text, fileNameWithoutExtension);
CustomAudioClips[fileNameWithoutExtension] = value;
num = checked(num + 1);
Plugin.logger.LogInfo((object)("Loaded custom SFX '" + fileNameWithoutExtension + "' from " + Path.GetFileName(text)));
}
catch (Exception ex)
{
Plugin.logger.LogError((object)("Failed to load '" + Path.GetFileName(text) + "': " + ex.Message));
}
}
Plugin.logger.LogInfo((object)$"CustomSFX loading complete: {num} clip(s) loaded from {CustomSoundsFolder}");
}
private static AudioClip LoadWav(string filePath, string key)
{
using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using BinaryReader binaryReader = new BinaryReader(fileStream);
if (FourCC(binaryReader) != "RIFF")
{
throw new InvalidDataException("Not a RIFF file");
}
binaryReader.ReadInt32();
if (FourCC(binaryReader) != "WAVE")
{
throw new InvalidDataException("Not a WAVE file");
}
short num = 0;
short num2 = 0;
int num3 = 0;
short num4 = 0;
byte[] array = null;
checked
{
while (fileStream.Position < fileStream.Length)
{
string text = FourCC(binaryReader);
int num5 = binaryReader.ReadInt32();
if (text == "fmt ")
{
num = binaryReader.ReadInt16();
num2 = binaryReader.ReadInt16();
num3 = binaryReader.ReadInt32();
binaryReader.ReadInt32();
binaryReader.ReadInt16();
num4 = binaryReader.ReadInt16();
int num6 = 16;
if ((ushort)num == 65534 && num5 >= 40)
{
binaryReader.ReadInt16();
binaryReader.ReadInt16();
binaryReader.ReadInt32();
byte[] value = binaryReader.ReadBytes(16);
num6 += 24;
switch (BitConverter.ToInt32(value, 0))
{
case 1:
num = 1;
break;
case 3:
num = 3;
break;
}
}
if (num5 > num6)
{
fileStream.Seek(num5 - num6, SeekOrigin.Current);
}
}
else
{
if (text == "data")
{
array = binaryReader.ReadBytes(num5);
break;
}
fileStream.Seek(num5, SeekOrigin.Current);
}
}
if (array == null)
{
throw new InvalidDataException("No 'data' chunk found");
}
}
float[] array2;
if (num == 1 && num4 == 16)
{
int num7 = array.Length / 2;
array2 = new float[num7];
checked
{
for (int i = 0; i < num7; i++)
{
short num8 = (short)(array[i * 2] | (array[i * 2 + 1] << 8));
array2[i] = (float)num8 / 32768f;
}
}
}
else if (num == 1 && num4 == 24)
{
int num9 = array.Length / 3;
array2 = new float[num9];
for (int j = 0; j < num9; j = checked(j + 1))
{
int num10 = checked(array[j * 3] | (array[j * 3 + 1] << 8) | (array[j * 3 + 2] << 16));
if (((uint)num10 & 0x800000u) != 0)
{
num10 |= -16777216;
}
array2[j] = (float)num10 / 8388608f;
}
}
else if (num == 1 && num4 == 32)
{
int num11 = array.Length / 4;
array2 = new float[num11];
checked
{
for (int k = 0; k < num11; k++)
{
int num12 = array[k * 4] | (array[k * 4 + 1] << 8) | (array[k * 4 + 2] << 16) | (array[k * 4 + 3] << 24);
array2[k] = (float)num12 / 2.1474836E+09f;
}
}
}
else
{
if (num != 3 || num4 != 32)
{
throw new InvalidDataException($"Unsupported WAV format (format={num}, bits={num4}). Use 16/24/32-bit PCM or 32-bit IEEE float.");
}
int num13 = array.Length / 4;
array2 = new float[num13];
Buffer.BlockCopy(array, 0, array2, 0, array.Length);
}
int num14 = array2.Length / num2;
AudioClip val = AudioClip.Create("EM_CSFX_" + key, num14, (int)num2, num3, false);
val.SetData(array2, 0);
return val;
}
private static string FourCC(BinaryReader reader)
{
return Encoding.ASCII.GetString(reader.ReadBytes(4));
}
}
internal static class KnownEnemies
{
public const string BunkerSpider = "Bunker Spider";
public const string Flowerman = "Flowerman";
public const string SandSpider = "SandSpider";
public const string Maneater = "Maneater";
}
public static class Utility
{
public const float KgToLb = 2.2046227f;
public static string ToStringObj(this object obj, string prefix = "")
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine(prefix + obj.GetType().FullName + ": {");
FieldInfo[] fields = obj.GetType().GetFields();
foreach (FieldInfo fieldInfo in fields)
{
object arg = fieldInfo.GetValue(obj) ?? null;
stringBuilder.AppendLine(prefix + $"\t{fieldInfo.FieldType.Name} {fieldInfo.Name}: {arg}");
}
stringBuilder.AppendLine(prefix + "}");
return stringBuilder.ToString();
}
public static T EnsureComponent<T>(this GameObject go) where T : Component
{
if (go == null)
{
throw new NullReferenceException("The gameObject is a null reference.");
}
T result = default(T);
if (!go.TryGetComponent<T>(ref result))
{
return go.AddComponent<T>();
}
return result;
}
public static void AddRange<K, T, TI>(this IDictionary<K, T> target, IEnumerable<TI> source, Func<TI, K> key, Func<TI, T> selector, bool set = true)
{
foreach (TI item in source)
{
K key2 = key(item);
T value = selector(item);
if (set)
{
target[key2] = value;
}
else
{
target.TryAdd(key(item), selector(item));
}
}
}
public static void ProperConcat<K, T>(this IDictionary<K, T> target, IDictionary<K, T> source)
{
foreach (KeyValuePair<K, T> item in source)
{
if (!target.ContainsKey(item.Key))
{
target.Add(item.Key, item.Value);
}
}
}
public static void RemoveComponentsInChildren<T>(this GameObject go) where T : Component
{
T[] componentsInChildren = go.GetComponentsInChildren<T>();
T[] array = componentsInChildren;
foreach (T val in array)
{
Plugin.logger.LogDebug((object)("Destroying component " + ((object)val).GetType().Name + " on " + ((Object)(object)val).name + " (child of " + ((Object)go).name + ")"));
Object.Destroy((Object)(object)val);
}
}
internal static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
if (assembly == null)
{
throw new ArgumentNullException("assembly");
}
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where((Type t) => t != null);
}
}
}
}
namespace EnhancedMonsters.Patches
{
[HarmonyPatch(typeof(EnemyAI))]
public class EnemyAI_Patches
{
[HarmonyPrefix]
[HarmonyPatch(typeof(EnemyAI), "Start")]
private static void Start(EnemyAI __instance)
{
if (__instance.enemyType == null)
{
return;
}
SyncedConfig syncedConfig = (LocalConfig.Singleton.synchronizeRanks.Value ? SyncedConfig.Instance : SyncedConfig.Default);
if (!syncedConfig.EnemiesData.TryGetValue(__instance.enemyType.enemyName, out var value))
{
Plugin.logger.LogWarning((object)("Enemy " + __instance.enemyType.enemyName + " is not registered in the enemies data. Registering it now."));
value = new EnemyData(pickupable: true, 80, 250, 50f, "E", null);
EnemiesDataManager.RegisterEnemy(__instance.enemyType.enemyName, value);
}
if (!(value.Rank == string.Empty))
{
ScanNodeProperties componentInChildren = ((Component)__instance).gameObject.GetComponentInChildren<ScanNodeProperties>();
if (Object.op_Implicit((Object)(object)componentInChildren))
{
componentInChildren.subText = "Rank " + value.Rank;
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(EnemyAI), "KillEnemy")]
private static void KillEnemy(EnemyAI __instance, bool destroy)
{
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.enemyType == (Object)null)
{
return;
}
Plugin.logger.LogDebug((object)("Mob " + __instance.enemyType.enemyName + " died."));
if (destroy)
{
return;
}
if (!SyncedConfig.Instance.EnemiesData.ContainsKey(__instance.enemyType.enemyName))
{
EnemiesDataManager.RegisterEnemy(__instance.enemyType.enemyName, new EnemyData(pickupable: true, 80, 250, 50f, "E", null));
Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + __instance.enemyType.enemyName + "'"));
}
if (!NetworkManager.Singleton.IsServer)
{
return;
}
Plugin.logger.LogDebug((object)("Spawning EnemyScrap for enemy " + __instance.enemyType.enemyName + "."));
if (!EnemiesDataManager.Enemies2Props.TryGetValue(__instance.enemyType.enemyName, out GameObject value))
{
Plugin.logger.LogWarning((object)("Mob " + __instance.enemyType.enemyName + " has no enemy2prop prefab."));
return;
}
GameObject val = Object.Instantiate<GameObject>(value);
((Object)val).hideFlags = (HideFlags)0;
val.transform.position = ((Component)__instance).transform.position;
val.GetComponent<NetworkObject>().Spawn(false);
Vector3 val2 = default(Vector3);
((Vector3)(ref val2))..ctor(-10000f, -10000f, -10000f);
((Component)__instance).transform.position = val2;
__instance.serverPosition = val2;
NetworkObject component = ((Component)__instance).GetComponent<NetworkObject>();
EnhancedMonstersNetworkHandler instance = EnhancedMonstersNetworkHandler.Instance;
if ((Object)(object)instance != (Object)null && (Object)(object)component != (Object)null)
{
instance.HideOriginalEnemyBodyClientRpc(NetworkObjectReference.op_Implicit(component), val2);
}
else
{
Plugin.logger.LogWarning((object)"Network handler or enemy NetworkObject unavailable; falling back to SyncPositionToClients()");
__instance.SyncPositionToClients();
}
Plugin.logger.LogDebug((object)"Mob should now be grabbable for all users.");
}
}
[HarmonyPatch(typeof(GameNetworkManager))]
internal class GameNetworkManager_Patches
{
[HarmonyPostfix]
[HarmonyPatch("StartDisconnect")]
public static void StartDisconnect()
{
SyncedConfig.RevertSync();
}
}
[HarmonyPatch(typeof(MenuManager))]
public class MenuManager_Patches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(MenuManager), "Start")]
private static void Start(MenuManager __instance)
{
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)__instance))
{
Plugin.logger.LogError((object)"MenuManager instance is null. Something might have booted too early.");
return;
}
if (__instance.versionNumberText == null)
{
Plugin.logger.LogWarning((object)"It seems like the Version Number Text of main menu is missing, it's probably the first main menu iteration. Skipping this one.");
return;
}
TextMeshProUGUI versionNumberText = __instance.versionNumberText;
((TMP_Text)versionNumberText).text = ((TMP_Text)versionNumberText).text + "\n<size=75%>Enhanced Monsters v1.4.0</size>";
((Component)__instance.versionNumberText).gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(500f, 50f);
EnemiesDataManager.ScanAndRegisterUnknownEnemies();
EnemiesDataManager.EnsureEnemy2PropPrefabs();
Plugin.logger.LogInfo((object)"All enemies have been patched correctly.");
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerControllerB_Patches
{
[HarmonyPrefix]
[HarmonyPatch("ConnectClientToPlayerObject")]
public static void InitializeLocalPlayerPrefabs()
{
EnemiesDataManager.ScanAndRegisterUnknownEnemies();
EnemiesDataManager.EnsureEnemy2PropPrefabs();
}
[HarmonyPostfix]
[HarmonyPatch("ConnectClientToPlayerObject")]
public static void InitializeLocalPlayer()
{
if (SyncedConfig.IsHost)
{
Plugin.logger.LogInfo((object)"Local player is host, no sync request needed");
}
else
{
SyncedConfig.RequestSync();
}
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal class StartOfRound_Patches
{
[HarmonyPostfix]
[HarmonyPatch("Start")]
public static void StartPatch()
{
EnemiesDataManager.ScanAndRegisterUnknownEnemies();
EnemiesDataManager.EnsureEnemy2PropPrefabs();
if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && (Object)(object)Plugin.NetworkHandlerPrefab != (Object)null)
{
GameObject val = Object.Instantiate<GameObject>(Plugin.NetworkHandlerPrefab);
val.GetComponent<NetworkObject>().Spawn(true);
Plugin.logger.LogInfo((object)"EnhancedMonstersNetworkHandler spawned by server in StartOfRound");
}
}
}
}
namespace EnhancedMonsters.Networking
{
public class EnhancedMonstersNetworkHandler : NetworkBehaviour
{
public static EnhancedMonstersNetworkHandler Instance { get; private set; }
public override void OnNetworkSpawn()
{
((NetworkBehaviour)this).OnNetworkSpawn();
Instance = this;
if (((NetworkBehaviour)this).IsServer)
{
ConfigSyncService.Synced = true;
}
Plugin.logger.LogInfo((object)("EnhancedMonstersNetworkHandler spawned (" + (((NetworkBehaviour)this).IsServer ? "server" : "client") + ")"));
}
public override void OnNetworkDespawn()
{
((NetworkBehaviour)this).OnNetworkDespawn();
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
Plugin.logger.LogInfo((object)"EnhancedMonstersNetworkHandler despawned");
}
[ServerRpc(RequireOwnership = false)]
public void RequestConfigSyncServerRpc(ServerRpcParams serverRpcParams = default(ServerRpcParams))
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Invalid comparison between Unknown and I4
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: 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_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
if (networkManager == null || !networkManager.IsListening)
{
return;
}
if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
{
FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(3276370873u, serverRpcParams, (RpcDelivery)0);
((NetworkBehaviour)this).__endSendServerRpc(ref val, 3276370873u, serverRpcParams, (RpcDelivery)0);
}
if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
{
return;
}
base.__rpc_exec_stage = (__RpcExecStage)0;
if (((NetworkBehaviour)this).IsServer)
{
ulong senderClientId = serverRpcParams.Receive.SenderClientId;
Plugin.logger.LogDebug((object)$"ConfigSync request received from client {senderClientId}");
byte[] array = ConfigSyncService.SerializeCurrent();
if (array.Length == 0)
{
Plugin.logger.LogError((object)"Aborting sync response: empty payload");
return;
}
ClientRpcParams val2 = default(ClientRpcParams);
val2.Send = new ClientRpcSendParams
{
TargetClientIds = new ulong[1] { senderClientId }
};
ClientRpcParams clientRpcParams = val2;
ReceiveConfigSyncClientRpc(array, clientRpcParams);
}
}
[ClientRpc]
public void ReceiveConfigSyncClientRpc(byte[] data, ClientRpcParams clientRpcParams = default(ClientRpcParams))
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Invalid comparison between Unknown and I4
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
if (networkManager == null || !networkManager.IsListening)
{
return;
}
if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
{
FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(2833577898u, clientRpcParams, (RpcDelivery)0);
bool flag = data != null;
((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
if (flag)
{
((FastBufferWriter)(ref val)).WriteValueSafe<byte>(data, default(ForPrimitives));
}
((NetworkBehaviour)this).__endSendClientRpc(ref val, 2833577898u, clientRpcParams, (RpcDelivery)0);
}
if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
{
base.__rpc_exec_stage = (__RpcExecStage)0;
if (!((NetworkBehaviour)this).IsServer)
{
Plugin.logger.LogInfo((object)$"Received config sync via ClientRpc, {((data != null) ? data.Length : 0)} bytes");
ConfigSyncService.ApplyReceivedSync(data);
}
}
}
[ClientRpc]
public void BroadcastConfigSyncClientRpc(byte[] data)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Invalid comparison between Unknown and I4
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
if (networkManager == null || !networkManager.IsListening)
{
return;
}
if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
{
ClientRpcParams val = default(ClientRpcParams);
FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(149726897u, val, (RpcDelivery)0);
bool flag = data != null;
((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
if (flag)
{
((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(data, default(ForPrimitives));
}
((NetworkBehaviour)this).__endSendClientRpc(ref val2, 149726897u, val, (RpcDelivery)0);
}
if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
{
base.__rpc_exec_stage = (__RpcExecStage)0;
if (!((NetworkBehaviour)this).IsServer)
{
Plugin.logger.LogInfo((object)$"Received config broadcast via ClientRpc, {((data != null) ? data.Length : 0)} bytes");
ConfigSyncService.ApplyReceivedSync(data);
}
}
}
[ClientRpc]
public void HideOriginalEnemyBodyClientRpc(NetworkObjectReference originalEnemyRef, Vector3 hidePosition)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Invalid comparison between Unknown and I4
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
if (networkManager == null || !networkManager.IsListening)
{
return;
}
if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
{
ClientRpcParams val = default(ClientRpcParams);
FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1086037223u, val, (RpcDelivery)0);
((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref originalEnemyRef, default(ForNetworkSerializable));
((FastBufferWriter)(ref val2)).WriteValueSafe(ref hidePosition);
((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1086037223u, val, (RpcDelivery)0);
}
if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsClient && !networkManager.IsHost))
{
return;
}
base.__rpc_exec_stage = (__RpcExecStage)0;
if (((NetworkBehaviour)this).IsServer)
{
return;
}
NetworkObject val3 = default(NetworkObject);
if (!((NetworkObjectReference)(ref originalEnemyRef)).TryGet(ref val3, (NetworkManager)null))
{
Plugin.logger.LogWarning((object)"HideOriginalEnemyBodyClientRpc: could not resolve enemy NetworkObject; skipping client-side teleport");
return;
}
((Component)val3).transform.position = hidePosition;
EnemyAI component = ((Component)val3).GetComponent<EnemyAI>();
if ((Object)(object)component != (Object)null)
{
component.serverPosition = hidePosition;
}
Plugin.logger.LogDebug((object)$"Hid original enemy body '{((Object)((Component)val3).gameObject).name}' at {hidePosition}");
}
protected override void __initializeVariables()
{
((NetworkBehaviour)this).__initializeVariables();
}
protected override void __initializeRpcs()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
((NetworkBehaviour)this).__registerRpc(3276370873u, new RpcReceiveHandler(__rpc_handler_3276370873), "RequestConfigSyncServerRpc");
((NetworkBehaviour)this).__registerRpc(2833577898u, new RpcReceiveHandler(__rpc_handler_2833577898), "ReceiveConfigSyncClientRpc");
((NetworkBehaviour)this).__registerRpc(149726897u, new RpcReceiveHandler(__rpc_handler_149726897), "BroadcastConfigSyncClientRpc");
((NetworkBehaviour)this).__registerRpc(1086037223u, new RpcReceiveHandler(__rpc_handler_1086037223), "HideOriginalEnemyBodyClientRpc");
((NetworkBehaviour)this).__initializeRpcs();
}
private static void __rpc_handler_3276370873(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = target.NetworkManager;
if (networkManager != null && networkManager.IsListening)
{
ServerRpcParams server = rpcParams.Server;
target.__rpc_exec_stage = (__RpcExecStage)1;
((EnhancedMonstersNetworkHandler)(object)target).RequestConfigSyncServerRpc(server);
target.__rpc_exec_stage = (__RpcExecStage)0;
}
}
private static void __rpc_handler_2833577898(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
{
//IL_002f: 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_0068: 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)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = target.NetworkManager;
if (networkManager != null && networkManager.IsListening)
{
bool flag = default(bool);
((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
byte[] data = null;
if (flag)
{
((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref data, default(ForPrimitives));
}
ClientRpcParams client = rpcParams.Client;
target.__rpc_exec_stage = (__RpcExecStage)1;
((EnhancedMonstersNetworkHandler)(object)target).ReceiveConfigSyncClientRpc(data, client);
target.__rpc_exec_stage = (__RpcExecStage)0;
}
}
private static void __rpc_handler_149726897(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
{
//IL_002f: 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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = target.NetworkManager;
if (networkManager != null && networkManager.IsListening)
{
bool flag = default(bool);
((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
byte[] data = null;
if (flag)
{
((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref data, default(ForPrimitives));
}
target.__rpc_exec_stage = (__RpcExecStage)1;
((EnhancedMonstersNetworkHandler)(object)target).BroadcastConfigSyncClientRpc(data);
target.__rpc_exec_stage = (__RpcExecStage)0;
}
}
private static void __rpc_handler_1086037223(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
{
//IL_002f: 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_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
NetworkManager networkManager = target.NetworkManager;
if (networkManager != null && networkManager.IsListening)
{
NetworkObjectReference originalEnemyRef = default(NetworkObjectReference);
((FastBufferReader)(ref reader)).ReadValueSafe<NetworkObjectReference>(ref originalEnemyRef, default(ForNetworkSerializable));
Vector3 hidePosition = default(Vector3);
((FastBufferReader)(ref reader)).ReadValueSafe(ref hidePosition);
target.__rpc_exec_stage = (__RpcExecStage)1;
((EnhancedMonstersNetworkHandler)(object)target).HideOriginalEnemyBodyClientRpc(originalEnemyRef, hidePosition);
target.__rpc_exec_stage = (__RpcExecStage)0;
}
}
protected internal override string __getTypeName()
{
return "EnhancedMonstersNetworkHandler";
}
}
}
namespace EnhancedMonsters.Monobehaviours
{
public class EnemyScrap : GrabbableObject
{
[CompilerGenerated]
private sealed class <DisableAnimatorOnAnimationEnd>d__22 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public EnemyScrap <>4__this;
private AnimatorClipInfo[] <currentClip>5__1;
private float <deathAnimDuration>5__2;
private float <deathAnimProgress>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DisableAnimatorOnAnimationEnd>d__22(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<currentClip>5__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: 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_0093: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
<currentClip>5__1 = <>4__this.EnemyAnimator.GetCurrentAnimatorClipInfo(0);
if (<currentClip>5__1.Length < 1)
{
return false;
}
<deathAnimDuration>5__2 = ((AnimatorClipInfo)(ref <currentClip>5__1[0])).clip.length;
AnimatorStateInfo currentAnimatorStateInfo = <>4__this.EnemyAnimator.GetCurrentAnimatorStateInfo(0);
<deathAnimProgress>5__3 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime;
break;
}
case 1:
<>1__state = -1;
break;
}
if (<deathAnimProgress>5__3 < <deathAnimDuration>5__2)
{
<>2__current = (object)new WaitForEndOfFrame();
<>1__state = 1;
return true;
}
((Behaviour)<>4__this.EnemyAnimator).enabled = false;
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public EnemyType enemyType;
private readonly NetworkVariable<int> _syncedScrapValue = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);
public Animator EnemyAnimator { get; private set; }
public ScanNodeProperties ScanNode { get; private set; }
public GameObject EnemyGameObject { get; set; }
public EnemyData EnemyData => LocalConfig.Singleton.synchronizeRanks.Value ? SyncedConfig.Instance.EnemiesData[enemyType.enemyName] : SyncedConfig.Default.EnemiesData[enemyType.enemyName];
public int SyncedScrapValue
{
get
{
return _syncedScrapValue.Value;
}
set
{
_syncedScrapValue.Value = value;
}
}
private void Awake()
{
EnemyAnimator = ((Component)this).gameObject.GetComponentInChildren<Animator>();
if ((Object)(object)EnemyAnimator == (Object)null)
{
Plugin.logger.LogWarning((object)("So somehow, the monster " + ((Object)((Component)this).gameObject).name + " does not have any Animator. Will work anyway but might have its animations glitched"));
}
ScanNode = ((Component)this).gameObject.GetComponentInChildren<ScanNodeProperties>();
if ((Object)(object)ScanNode == (Object)null)
{
Plugin.logger.LogWarning((object)("No ScanNode found in " + ((Object)((Component)this).gameObject).name + ". That's a weird enemy..."));
}
if (!base.itemProperties.saveItemVariable)
{
Plugin.logger.LogError((object)("Error: Enemy corpse saving was set to false for " + enemyType.enemyName));
}
}
public override void Start()
{
((GrabbableObject)this).Start();
if (((NetworkBehaviour)this).IsServer)
{
Plugin.logger.LogInfo((object)"Synchronizing the mob data and scrap values and positions with clients...");
EnemyData enemyData = SyncedConfig.Instance.EnemiesData[enemyType.enemyName];
if (GameNetworkManager.Instance.gameHasStarted || base.scrapValue == 0)
{
int syncedScrapValue = new Random().Next(enemyData.MinValue, enemyData.MaxValue);
SyncedScrapValue = syncedScrapValue;
}
else
{
SyncedScrapValue = base.scrapValue;
}
}
Plugin.logger.LogInfo((object)("Mob scrap " + enemyType.enemyName + " has spawned !"));
if ((Object)(object)EnemyAnimator != (Object)null)
{
if (!EnemyData.Metadata.AnimateOnDeath)
{
((Behaviour)EnemyAnimator).enabled = false;
}
try
{
EnemyAnimator.SetLayerWeight(2, 0f);
}
catch (Exception arg)
{
Plugin.logger.LogWarning((object)$"Failed to set layer 2's weight to 0 (bracken fix?). Error: {arg}");
((Behaviour)EnemyAnimator).enabled = false;
}
try
{
EnemyAnimator.SetBool("Stunned", false);
EnemyAnimator.SetBool("stunned", false);
EnemyAnimator.SetBool("stun", false);
EnemyAnimator.SetTrigger("KillEnemy");
EnemyAnimator.SetBool("Dead", true);
((MonoBehaviour)this).StartCoroutine(DisableAnimatorOnAnimationEnd());
}
catch (Exception arg2)
{
Plugin.logger.LogError((object)$"Failed to set the enemy {((Object)((Component)this).gameObject).name} mob mesh animator to dead state. Maybe the animator doesn't have a dead state ? Error: {arg2}");
((Behaviour)EnemyAnimator).enabled = false;
}
if (enemyType.enemyName == "Flowerman")
{
((Component)EnemyAnimator).gameObject.SetActive(false);
((Component)EnemyAnimator).gameObject.SetActive(true);
((Behaviour)EnemyAnimator).enabled = false;
}
}
if (Object.op_Implicit((Object)(object)ScanNode))
{
EnemyData enemyData2 = (LocalConfig.Singleton.synchronizeRanks.Value ? SyncedConfig.Instance.EnemiesData[enemyType.enemyName] : SyncedConfig.Default.EnemiesData[enemyType.enemyName]);
ScanNodeProperties component = ((Component)ScanNode).GetComponent<ScanNodeProperties>();
component.scrapValue = SyncedScrapValue;
component.subText = $"Rank:{enemyData2.Rank}\nValue: ${SyncedScrapValue}";
}
else
{
Plugin.logger.LogError((object)("Enemy corpse " + base.itemProperties.itemName + " is missing a ScanNode !"));
}
}
public void SetScrapValue(int value)
{
Plugin.logger.LogInfo((object)$"Setting scrap value for {base.itemProperties.itemName}: {value}");
base.scrapValue = value;
ScanNode.scrapValue = value;
EnemyData enemyData = (LocalConfig.Singleton.synchronizeRanks.Value ? SyncedConfig.Instance.EnemiesData[enemyType.enemyName] : SyncedConfig.Default.EnemiesData[enemyType.enemyName]);
ScanNode.subText = $"Rank: {enemyData.Rank}\nValue: {value}";
}
[IteratorStateMachine(typeof(<DisableAnimatorOnAnimationEnd>d__22))]
public IEnumerator DisableAnimatorOnAnimationEnd()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DisableAnimatorOnAnimationEnd>d__22(0)
{
<>4__this = this
};
}
public override void OnNetworkSpawn()
{
((NetworkBehaviour)this).OnNetworkSpawn();
((NetworkVariableBase)_syncedScrapValue).Initialize((NetworkBehaviour)(object)this);
NetworkVariable<int> syncedScrapValue = _syncedScrapValue;
syncedScrapValue.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Combine((Delegate?)(object)syncedScrapValue.OnValueChanged, (Delegate?)(object)(OnValueChangedDelegate<int>)delegate(int oldVal, int newVal)
{
SetScrapValue(newVal);
});
}
public override int GetItemDataToSave()
{
Plugin.logger.LogInfo((object)("GetItemData: Trying to save enemy scrap for " + base.itemProperties.itemName + "."));
return 0;
}
protected override void __initializeVariables()
{
if (_syncedScrapValue == null)
{
throw new Exception("EnemyScrap._syncedScrapValue cannot be null. All NetworkVariableBase instances must be initialized.");
}
((NetworkVariableBase)_syncedScrapValue).Initialize((NetworkBehaviour)(object)this);
((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)_syncedScrapValue, "_syncedScrapValue");
((NetworkBehaviour)this).NetworkVariableFields.Add((NetworkVariableBase)(object)_syncedScrapValue);
((GrabbableObject)this).__initializeVariables();
}
protected override void __initializeRpcs()
{
((GrabbableObject)this).__initializeRpcs();
}
protected internal override string __getTypeName()
{
return "EnemyScrap";
}
}
public class SpiderArachnophobiaToggle : MonoBehaviour
{
private MeshRenderer _safeMesh;
private SkinnedMeshRenderer _normalMesh;
private bool _renderersResolved;
private void Start()
{
ResolveRenderers();
ApplyArachnophobeMode(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode);
}
private void LateUpdate()
{
ApplyArachnophobeMode(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode);
}
public void ApplyArachnophobeMode(bool arachnophobeEnabled)
{
if (!_renderersResolved)
{
ResolveRenderers();
}
if (!((Object)(object)_safeMesh == (Object)null) && !((Object)(object)_normalMesh == (Object)null))
{
if (((Renderer)_safeMesh).enabled != arachnophobeEnabled)
{
((Renderer)_safeMesh).enabled = arachnophobeEnabled;
}
if (((Renderer)_normalMesh).enabled != !arachnophobeEnabled)
{
((Renderer)_normalMesh).enabled = !arachnophobeEnabled;
}
}
}
private void ResolveRenderers()
{
if (((Component)this).transform.childCount == 0)
{
return;
}
Transform child = ((Component)this).transform.GetChild(0);
Transform obj = child.Find("MeshContainer");
object obj2;
if (obj == null)
{
obj2 = null;
}
else
{
Transform obj3 = obj.Find("AnimContainer");
if (obj3 == null)
{
obj2 = null;
}
else
{
Transform obj4 = obj3.Find("Armature");
if (obj4 == null)
{
obj2 = null;
}
else
{
Transform obj5 = obj4.Find("Abdomen");
obj2 = ((obj5 != null) ? obj5.Find("SpiderText") : null);
}
}
}
Transform val = (Transform)obj2;
Transform obj6 = child.Find("MeshContainer");
Transform val2 = ((obj6 != null) ? obj6.Find("MeshRenderer") : null);
_safeMesh = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<MeshRenderer>() : null);
_normalMesh = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<SkinnedMeshRenderer>() : null);
if ((Object)(object)_safeMesh == (Object)null || (Object)(object)_normalMesh == (Object)null)
{
Plugin.logger.LogError((object)"This Spider mesh doesn't have a normal mesh or an arachnophobe mesh.");
}
else
{
_renderersResolved = true;
}
}
}
}
namespace EnhancedMonsters.Config
{
internal static class ConfigSyncService
{
[CompilerGenerated]
private sealed class <WaitForHandlerAndRequest>d__19 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
private float <waited>5__1;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <WaitForHandlerAndRequest>d__19(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<waited>5__1 = 0f;
break;
case 1:
<>1__state = -1;
<waited>5__1 += 0.25f;
break;
}
if ((Object)(object)EnhancedMonstersNetworkHandler.Instance == (Object)null && <waited>5__1 < 10f)
{
<>2__current = (object)new WaitForSeconds(0.25f);
<>1__state = 1;
return true;
}
if ((Object)(object)EnhancedMonstersNetworkHandler.Instance != (Object)null)
{
EnhancedMonstersNetworkHandler.Instance.RequestConfigSyncServerRpc();
Plugin.logger.LogInfo((object)$"Config sync request sent after {<waited>5__1:0.00}s wait");
}
else
{
Plugin.logger.LogWarning((object)$"Config sync handler did not appear within {10f}s, giving up");
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public static SyncedConfig Default { get; private set; }
public static SyncedConfig Instance { get; private set; }
public static bool Synced { get; internal set; }
public static bool IsHost
{
get
{
NetworkManager singleton = NetworkManager.Singleton;
return singleton != null && singleton.IsHost;
}
}
public static bool IsClient
{
get
{
NetworkManager singleton = NetworkManager.Singleton;
return singleton != null && singleton.IsClient;
}
}
public static void Initialize(SyncedConfig defaults)
{
Default = defaults;
Instance = defaults;
Synced = false;
}
public static void RevertSync()
{
Instance = Default;
Synced = false;
Plugin.logger.LogInfo((object)"Reverting sync, Instance=Default, Synced=false");
}
public static void RequestSync()
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
if (!IsClient || IsHost)
{
return;
}
if ((Object)(object)EnhancedMonstersNetworkHandler.Instance != (Object)null)
{
EnhancedMonstersNetworkHandler.Instance.RequestConfigSyncServerRpc();
Plugin.logger.LogInfo((object)"Requesting config sync via ServerRpc");
return;
}
Plugin.logger.LogInfo((object)"EnhancedMonstersNetworkHandler not yet spawned, scheduling retry");
StartOfRound instance = StartOfRound.Instance;
if ((Object)(object)instance != (Object)null)
{
((MonoBehaviour)instance).StartCoroutine(WaitForHandlerAndRequest());
}
else
{
Plugin.logger.LogWarning((object)"StartOfRound.Instance is null, cannot schedule sync retry");
}
}
[IteratorStateMachine(typeof(<WaitForHandlerAndRequest>d__19))]
private static IEnumerator WaitForHandlerAndRequest()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <WaitForHandlerAndRequest>d__19(0);
}
public static void BroadcastSync()
{
if (!IsHost)
{
return;
}
EnhancedMonstersNetworkHandler instance = EnhancedMonstersNetworkHandler.Instance;
if ((Object)(object)instance == (Object)null)
{
Plugin.logger.LogDebug((object)"BroadcastSync: handler not spawned yet, skipping");
return;
}
byte[] array = SerializeCurrent();
if (array.Length != 0)
{
instance.BroadcastConfigSyncClientRpc(array);
Plugin.logger.LogInfo((object)$"Host broadcast config sync, {array.Length} bytes");
}
}
public static byte[] SerializeCurrent()
{
if (Instance == null)
{
Plugin.logger.LogError((object)"SerializeCurrent: Instance is null");
return Array.Empty<byte>();
}
try
{
string s = JsonConvert.SerializeObject((object)Instance.EnemiesData);
return Encoding.UTF8.GetBytes(s);
}
catch (Exception arg)
{
Plugin.logger.LogError((object)$"Failed to serialize sync payload: {arg}");
return Array.Empty<byte>();
}
}
public static void ApplyReceivedSync(byte[] data)
{
if (data == null || data.Length == 0)
{
Plugin.logger.LogError((object)"ApplyReceivedSync: empty payload");
return;
}
if (Instance == null)
{
Plugin.logger.LogError((object)"ApplyReceivedSync: Instance is null, cannot apply");
return;
}
try
{
string @string = Encoding.UTF8.GetString(data);
Dictionary<string, EnemyData> dictionary = JsonConvert.DeserializeObject<Dictionary<string, EnemyData>>(@string);
if (dictionary == null)
{
Plugin.logger.LogError((object)"ApplyReceivedSync: deserialization returned null");
return;
}
EnemiesDataManager.EnemiesData.Clear();
foreach (KeyValuePair<string, EnemyData> item in dictionary)
{
EnemiesDataManager.EnemiesData[item.Key] = item.Value;
}
Synced = true;
Plugin.logger.LogInfo((object)$"Applied sync, {dictionary.Count} entries, Synced=true");
}
catch (Exception arg)
{
Plugin.logger.LogError((object)$"Failed to apply sync payload: {arg}");
}
}
}
internal static class LethalConfigSupport
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static CanModifyDelegate <>9__3_1;
public static GenericButtonHandler <>9__3_0;
internal CanModifyResult <RegisterLethalConfig>b__3_1()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
return CanModifyResult.op_Implicit(!GameNetworkManager.Instance.gameHasStarted || !NetworkManager.Singleton.IsListening);
}
internal void <RegisterLethalConfig>b__3_0()
{
GUIUtility.systemCopyBuffer = EnemiesDataManager.EnemiesDataFile;
}
}
private static bool? lethalConfigLoaded;
public static bool LethalConfigLoaded
{
get
{
bool valueOrDefault = lethalConfigLoaded.GetValueOrDefault();
if (!lethalConfigLoaded.HasValue)
{
valueOrDefault = Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig");
lethalConfigLoaded = valueOrDefault;
}
return lethalConfigLoaded.Value;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
internal static void RegisterLethalConfig(LocalConfig config)
{
//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)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected O, but got Unknown
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Expected O, but got Unknown
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
LethalConfigManager.SetModDescription("Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements.");
ConfigEntry<bool> synchronizeRanks = config.synchronizeRanks;
BoolCheckBoxOptions val = new BoolCheckBoxOptions
{
Name = "Synchronize Ranks",
Section = "General",
RequiresRestart = false
};
object obj = <>c.<>9__3_1;
if (obj == null)
{
CanModifyDelegate val2 = () => CanModifyResult.op_Implicit(!GameNetworkManager.Instance.gameHasStarted || !NetworkManager.Singleton.IsListening);
<>c.<>9__3_1 = val2;
obj = (object)val2;
}
((BaseOptions)val).CanModifyCallback = (CanModifyDelegate)obj;
BoolCheckBoxConfigItem val3 = new BoolCheckBoxConfigItem(synchronizeRanks, val);
object obj2 = <>c.<>9__3_0;
if (obj2 == null)
{
GenericButtonHandler val4 = delegate
{
GUIUtility.systemCopyBuffer = EnemiesDataManager.EnemiesDataFile;
};
<>c.<>9__3_0 = val4;
obj2 = (object)val4;
}
GenericButtonConfigItem val5 = new GenericButtonConfigItem("General", "Enemies Data", "All the enemies data are stored inside the file. You have a few rules to follow when editing the file or it will not work. Look at the github or thunderstore page for more info.", "Copy path", (GenericButtonHandler)obj2);
LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val3);
LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val5);
}
}
internal static class LethalSettingsSupport
{
private static bool? lethalSettingsLoaded;
public static bool LethalSettingsLoaded
{
get
{
bool valueOrDefault = lethalSettingsLoaded.GetValueOrDefault();
if (!lethalSettingsLoaded.HasValue)
{
valueOrDefault = Chainloader.PluginInfos.ContainsKey("com.willis.lc.lethalsettings");
lethalSettingsLoaded = valueOrDefault;
}
return lethalSettingsLoaded.Value;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
internal static void RegisterLethalSettings(LocalConfig config)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Expected O, but got Unknown
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Expected O, but got Unknown
LocalConfig config2 = config;
Plugin.logger.LogInfo((object)"Registering lsSyncRank");
ToggleComponent val = new ToggleComponent
{
Enabled = true,
Text = "Synchronize Ranks",
Value = true,
OnValueChanged = delegate(ToggleComponent comp, bool value)
{
config2.synchronizeRanks.Value = value;
},
OnInitialize = delegate(ToggleComponent comp)
{
comp.Value = config2.synchronizeRanks.Value;
comp.Enabled = !GameNetworkManager.Instance.gameHasStarted || !NetworkManager.Singleton.IsListening;
}
};
Plugin.logger.LogInfo((object)"Registering lsAccessEnemiesDataFile");
ButtonComponent val2 = new ButtonComponent
{
Enabled = true,
ShowCaret = true,
Text = "Copy path to Enemies Data file",
OnClick = delegate
{
GUIUtility.systemCopyBuffer = EnemiesDataManager.EnemiesDataFile;
}
};
Plugin.logger.LogInfo((object)"Registering mod info");
ModSettingsConfig val3 = new ModSettingsConfig();
val3.Id = "com.velddev.enhancedmonsters";
val3.Name = "Enhanced Monsters";
val3.Version = "1.4.0";
val3.Description = "Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements.";
val3.MenuComponents = (MenuComponent[])(object)new MenuComponent[2]
{
(MenuComponent)val,
(MenuComponent)val2
};
ModMenu.RegisterMod(val3);
Plugin.logger.LogInfo((object)"Registered Mod Info");
}
}
public class LocalConfig
{
internal const string ModDesc = "Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements.";
public readonly ConfigEntry<bool> synchronizeRanks;
public static LocalConfig Singleton { get; private set; }
public LocalConfig(ConfigFile cfg)
{
Singleton = this;
synchronizeRanks = cfg.Bind<bool>("General", "Synchronize Ranks", true, "Wether or not to synchronize ranks of enemies from host's configs. It is recommended to keep it enabled. [NOTE: This setting can only be edited from the main menu.]");
if (LethalConfigSupport.LethalConfigLoaded)
{
Plugin.logger.LogInfo((object)"Loading LethalConfig settings");
LethalConfigSupport.RegisterLethalConfig(this);
}
if (LethalSettingsSupport.LethalSettingsLoaded)
{
Plugin.logger.LogInfo((object)"Loading LethalSettings settings");
LethalSettingsSupport.RegisterLethalSettings(this);
}
Plugin.logger.LogInfo((object)"Registering all settings.");
}
}
public class SyncedConfig
{
public Dictionary<string, EnemyData> EnemiesData;
public ConfigFile BepInConfigs;
public static SyncedConfig Default => ConfigSyncService.Default;
public static SyncedConfig Instance => ConfigSyncService.Instance;
public static bool Synced => ConfigSyncService.Synced;
public static bool IsHost => ConfigSyncService.IsHost;
public static bool IsClient => ConfigSyncService.IsClient;
public SyncedConfig(ConfigFile cfg)
{
BepInConfigs = cfg;
EnemiesData = EnemiesDataManager.EnemiesData;
ConfigSyncService.Initialize(this);
}
public static void BroadcastSync()
{
ConfigSyncService.BroadcastSync();
}
public static void RequestSync()
{
ConfigSyncService.RequestSync();
}
public static void RevertSync()
{
ConfigSyncService.RevertSync();
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}
namespace __GEN
{
internal class NetworkVariableSerializationHelper
{
[RuntimeInitializeOnLoadMethod]
internal static void InitializeSerialization()
{
}
}
}
namespace EnhancedMonsters.NetcodePatcher
{
[AttributeUsage(AttributeTargets.Module)]
internal class NetcodePatchedAssemblyAttribute : Attribute
{
}
}