using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading.Tasks; using AIGraph; using AK; using Agents; using AssetShards; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Utils.Collections; using CellMenu; using CullingSystem; using EEC.API; using EEC.Configs; using EEC.Configs.Customizations; using EEC.CustomAbilities.Bleed; using EEC.CustomAbilities.Bleed.Handlers; using EEC.CustomAbilities.Bleed.Inject; using EEC.CustomAbilities.DrainStamina; using EEC.CustomAbilities.EMP; using EEC.CustomAbilities.EMP.Handlers; using EEC.CustomAbilities.EMP.Inject; using EEC.CustomAbilities.Explosion; using EEC.CustomAbilities.Explosion.Handlers; using EEC.CustomAbilities.FogHealth; using EEC.CustomAbilities.Infection; using EEC.CustomAbilities.Knockback; using EEC.CustomSettings.CustomProjectiles; using EEC.CustomSettings.CustomScoutWaves; using EEC.CustomSettings.CustomTentacles; using EEC.EnemyCustomizations; using EEC.EnemyCustomizations.Abilities; using EEC.EnemyCustomizations.Abilities.Handlers; using EEC.EnemyCustomizations.Abilities.Inject; using EEC.EnemyCustomizations.Detections; using EEC.EnemyCustomizations.EnemyAbilities; using EEC.EnemyCustomizations.EnemyAbilities.Abilities; using EEC.EnemyCustomizations.EnemyAbilities.Events; using EEC.EnemyCustomizations.EnemyAbilities.Handlers; using EEC.EnemyCustomizations.Models; using EEC.EnemyCustomizations.Models.Handlers; using EEC.EnemyCustomizations.Properties; using EEC.EnemyCustomizations.Shared; using EEC.EnemyCustomizations.Shared.Handlers; using EEC.EnemyCustomizations.Shooters; using EEC.EnemyCustomizations.Shooters.Handlers; using EEC.EnemyCustomizations.Strikers; using EEC.Events; using EEC.Managers; using EEC.Managers.Assets; using EEC.Managers.Properties; using EEC.Networking; using EEC.Networking.Events; using EEC.Networking.Replicators; using EEC.Patches.Handlers; using EEC.Utils; using EEC.Utils.Integrations; using EEC.Utils.Json; using EEC.Utils.Json.Converters; using EEC.Utils.Json.Elements; using EEC.Utils.Unity; using Enemies; using ExtraEnemyCustomization.Extensions; using GTFO.API; using GTFO.API.Utilities; using GameData; using Gear; using HarmonyLib; using IRF; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.InteropTypes.Fields; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using InjectLib.JsonNETInjection.Supports; using LevelGeneration; using Localization; using Microsoft.CodeAnalysis; using Player; using SNetwork; using SemanticVersioning; using StateMachines; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ExtraEnemyCustomization")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6ed8092032ccde82d4951ffce9ac8042ac794cfa")] [assembly: AssemblyProduct("ExtraEnemyCustomization")] [assembly: AssemblyTitle("ExtraEnemyCustomization")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] 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; } } } namespace ExtraEnemyCustomization.Inject { [HarmonyPatch(typeof(PlayerAgent), "ReceiveModification")] internal static class Inject_PlayerAgent_ReceiveModification { [HarmonyWrapSafe] [HarmonyPriority(200)] private static void Prefix(PlayerAgent __instance, ref EV_ModificationData data) { float health = data.health; if (health != 0f) { data.health = 0f; FogHealthManager.DoHealthChange(__instance, health); } } } } namespace ExtraEnemyCustomization.Extensions { public static class CellSoundPlayerExtension { public static uint PostWithCleanup(this CellSoundPlayer soundPlayer, uint eventID, Vector3 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return soundPlayer.Post(eventID, pos, 1u, EventCallback.op_Implicit((Action)SoundDoneCallback), (Object)(object)soundPlayer); } public static void SoundDoneCallback(Object in_cookie, AkCallbackType in_type, AkCallbackInfo callbackInfo) { CellSoundPlayer obj = ((Il2CppObjectBase)in_cookie).Cast(); if (obj != null) { obj.Recycle(); } } } } namespace EEC { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] internal sealed class CallConstructorOnLoadAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] internal sealed class InjectToIl2CppAttribute : Attribute { } public static class Configuration { public const string SECTION_USER = "1. User-End"; public const string SECTION_RUNDEVS = "2. Rundown Developer"; public const string SECTION_LOGGING = "3. Logging"; public const string SECTION_DEV = "4. DEBUG"; public const int CONFIG_VERSION = 1; private static ConfigEntry _showMarkerText; private static ConfigEntry _showMarkerDistance; private static ConfigEntry _showExplosionEffect; private static ConfigEntry _shitpostType; private static ConfigEntry _useLiveEdit; private static ConfigEntry _linkMTFOHotReload; private static ConfigEntry _useDebugLog; private static ConfigEntry _useVerboseLog; private static ConfigEntry _assetCacheBehaviour; private static ConfigEntry _dumpConfig; private static ConfigEntry _profiler; private static ConfigFile _currentContext; public static bool ShowMarkerText { get; private set; } public static bool ShowMarkerDistance { get; private set; } public static bool ShowExplosionEffect { get; private set; } public static ShitpostType ShitpostType { get; private set; } public static bool UseLiveEdit { get; private set; } public static bool LinkMTFOHotReload { get; private set; } public static bool UseDebugLog { get; private set; } public static bool UseVerboseLog { get; private set; } public static AssetCacheManager.OutputType AssetCacheBehaviour { get; private set; } public static bool DumpConfig { get; private set; } public static bool Profiler { get; private set; } public static bool CanShitpostOf(ShitpostType type) { switch (ShitpostType) { case ShitpostType.ForceOff: return false; case ShitpostType.Enable: { DateTime now = DateTime.Now; if (now.Month == 4) { return now.Day == 1; } return false; } default: return ShitpostType.HasFlag(type); } } public static void CreateAndBindAll() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "EEC.cfg"); ConfigFile context = new ConfigFile(text, true); if (BindConfigVersion(context).Value < 1) { File.Delete(text); context = new ConfigFile(text, true); BindConfigVersion(context); } BindAll(context); } public static void BindAll(ConfigFile context) { _currentContext = context; _showMarkerText = BindUserConfig("Marker Text", "Display Enemy Marker Texts? (if set by rundown devs)", defaultValue: true); _showMarkerDistance = BindUserConfig("Marker Distance", "Display Enemy Marker Distance? (if set by rundown devs)", defaultValue: true); _showExplosionEffect = BindUserConfig("Explosion Flash", "(Accessibility) Display Light flash effect for explosion abilities?", defaultValue: true); _shitpostType = BindUserConfig("Shitposting", "Shitpost mode use comma to enable multiple stuffs", ShitpostType.ForceOff); ShowMarkerText = _showMarkerText.Value; ShowMarkerDistance = _showMarkerDistance.Value; ShowExplosionEffect = _showExplosionEffect.Value; ShitpostType = _shitpostType.Value; _useLiveEdit = BindRdwDevConfig("Live Edit", "Reload Config when they are edited while in-game", defaultValue: true); _linkMTFOHotReload = BindRdwDevConfig("Reload on MTFO HotReload", "Reload Configs when MTFO's HotReload button has pressed?", defaultValue: true); UseLiveEdit = _useLiveEdit.Value; LinkMTFOHotReload = _linkMTFOHotReload.Value; _useDebugLog = BindLoggingConfig("UseDevMessage", "Using Dev Message for Debugging your config?", defaultValue: false); _useVerboseLog = BindLoggingConfig("Verbose", "Using Much more detailed Message for Debugging?", defaultValue: false); _assetCacheBehaviour = BindLoggingConfig("Cached Asset Result Output", "How does your cached material/texture result be returned?", AssetCacheManager.OutputType.None); UseDebugLog = _useDebugLog.Value; UseVerboseLog = _useVerboseLog.Value; AssetCacheBehaviour = _assetCacheBehaviour.Value; _dumpConfig = BindDevConfig("DumpConfig", "Dump Empty Config file?", defaultValue: false); _profiler = BindDevConfig("Profiler", "Show Profiler Info for Spawned Event", defaultValue: false); DumpConfig = _dumpConfig.Value; Profiler = _profiler.Value; } private static ConfigEntry BindConfigVersion(ConfigFile context) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown return context.Bind(new ConfigDefinition("Version", "Config Version"), 1, (ConfigDescription)null); } private static ConfigEntry BindUserConfig(string name, string description, T defaultValue) { return BindItem(_currentContext, "1. User-End", name, description, defaultValue); } private static ConfigEntry BindRdwDevConfig(string name, string description, T defaultValue) { return BindItem(_currentContext, "2. Rundown Developer", name, description, defaultValue); } private static ConfigEntry BindLoggingConfig(string name, string description, T defaultValue) { return BindItem(_currentContext, "3. Logging", name, description, defaultValue); } private static ConfigEntry BindDevConfig(string name, string description, T defaultValue) { return BindItem(_currentContext, "4. DEBUG", name, description, defaultValue); } private static ConfigEntry BindItem(ConfigFile context, string section, string name, string description, T defaultValue) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001b: Expected O, but got Unknown return context.Bind(new ConfigDefinition(section, name), defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty())); } } [BepInPlugin("GTFO.EECustomization", "EECustom", "1.8.25")] [BepInProcess("GTFO.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class EntryPoint : BasePlugin { public static Harmony HarmonyInstance { get; private set; } public static string BasePath { get; private set; } public override void Load() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown Configuration.CreateAndBindAll(); Logger.Initialize(); InjectAllIl2CppType(); CallAllAutoConstructor(); BasePath = Path.Combine(MTFOUtil.CustomPath, "ExtraEnemyCustomization"); HarmonyInstance = new Harmony("EEC.Harmony"); HarmonyInstance.PatchAll(); NetworkManager.Initialize(); ConfigManager.Initialize(); if (Configuration.DumpConfig) { ConfigManager.DumpDefault(); } AssetEvents.AllAssetLoaded += AllAssetLoaded; AssetCacheManager.OutputMethod = Configuration.AssetCacheBehaviour; } private void AllAssetLoaded() { SpriteManager.Initialize(); AssetCacheManager.AssetLoaded(); ConfigManager.FireAssetLoaded(); ConfigManager.FirePrefabBuildEventAll(rebuildPrefabs: false); } public override bool Unload() { UninjectAllIl2CppType(); HarmonyInstance.UnpatchSelf(); ConfigManager.UnloadAllConfig(doClear: true); return ((BasePlugin)this).Unload(); } private void InjectAllIl2CppType() { Logger.Debug("Injecting IL2CPP Types"); IEnumerable allHandlers = GetAllHandlers(); Logger.Debug($" - Count: {allHandlers.Count()}"); foreach (Type item in allHandlers) { if (!ClassInjector.IsTypeRegisteredInIl2Cpp(item)) { ClassInjector.RegisterTypeInIl2Cpp(item); } } } private void CallAllAutoConstructor() { Logger.Debug("Calling Necessary Static .ctors"); IEnumerable allAutoConstructor = GetAllAutoConstructor(); Logger.Debug($" - Count: {allAutoConstructor.Count()}"); foreach (Type item in allAutoConstructor) { Logger.Debug("calling ctor of: " + item.Name); RuntimeHelpers.RunClassConstructor(item.TypeHandle); } } private void UninjectAllIl2CppType() { Logger.Debug("Uninjecting IL2CPP Types"); IEnumerable allHandlers = GetAllHandlers(); Logger.Debug($" - Count: {allHandlers.Count()}"); foreach (Type item in allHandlers) { ClassInjector.IsTypeRegisteredInIl2Cpp(item); } } private IEnumerable GetAllAutoConstructor() { return from type in ((object)this).GetType().Assembly.GetTypes() where type != null && Attribute.IsDefined(type, typeof(CallConstructorOnLoadAttribute)) select type; } private IEnumerable GetAllHandlers() { return from type in ((object)this).GetType().Assembly.GetTypes() where type != null && Attribute.IsDefined(type, typeof(InjectToIl2CppAttribute)) select type; } } public static class AgentExtension { public static bool TryCastToEnemyAgent(this Agent agent, out EnemyAgent enemyAgent) { return TryCast(agent, (AgentType)1, out enemyAgent); } public static bool TryCastToPlayerAgent(this Agent agent, out PlayerAgent playerAgent) { return TryCast(agent, (AgentType)0, out playerAgent); } private static bool TryCast(Agent agent, AgentType type, out T result) where T : Agent { //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 (!((Object)(object)agent == (Object)null) && !((Il2CppObjectBase)agent).WasCollected && agent.Type == type) { T val = ((Il2CppObjectBase)agent).TryCast(); if (!((Object)(object)val == (Object)null)) { result = val; return true; } } result = default(T); return false; } public static void GetRagdollPosition(this Agent agent, ref Vector3 position) { if (agent.TryCastToEnemyAgent(out EnemyAgent enemyAgent)) { enemyAgent.GetRagdollPosition(ref position); } } } public static class EasingExtension { public static float Evaluate(this eEasingType easeType, float progress, bool backward = false) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Easing.GetEasingValue(easeType, progress, backward); } public static Func GetEaseFunction(this eEasingType easeType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected I4, but got Unknown return (easeType - 1) switch { 0 => Easing.EaseInQuad, 1 => Easing.EaseOutQuad, 2 => Easing.EaseInOutQuad, 3 => Easing.EaseInCubic, 4 => Easing.EaseOutCubic, 5 => Easing.EaseInOutCubic, 6 => Easing.EaseInQuart, 7 => Easing.EaseOutQuart, 8 => Easing.EaseInOutQuart, 9 => Easing.EaseInQuint, 10 => Easing.EaseOutQuint, 11 => Easing.EaseInOutQuint, 12 => Easing.EaseInSine, 13 => Easing.EaseOutSine, 14 => Easing.EaseInOutSine, 15 => Easing.EaseInExpo, 16 => Easing.EaseOutExpo, 17 => Easing.EaseInOutExpo, 18 => Easing.EaseInCirc, 19 => Easing.EaseOutCirc, 20 => Easing.EaseInOutCirc, _ => Easing.LinearTween, }; } } public static class EnemyAgentExtension { public static void AddOnDeadOnce(this EnemyAgent agent, Action onDead) { Action onDead2 = onDead; bool called = false; agent.OnDeadCallback += Action.op_Implicit((Action)delegate { if (!called && !CheckpointManager.IsReloadingCheckpoint) { onDead2?.Invoke(); called = true; } }); } public static T RegisterOrGetProperty(this EnemyAgent agent) where T : class, new() { return EnemyProperty.RegisterOrGet(agent); } public static bool TryGetProperty(this EnemyAgent agent, out T property) where T : class, new() { return EnemyProperty.TryGet(agent, out property); } public static bool TryGetSpawnData(this EnemyAgent agent, out pEnemySpawnData spawnData) { return EnemySpawnDataManager.TryGet(((Agent)agent).GlobalID, out spawnData); } public static bool TryGetEnemyGroup(this EnemyAgent agent, out EnemyGroup group) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!agent.TryGetSpawnData(out var spawnData)) { group = null; return false; } if (spawnData.groupReplicatorKey == 0) { group = null; return false; } IReplicator val = default(IReplicator); if (!SNet_Replication.TryGetReplicator(spawnData.groupReplicatorKey, ref val)) { group = null; return false; } if (val.ReplicatorSupplier == null) { group = null; return false; } group = ((Il2CppObjectBase)val.ReplicatorSupplier).TryCast(); return (Object)(object)group != (Object)null; } public static AIG_CourseNode GetSpawnedNode(this EnemyAgent agent) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) pEnemySpawnData spawnData = ((SNet_DynamicReplicator)(object)((Il2CppObjectBase)agent.Sync.Replicator).Cast()).GetSpawnData(); AIG_CourseNode result = default(AIG_CourseNode); if (!((pCourseNode)(ref spawnData.courseNode)).TryGet(ref result)) { return null; } return result; } public static void GetRagdollPosition(this EnemyAgent agent, ref Vector3 position) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0039: 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) if (!((Agent)agent).Alive && agent.RagdollInstance != null && (int)agent.EnemyMovementData.LocomotionDead == 11) { EnemyRagdollBodyData componentInChildren = agent.RagdollInstance.GetComponentInChildren(); if (componentInChildren != null) { position = ((Component)componentInChildren).transform.position; } } } public static bool CanUseAbilities(this EnemyAgent agent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected I4, but got Unknown ES_StateEnum currentStateEnum = agent.Locomotion.CurrentStateEnum; switch (currentStateEnum - 7) { case 0: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 16: case 18: case 19: case 20: case 22: case 24: case 25: case 26: return false; default: return true; } } public static bool IsStopped(this EnemyAgent agent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected I4, but got Unknown ES_StateEnum currentStateEnum = agent.Locomotion.CurrentStateEnum; switch (currentStateEnum - 7) { case 0: case 4: case 5: case 6: case 9: case 10: case 11: case 12: case 13: case 16: case 19: case 22: case 23: case 24: case 25: case 26: return true; default: return false; } } public static bool CanApplyRootMotion(this EnemyAgent agent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_000f: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 ES_StateEnum currentStateEnum = agent.Locomotion.CurrentStateEnum; if ((int)currentStateEnum <= 17) { if ((int)currentStateEnum == 2 || (int)currentStateEnum == 17) { goto IL_0026; } } else if ((int)currentStateEnum == 24 || (int)currentStateEnum == 28) { goto IL_0026; } return true; IL_0026: return false; } } public static class EnemyDataBlockExtension { public static bool TryGetBehaviourBlock(this EnemyDataBlock data, out EnemyBehaviorDataBlock behaviour) { if (data == null) { behaviour = null; return false; } behaviour = GameDataBlockBase.GetBlock(data.BehaviorDataId); return behaviour != null; } public static bool TryGetBalancingBlock(this EnemyDataBlock data, out EnemyBalancingDataBlock balancing) { if (data == null) { balancing = null; return false; } balancing = GameDataBlockBase.GetBlock(data.BalancingDataId); return balancing != null; } } public static class GameObjectExtension { public static bool TryGetComp(this GameObject obj, out T component) { component = obj.GetComponent(); return component != null; } public static T AddOrGetComponent(this GameObject obj) where T : Component { if (!obj.TryGetComp(out var component)) { return obj.AddComponent(); } return component; } public static GameObject FindChild(this GameObject obj, string name, bool includeInactive = false) { foreach (Transform componentsInChild in obj.GetComponentsInChildren(includeInactive)) { if (!(((Object)((Component)componentsInChild).gameObject).name != name)) { return ((Component)componentsInChild).gameObject; } } return null; } public static GameObject RegexFindChild(this GameObject obj, Regex rx, bool includeInactive = false) { foreach (Transform componentsInChild in obj.GetComponentsInChildren(includeInactive)) { if (rx.IsMatch(((Object)componentsInChild).name)) { return ((Component)componentsInChild).gameObject; } } return null; } public static GameObject Instantiate(this GameObject obj, Transform toParent, string name) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) GameObject obj2 = Object.Instantiate(obj); obj2.transform.parent = toParent; obj2.transform.localPosition = Vector3.zero; obj2.transform.localRotation = Quaternion.Euler(Vector3.zero); ((Object)obj2).name = name; return obj2; } } public static class MonoBehaviourExtension { public static Coroutine StartCoroutine(this MonoBehaviour self, IEnumerator routine) { return self.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(routine)); } } public static class ProjectileTargetingExtension { public static bool TryGetOwnerEnemyDataID(this ProjectileBase projectile, out uint id) { if ((Object)(object)projectile == (Object)null) { id = 0u; return false; } return ProjectileOwnerManager.TryGetDataID(((Object)((Component)projectile).gameObject).GetInstanceID(), out id); } public static bool TryGetOwnerEnemyDataID(this ProjectileTargeting projectile, out uint id) { if ((Object)(object)projectile == (Object)null) { id = 0u; return false; } return ProjectileOwnerManager.TryGetDataID(((Object)((Component)projectile).gameObject).GetInstanceID(), out id); } public static bool TryGetOwner(this ProjectileBase projectile, out EnemyAgent agent) { if ((Object)(object)projectile == (Object)null) { agent = null; return false; } return ProjectileOwnerManager.TryGet(((Object)((Component)projectile).gameObject).GetInstanceID(), out agent); } public static bool TryGetOwner(this ProjectileTargeting projectile, out EnemyAgent agent) { if ((Object)(object)projectile == (Object)null) { agent = null; return false; } return ProjectileOwnerManager.TryGet(((Object)((Component)projectile).gameObject).GetInstanceID(), out agent); } } public static class StringExtension { public static bool InvariantEquals(this string str, string strToCompare, bool ignoreCase = false) { return str.Equals(strToCompare, ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture); } public static bool InvariantContains(this string str, string strToCompare, bool ignoreCase = false) { return str.Contains(strToCompare, ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture); } public static bool InvariantStartsWith(this string str, string strToCompare, bool ignoreCase = false) { return str.StartsWith(strToCompare, ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture); } public static bool InvariantEndsWith(this string str, string strToCompare, bool ignoreCase = false) { return str.EndsWith(strToCompare, ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture); } public static bool EqualsAnyIgnoreCase(this string input, params string[] args) { return input.EqualsAny(ignoreCase: true, args); } public static bool EqualsAny(this string input, bool ignoreCase, params string[] args) { StringComparison comparisonType = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); foreach (string value in args) { if (input.Equals(value, comparisonType)) { return true; } } return false; } public static bool ContainsAnyIgnoreCase(this string input, params string[] args) { return input.ContainsAny(ignoreCase: true, args); } public static bool ContainsAny(this string input, bool ignoreCase, params string[] args) { StringComparison comparisonType = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); foreach (string value in args) { if (input.Contains(value, comparisonType)) { return true; } } return false; } } public static class Logger { public static ManualLogSource LogInstance { get; private set; } public static bool UsingDevMessage { get; private set; } public static bool UsingVerbose { get; private set; } public static bool DevLogAllowed => UsingDevMessage; public static bool VerboseLogAllowed { get { if (UsingDevMessage) { return UsingVerbose; } return false; } } internal static void Initialize() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown LogInstance = new ManualLogSource("EEC"); Logger.Sources.Add((ILogSource)(object)LogInstance); UsingDevMessage = Configuration.UseDebugLog; UsingVerbose = Configuration.UseVerboseLog; } public static void Log(string format, params object[] args) { Log(string.Format(format, args)); } public static void Log(string str) { ManualLogSource logInstance = LogInstance; if (logInstance != null) { logInstance.Log((LogLevel)8, (object)str); } } public static void Warning(string format, params object[] args) { Warning(string.Format(format, args)); } public static void Warning(string str) { ManualLogSource logInstance = LogInstance; if (logInstance != null) { logInstance.Log((LogLevel)4, (object)str); } } public static void Error(string format, params object[] args) { Error(string.Format(format, args)); } public static void Error(string str) { ManualLogSource logInstance = LogInstance; if (logInstance != null) { logInstance.Log((LogLevel)2, (object)str); } } public static void Debug(string format, params object[] args) { Debug(string.Format(format, args)); } public static void Debug(string str) { if (UsingDevMessage) { ManualLogSource logInstance = LogInstance; if (logInstance != null) { logInstance.LogDebug((object)str); } } } public static void Verbose(string format, params object[] args) { Verbose(string.Format(format, args)); } public static void Verbose(string str) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (!UsingDevMessage || !UsingVerbose) { return; } ManualLogSource logInstance = LogInstance; if (logInstance != null) { bool flag = default(bool); BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(10, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(str); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (Verbose)"); } logInstance.LogDebug(val); } } [Conditional("DEBUG")] [Obsolete("Logger.Dev call will be removed in release mode!")] public static void Dev(string format, params object[] args) { } [Conditional("DEBUG")] [Obsolete("Logger.Dev call will be removed in release mode!")] public static void Dev(string str) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) ManualLogSource logInstance = LogInstance; if (logInstance != null) { LogLevel val = (LogLevel)8; LogLevel val2 = val; bool flag = default(bool); BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(6, 1, val, ref flag); if (flag) { val3.AppendLiteral("[DEV] "); val3.AppendFormatted(str); } logInstance.Log(val2, val3); } } } } namespace EEC.Utils { public static class EnemyAnimUtil { private static readonly Dictionary _animHashsLookup; private static bool _initialized; static EnemyAnimUtil() { _animHashsLookup = new Dictionary(Enum.GetValues(typeof(EnemyAnimType)).Length); } internal static void Initialize() { if (!_initialized) { CacheLookup(); _initialized = true; } } private static void CacheLookup() { Type typeFromHandle = typeof(EnemyLocomotion); foreach (EnemyAnimType value in Enum.GetValues(typeof(EnemyAnimType))) { switch (value) { case EnemyAnimType.Heartbeats: _animHashsLookup.Add(value, Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)EnemyLocomotion.s_hashHearbeats)); Logger.Verbose($"{value}, {string.Join(" / ", (IEnumerable)EnemyLocomotion.s_hashHearbeats)}"); continue; case EnemyAnimType.None: continue; } string text = "s_hash" + Enum.GetName(typeof(EnemyAnimType), value); PropertyInfo property = typeFromHandle.GetProperty(text, BindingFlags.Static | BindingFlags.Public); if (property == null) { Logger.Warning(text + " does not exist!"); } else if (property.PropertyType == typeof(int)) { _animHashsLookup.Add(value, new int[1] { (int)property.GetValue(null) }); Logger.Verbose($"{value}, {property.GetValue(null)}"); } else if (property.PropertyType == typeof(Il2CppStructArray)) { int[] array = Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)(Il2CppStructArray)property.GetValue(null)); _animHashsLookup.Add(value, array); Logger.Verbose($"{value}, {string.Join(" / ", array)}"); } else { Logger.Error($"{value} is not a valid hash property!"); } } } public static void DoAnimationLocal(EnemyAgent agent, EnemyAnimType type, float crossfadeTime, bool pauseAI) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) if (!_initialized) { Logger.Error("EnemyAnimUtil.DoAnimation was called too fast before it got cached!"); } else { if (type == EnemyAnimType.None) { return; } if (!_animHashsLookup.TryGetValue(type, out int[] value)) { Logger.Error($"Cannot find AnimationHash with: {type}"); return; } int num = ((value.Length > 1) ? Rand.IndexOf(value) : 0); agent.Locomotion.m_animator.applyRootMotion = true; agent.Locomotion.m_animator.CrossFadeInFixedTime(value[num], crossfadeTime); if (pauseAI) { ((AgentAI)agent.AI).m_navMeshAgent.velocity = Vector3.zero; if (((AgentAI)agent.AI).m_navMeshAgent.isOnNavMesh) { ((AgentAI)agent.AI).m_navMeshAgent.isStopped = true; } } } } public static void DoAnimation(EnemyAgent agent, EnemyAnimType type, float crossfadeTime, bool pauseAI) { if (!_initialized) { Logger.Error("EnemyAnimUtil.DoAnimation was called too fast before it got cached!"); } else if (type != 0) { if (!_animHashsLookup.TryGetValue(type, out int[] value)) { Logger.Error($"Cannot find AnimationHash with: {type}"); return; } int num = ((value.Length > 1) ? Rand.IndexOf(value) : 0); NetworkManager.EnemyAnim.Send(new EnemyAnimEvent.Packet { enemyID = ((Agent)agent).GlobalID, crossfadeTime = crossfadeTime, pauseAI = pauseAI, animHash = value[num] }); } } } public enum EnemyAnimType : byte { None, MoveOnGround, Forward, Right, ClimbLadder, GiveBirth, HitLights_Fwd, HitLights_Bwd, HitLights_Rt, HitLights_Lt, HitHeavys_Fwd, HitHeavys_Bwd, HitHeavys_Rt, HitHeavys_Lt, Screams, ScreamTurns, HibernationIn, Heartbeats, HibernationWakeups, HibernationWakeupTurns, AbilityFires, AbilityUse, AbilityUseOut, MeleeWalkSequences, MeleeSequences, Melee180Sequences, JumpStart, JumpLand } public static class EnemyProperty where T : class, new() { private static readonly Dictionary _properties; public static IEnumerable Properties => _properties.Values; static EnemyProperty() { _properties = new Dictionary(); EnemyEvents.Despawn += EnemyDespawn; LevelEvents.LevelCleanup += OnLevelCleanup; } private static void EnemyDespawn(EnemyAgent agent) { _properties.Remove(((Agent)agent).GlobalID); } private static void OnLevelCleanup() { _properties.Clear(); } public static T RegisterOrGet(EnemyAgent agent) { T val = RegisterEnemy(agent); if (val != null) { return val; } return Get(agent); } public static T RegisterEnemy(EnemyAgent agent) { ushort globalID = ((Agent)agent).GlobalID; if (_properties.ContainsKey(globalID)) { return null; } T val = new T(); _properties.Add(globalID, val); return val; } public static T Get(EnemyAgent agent) { return Get(((Agent)agent).GlobalID); } public static T Get(ushort id) { if (_properties.ContainsKey(id)) { return _properties[id]; } return null; } public static bool TryGet(EnemyAgent agent, out T property) { return TryGet(((Agent)agent).GlobalID, out property); } public static bool TryGet(ushort id, out T property) { return _properties.TryGetValue(id, out property); } } [Obsolete("Will be moved to ExplosionManager")] public static class ExplosionUtil { public static void MakeExplosion(Vector3 position, float damage, float enemyMulti, float minRange, float maxRange, float enemyMinRange, float enemyMaxRange) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) ExplosionPosData data = default(ExplosionPosData); data.position = position; data.data = new ExplosionData { damage = damage, enemyMulti = enemyMulti, minRange = minRange, maxRange = maxRange, enemyMinRange = enemyMinRange, enemyMaxRange = enemyMaxRange, lightColor = ExplosionManager.FlashColor }; ExplosionManager.DoExplosion(data); } } public static class PlayerData { public static float MaxHealth { get; internal set; } = 25f; public static float MaxInfection { get; internal set; } = 1f; } public static class Rand { public const int InclusiveDoublePrecision = 10000; public const double InclusiveDoubleConversion = 0.0001; private static readonly Random _rand = new Random(); public static Random CreateInstance() { return new Random(_rand.Next()); } public static T ItemOf(T[] array) { return array[IndexOf(array)]; } public static int IndexOf(Array array) { if (array == null) { throw new ArgumentNullException("array"); } if (array.Length == 0) { throw new ArgumentException("Array Length was zero!", "array"); } return _rand.Next(0, array.Length); } public static int Index(int length) { return _rand.Next(0, length); } public static int Range(int min, int max) { return _rand.Next(min, max); } public static float Range(float min, float max) { return NextFloat() * (max - min) + min; } public static int RangeInclusive(int min, int max) { return _rand.Next(min, max + 1); } public static float RangeInclusive(float min, float max) { return NextFloatInclusive() * (max - min) + min; } public static float NextFloatInclusive() { return Math.Clamp((float)NextDoubleInclusive(), 0f, 1f); } public static double NextDoubleInclusive() { return Math.Clamp((double)_rand.Next(0, 10001) * 0.0001, 0.0, 1.0); } public static float NextFloat() { return (float)_rand.NextDouble(); } public static bool CanDoBy(float chance01) { return NextFloat() <= chance01; } public static int NextInt() { return _rand.Next(); } } public static class RegexUtil { private static readonly Regex _vectorRegex = new Regex("-?[0-9.]+"); public static bool TryParseVectorString(string input, out float[] vectorArray) { try { MatchCollection matchCollection = _vectorRegex.Matches(input); int count = matchCollection.Count; if (count < 1) { throw new Exception(); } vectorArray = new float[count]; for (int i = 0; i < count; i++) { Match match = matchCollection[i]; vectorArray[i] = float.Parse(match.Value, CultureInfo.InvariantCulture); } return true; } catch { vectorArray = null; return false; } } } } namespace EEC.Utils.Unity { [CallConstructorOnLoad] public static class InLevelCoroutine { [InjectToIl2Cpp] private sealed class InLevelCoroutineHandler : MonoBehaviour { } private static InLevelCoroutineHandler _handler; static InLevelCoroutine() { AssetEvents.AllAssetLoaded += AssetEvents_AllAssetLoaded; LevelEvents.LevelCleanup += LevelEvents_LevelCleanup; SNetEvents.PrepareRecall += SNetEvents_PrepareRecall; } private static void AssetEvents_AllAssetLoaded() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if ((Object)(object)_handler == (Object)null) { GameObject val = new GameObject(); Object.DontDestroyOnLoad((Object)val); _handler = val.AddComponent(); } } private static void SNetEvents_PrepareRecall(eBufferType _) { StopAll(); } private static void LevelEvents_LevelCleanup() { StopAll(); } public static Coroutine Start(IEnumerator coroutine) { if ((Object)(object)_handler != (Object)null && GameStateManager.IsInExpedition) { return ((MonoBehaviour)_handler).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(coroutine)); } return null; } public static void Stop(Coroutine coroutine) { if ((Object)(object)_handler != (Object)null && GameStateManager.IsInExpedition) { ((MonoBehaviour)_handler).StopCoroutine(coroutine); } } public static void StopAll() { if ((Object)(object)_handler != (Object)null) { ((MonoBehaviour)_handler).StopAllCoroutines(); } } } public struct LazyTimer { private float _lastTickTime; private float _durationInv; public float PassedTime { get; private set; } public float Duration { get; private set; } public bool Done => Progress >= 1f; public float Progress => Mathf.Clamp01(ProgressUnclamped); public float ProgressUnclamped { get { if (Duration != 0f) { return PassedTime * _durationInv; } return 1f; } } public LazyTimer(float duration) { PassedTime = 0f; Duration = duration; _durationInv = 1f / duration; _lastTickTime = GetTime(); } public void Reset(float newDuration = -1f) { PassedTime = 0f; if (newDuration >= 0f) { Duration = newDuration; _durationInv = 1f / newDuration; } _lastTickTime = GetTime(); } public void Tick() { float time = GetTime(); float num = time - _lastTickTime; _lastTickTime = time; PassedTime += num; } public bool TickAndCheckDone() { Tick(); return Done; } private static float GetTime() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)GameStateManager.CurrentStateName == 10) { return Clock.ExpeditionProgressionTime; } return Clock.Time; } } public struct Timer { private float _durationInv; public float PassedTime { get; private set; } public float Duration { get; private set; } public bool Done => Progress >= 1f; public float Progress => Mathf.Clamp01(ProgressUnclamped); public float ProgressUnclamped { get { if (Duration != 0f) { return PassedTime * _durationInv; } return 1f; } } public Timer(float duration) { PassedTime = 0f; Duration = duration; _durationInv = 1f / duration; } public void Reset(float newDuration = -1f) { PassedTime = 0f; if (newDuration >= 0f) { Duration = newDuration; _durationInv = 1f / newDuration; } } public void Tick() { PassedTime += Time.deltaTime; } public void Tick(float deltaTime) { PassedTime += deltaTime; } public bool TickAndCheckDone() { Tick(); return Done; } public bool TickAndCheckDone(float deltaTime) { Tick(deltaTime); return Done; } } public struct DoubleTimer { private double _durationInv; public double PassedTime { get; private set; } public double Duration { get; private set; } public bool Done => Progress >= 1.0; public double Progress => Math.Clamp(0.0, 1.0, ProgressUnclamped); public double ProgressUnclamped { get { if (Duration != 0.0) { return PassedTime * _durationInv; } return 1.0; } } public DoubleTimer(double duration) { PassedTime = 0.0; Duration = duration; _durationInv = 1.0 / duration; } public void Reset(double newDuration = -1.0) { PassedTime = 0.0; if (newDuration >= 0.0) { Duration = newDuration; _durationInv = 1.0 / newDuration; } } public void Tick() { PassedTime += Time.deltaTime; } public bool TickAndCheckDone() { Tick(); return Done; } } public static class WaitFor { public static readonly WaitForEndOfFrame EndOfFrame = new WaitForEndOfFrame(); public static readonly WaitForFixedUpdate FixedUpdate = new WaitForFixedUpdate(); public static readonly WaitForSecondsCollection Seconds = new WaitForSecondsCollection(); public static readonly WaitForSecondsRealtimeCollection SecondsRealtime = new WaitForSecondsRealtimeCollection(); } public sealed class WaitForSecondsCollection : WaitForCollection { protected override WaitForSeconds CreateInstance(float time) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new WaitForSeconds(time); } } public sealed class WaitForSecondsRealtimeCollection : WaitForCollection { protected override WaitForSecondsRealtime CreateInstance(float time) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new WaitForSecondsRealtime(time); } } public abstract class WaitForCollection { private readonly Dictionary _lookup = new Dictionary(100); private T _temp; public T this[float time] { get { int key = ((!(time <= 0f)) ? Mathf.RoundToInt(time * 1000f) : 0); if (_lookup.TryGetValue(key, out _temp)) { return _temp; } _temp = CreateInstance(time); _lookup[key] = _temp; return _temp; } } protected abstract T CreateInstance(float time); } } namespace EEC.Utils.Json { public static class JSON { private static readonly JsonSerializerOptions _setting; static JSON() { _setting = new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip, IncludeFields = false, PropertyNameCaseInsensitive = true, WriteIndented = true, IgnoreReadOnlyProperties = true }; _setting.Converters.Add(new ColorConverter()); _setting.Converters.Add(new LocalizedTextConverter()); _setting.Converters.Add(new JsonStringEnumConverter()); _setting.Converters.Add(new Vector2Converter()); _setting.Converters.Add(new Vector3Converter()); if (MTFOPartialDataUtil.IsLoaded && MTFOPartialDataUtil.Initialized) { _setting.Converters.Add(MTFOPartialDataUtil.PersistentIDConverter); Logger.Log("PartialData Support Found!"); } if (InjectLibUtil.IsLoaded) { _setting.Converters.Add(InjectLibUtil.InjectLibConnector); Logger.Log("InjectLib found!"); } } public static T Deserialize(string json) { return JsonSerializer.Deserialize(json, _setting); } public static object Deserialize(Type type, string json) { return JsonSerializer.Deserialize(json, type, _setting); } public static string Serialize(object value, Type type) { return JsonSerializer.Serialize(value, type, _setting); } } } namespace EEC.Utils.Json.Elements { [JsonConverter(typeof(AgentModeTargetConverter))] public struct AgentModeTarget { public static readonly AgentModeTarget All = new AgentModeTarget(AgentModeType.Off | AgentModeType.Hibernate | AgentModeType.Agressive | AgentModeType.Scout | AgentModeType.Patrolling); public static readonly AgentModeTarget Scout = new AgentModeTarget(AgentModeType.Scout); public static readonly AgentModeTarget Hibernate = new AgentModeTarget(AgentModeType.Hibernate); public static readonly AgentModeTarget Agressive = new AgentModeTarget(AgentModeType.Agressive); public static readonly AgentModeTarget None = new AgentModeTarget(AgentModeType.None); public AgentModeType Mode; public AgentModeTarget(AgentModeType modes) { Mode = modes; } public bool IsMatch(EnemyAgent agent) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected I4, but got Unknown if ((Object)(object)agent == (Object)null) { return false; } AgentMode mode = ((AgentAI)agent.AI).Mode; return (int)mode switch { 0 => Mode.HasFlag(AgentModeType.Off), 4 => Mode.HasFlag(AgentModeType.Hibernate), 1 => Mode.HasFlag(AgentModeType.Agressive), 3 => Mode.HasFlag(AgentModeType.Scout), 2 => Mode.HasFlag(AgentModeType.Patrolling), _ => false, }; } } [Flags] public enum AgentModeType { None = 0, Off = 1, Hibernate = 2, Agressive = 4, Scout = 8, Patrolling = 0x10 } public sealed class AgentModeTargetConverter : JsonConverter { private static readonly char[] _separators = new char[2] { ',', '|' }; public override AgentModeTarget Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { switch (reader.TokenType) { case JsonTokenType.String: { string @string = reader.GetString(); string[] array = @string.Split(_separators, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { throw new JsonException("There are no entries in " + @string + "! Are you sure it's in right format?"); } AgentModeType agentModeType = AgentModeType.None; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { switch (array2[i].ToLowerInvariant().Trim()) { case "off": case "dead": agentModeType |= AgentModeType.Off; break; case "agressive": case "combat": agentModeType |= AgentModeType.Agressive; break; case "hibernate": case "hibernating": case "hibernation": case "sleeping": agentModeType |= AgentModeType.Hibernate; break; case "scout": case "scoutpatrolling": agentModeType |= AgentModeType.Scout; break; case "patrolling": agentModeType |= AgentModeType.Patrolling; break; } } return new AgentModeTarget(agentModeType); } case JsonTokenType.Number: Logger.Warning("Found flag number value in AgentModeTarget! : consider changing it to string."); return new AgentModeTarget((AgentModeType)reader.GetInt32()); default: throw new JsonException($"Token type: {reader.TokenType} in AgentModeTarget is not supported!"); } } public override void Write(Utf8JsonWriter writer, AgentModeTarget value, JsonSerializerOptions options) { writer.WriteNumberValue((int)value.Mode); } } [JsonConverter(typeof(BoolBaseConverter))] public struct BoolBase { public static readonly BoolBase False = new BoolBase(BoolMode.False); public static readonly BoolBase True = new BoolBase(BoolMode.True); public static readonly BoolBase Unchanged = new BoolBase(BoolMode.Unchanged); public BoolMode Mode; public BoolBase(bool mode) { Mode = (mode ? BoolMode.True : BoolMode.False); } public BoolBase(BoolMode mode) { Mode = mode; } public bool GetValue(bool originalValue) { switch (Mode) { case BoolMode.Unchanged: return originalValue; case BoolMode.True: return true; case BoolMode.False: return false; default: Logger.Error($"BoolBase.GetValue; Got Unknown Mode: {Mode}!\n{Environment.StackTrace}"); return originalValue; } } } public enum BoolMode { False, True, Unchanged } public sealed class BoolBaseConverter : JsonConverter { public override bool HandleNull => false; public override bool CanConvert(Type objectType) { return objectType == typeof(BoolBase); } public override BoolBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { switch (reader.TokenType) { case JsonTokenType.String: { string text = reader.GetString().Trim(); if (text.EqualsAnyIgnoreCase("Unchanged", "Ignore", "Keep", "Original", "KeepOriginal")) { return BoolBase.Unchanged; } if (bool.TryParse(text, out var result)) { return new BoolBase(result); } throw new JsonException("Cannot parse BoolBase string: " + text + "! Are you sure it's in right format?"); } case JsonTokenType.True: return BoolBase.True; case JsonTokenType.False: return BoolBase.False; default: throw new JsonException($"BoolBaseJson type: {reader.TokenType} is not implemented!"); } } public override void Write(Utf8JsonWriter writer, BoolBase value, JsonSerializerOptions options) { switch (value.Mode) { case BoolMode.True: writer.WriteBooleanValue(value: true); break; case BoolMode.False: writer.WriteBooleanValue(value: false); break; case BoolMode.Unchanged: writer.WriteStringValue("Unchanged"); break; } writer.WriteCommentValue("BoolBase"); } } public sealed class CurveWrapper : Collection { public const int KEYFRAME_FRAMECOUNT = 20; public const float KEYFRAME_PROGRESS_INV = 0.05f; public static readonly CurveWrapper Empty = new CurveWrapper(); private static readonly List _keys = new List(); public bool HasSetting => base.Count >= 2; public bool TryBuildCurve(out AnimationCurve curve) { //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected O, but got Unknown //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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) if (base.Count < 2) { curve = null; return false; } CurveKeyFrame[] array = this.OrderBy((CurveKeyFrame x) => x.Time).ToArray(); _keys.Clear(); for (int i = 0; i < base.Count - 1; i++) { CurveKeyFrame curveKeyFrame = array[i]; CurveKeyFrame curveKeyFrame2 = array[i + 1]; if (curveKeyFrame.Time > 1f || curveKeyFrame.Time < 0f) { Logger.Error($"CurveWrapper Time '{curveKeyFrame.Time}' was invalid!, must be range of 0.0 ~ 1.0"); curve = null; return false; } float num = curveKeyFrame2.Time - curveKeyFrame.Time; float num2 = curveKeyFrame2.Value - curveKeyFrame.Value; float num3 = num2 / num; for (int j = 0; j < 20; j++) { float num4 = 0.05f * (float)j; float time = curveKeyFrame.Time + num * num4; float value = curveKeyFrame.Value + num2 * curveKeyFrame.OutEaseType.Evaluate(num4); List keys = _keys; Keyframe item = default(Keyframe); ((Keyframe)(ref item)).time = time; ((Keyframe)(ref item)).value = value; ((Keyframe)(ref item)).inTangent = num3; ((Keyframe)(ref item)).outTangent = num3; keys.Add(item); } } curve = new AnimationCurve(_keys.ToArray()); return true; } } public struct CurveKeyFrame { public float Time { get; set; } public float Value { get; set; } public eEasingType OutEaseType { get; set; } } [JsonConverter(typeof(EventWrapperConverter))] public sealed class EventWrapper : IDisposable { private string _json; private WardenObjectiveEventData _cached; public EventWrapper(string json) { _json = json; } public void Cache() { _cached = InjectLibJSON.Deserialize(_json, Array.Empty()); _json = string.Empty; } public WardenObjectiveEventData ToEvent() { if (_cached == null) { Cache(); } return _cached; } public void Dispose() { _json = null; _cached = null; } } internal sealed class EventWrapperConverter : JsonConverter { public override bool HandleNull => false; public override EventWrapper Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.StartObject) { using (JsonDocument jsonDocument = JsonDocument.ParseValue(ref reader)) { return new EventWrapper(jsonDocument.RootElement.ToString()); } } throw new JsonException($"{reader.TokenType} is not supported for EventWrapperValue!"); } public override void Write(Utf8JsonWriter writer, EventWrapper value, JsonSerializerOptions options) { } } [JsonConverter(typeof(ExitConditionTargetConverter))] public struct ExitConditionTarget { public static readonly ExitConditionTarget All = new ExitConditionTarget(ExitConditionType.Mode | ExitConditionType.Dead | ExitConditionType.Attack | ExitConditionType.State | ExitConditionType.Distance); public static readonly ExitConditionTarget None = new ExitConditionTarget(ExitConditionType.None); public ExitConditionType Mode; public ExitConditionTarget(ExitConditionType modes) { Mode = modes; } public bool HasFlag(ExitConditionType type) { return Mode.HasFlag(type); } } [Flags] public enum ExitConditionType { None = 0, Mode = 1, Dead = 2, Attack = 4, State = 8, Distance = 0x10, EABAllowed = 0x20 } public sealed class ExitConditionTargetConverter : JsonConverter { private static readonly char[] _separators = new char[2] { ',', '|' }; public override ExitConditionTarget Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { switch (reader.TokenType) { case JsonTokenType.False: return ExitConditionTarget.None; case JsonTokenType.True: return ExitConditionTarget.All; case JsonTokenType.String: { string @string = reader.GetString(); string[] array = @string.Split(_separators, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { throw new JsonException("There are no entries in " + @string + "! Are you sure it's in right format?"); } ExitConditionType exitConditionType = ExitConditionType.None; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { switch (array2[i].ToLowerInvariant().Trim()) { case "mode": case "allowedmode": exitConditionType |= ExitConditionType.Mode; break; case "dead": case "keepondead": exitConditionType |= ExitConditionType.Dead; break; case "allowwhileattack": case "attack": exitConditionType |= ExitConditionType.Attack; break; case "state": exitConditionType |= ExitConditionType.State; break; case "distance": exitConditionType |= ExitConditionType.Distance; break; case "eaballowed": case "requireeab": case "requireeaballowed": exitConditionType |= ExitConditionType.EABAllowed; break; } } return new ExitConditionTarget(exitConditionType); } case JsonTokenType.Number: Logger.Warning("Found flag number value in ExitConditionTarget! : consider changing it to string."); return new ExitConditionTarget((ExitConditionType)reader.GetInt32()); default: throw new JsonException($"Token type: {reader.TokenType} in ExitConditionTarget is not supported!"); } } public override void Write(Utf8JsonWriter writer, ExitConditionTarget value, JsonSerializerOptions options) { writer.WriteNumberValue((int)value.Mode); } } [JsonConverter(typeof(ValueBaseConverter))] public struct ValueBase { public static readonly ValueBase Unchanged = new ValueBase(1f, ValueMode.Rel, fromDefault: true); public static readonly ValueBase Zero = new ValueBase(0f, ValueMode.Abs, fromDefault: false); public float Value; public ValueMode Mode; public bool FromDefault; public ValueBase(float value = 1f, ValueMode mode = ValueMode.Rel, bool fromDefault = true) { Value = value; Mode = mode; FromDefault = fromDefault; } public float GetAbsValue(float maxValue, float currentValue) { if (Mode == ValueMode.Rel) { if (FromDefault) { return currentValue * Value; } return maxValue * Value; } return Value; } public float GetAbsValue(float baseValue) { if (Mode == ValueMode.Rel) { return baseValue * Value; } return Value; } public int GetAbsValue(int maxValue, int currentValue) { return (int)Math.Round(GetAbsValue((float)maxValue, (float)currentValue)); } public int GetAbsValue(int baseValue) { return (int)Math.Round(GetAbsValue((float)baseValue)); } public override string ToString() { return $"[Mode: {Mode}, Value: {Value}]"; } } public enum ValueMode { Rel, Abs } public sealed class ValueBaseConverter : JsonConverter { public override bool HandleNull => false; public override bool CanConvert(Type objectType) { return objectType == typeof(ValueBase); } public override ValueBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { switch (reader.TokenType) { case JsonTokenType.Number: return new ValueBase(reader.GetSingle(), ValueMode.Abs); case JsonTokenType.StartObject: { ValueBase result3 = default(ValueBase); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return result3; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string? @string = reader.GetString(); reader.Read(); switch (@string.ToLowerInvariant()) { case "value": result3.Value = reader.GetSingle(); break; case "mode": { if (Enum.TryParse(reader.GetString(), out var result4)) { result3.Mode = result4; } break; } case "fromdefault": result3.FromDefault = reader.GetBoolean(); break; } } throw new JsonException("Expected EndObject token"); } case JsonTokenType.String: { string text = reader.GetString().Trim(); bool fromDefault = false; if (text.EndsWith("of default", StringComparison.OrdinalIgnoreCase)) { fromDefault = true; string text2 = text; text = text2.Substring(0, text2.Length - 10).TrimEnd(); } if (text.InvariantEndsWith("%")) { string text2 = text; if (float.TryParse(text2.Substring(0, text2.Length - 1).TrimEnd(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var result)) { return new ValueBase(result / 100f, ValueMode.Rel, fromDefault); } } else { if (text.EqualsAnyIgnoreCase("Unchanged", "Ignore", "Keep", "Original", "KeepOriginal")) { return new ValueBase(1f, ValueMode.Rel, fromDefault: false); } if (float.TryParse(text, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var result2)) { return new ValueBase(result2, ValueMode.Abs); } } throw new JsonException("Cannot parse ValueBase string: " + text + "! Are you sure it's in right format?"); } default: throw new JsonException($"ValueBaseJson type: {reader.TokenType} is not implemented!"); } } public override void Write(Utf8JsonWriter writer, ValueBase value, JsonSerializerOptions options) { switch (value.Mode) { case ValueMode.Rel: { if (Mathf.Approximately(value.Value, 1f)) { writer.WriteStringValue("Unchanged"); break; } string format = (value.FromDefault ? "{0}% of default" : "{0}%"); writer.WriteStringValue(string.Format(format, value.Value * 100f)); break; } case ValueMode.Abs: writer.WriteStringValue(value.Value.ToString()); break; } writer.WriteCommentValue("ValueBase"); } } } namespace EEC.Utils.Json.Converters { public sealed class ColorConverter : JsonConverter { public override bool HandleNull => false; public override bool CanConvert(Type objectType) { return objectType == typeof(Color); } public override Color Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) Color color = default(Color); float result = 1f; switch (reader.TokenType) { case JsonTokenType.StartObject: while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return color * result; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string? @string = reader.GetString(); reader.Read(); switch (@string.ToLowerInvariant()) { case "r": color.r = reader.GetSingle(); break; case "g": color.g = reader.GetSingle(); break; case "b": color.b = reader.GetSingle(); break; case "a": color.a = reader.GetSingle(); break; case "multiplier": result = reader.GetSingle(); break; } } throw new JsonException("Expected EndObject token"); case JsonTokenType.String: { string text = reader.GetString().Trim(); string[] array = text.Split("*"); string text2; switch (array.Length) { case 1: result = 1f; text2 = array[0].Trim(); break; case 2: if (!float.TryParse(array[1].Trim(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result)) { throw new JsonException("Color multiplier is not valid number! (*): " + text); } text2 = array[0].Trim(); break; default: throw new JsonException("Color format has more than two Mutiplier (*): " + text); } if (ColorUtility.TryParseHtmlString(text2, ref color)) { return color * result; } if (TryParseColor(text, out color)) { return color * result; } throw new JsonException("Color format is not right: " + text); } default: throw new JsonException($"ColorJson type: {reader.TokenType} is not implemented!"); } } private static bool TryParseColor(string input, out Color color) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!RegexUtil.TryParseVectorString(input, out float[] vectorArray)) { color = Color.white; return false; } if (vectorArray.Length < 3) { color = Color.white; return false; } float num = 1f; if (vectorArray.Length > 3) { num = vectorArray[3]; } color = new Color(vectorArray[0], vectorArray[1], vectorArray[2], num); return true; } public override void Write(Utf8JsonWriter writer, Color value, JsonSerializerOptions options) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) writer.WriteStringValue("#" + ColorUtility.ToHtmlStringRGBA(value)); } } public sealed class LocalizedTextConverter : JsonConverter { public override bool HandleNull => false; public override LocalizedText Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown switch (reader.TokenType) { case JsonTokenType.String: { string @string = reader.GetString(); if (!MTFOPartialDataUtil.TryGetId(@string, out var id)) { return new LocalizedText { Id = 0u, UntranslatedText = @string }; } return new LocalizedText { Id = id, UntranslatedText = null }; } case JsonTokenType.Number: return new LocalizedText { Id = reader.GetUInt32(), UntranslatedText = null }; default: throw new JsonException($"LocalizedTextJson type: {reader.TokenType} is not implemented!"); } } public override void Write(Utf8JsonWriter writer, LocalizedText value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, options); } } public sealed class Vector2Converter : JsonConverter { public override Vector2 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) Vector2 vector = default(Vector2); switch (reader.TokenType) { case JsonTokenType.StartObject: while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return vector; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string? @string = reader.GetString(); reader.Read(); string text2 = @string.ToLowerInvariant(); if (!(text2 == "x")) { if (text2 == "y") { vector.y = reader.GetSingle(); } } else { vector.x = reader.GetSingle(); } } throw new JsonException("Expected EndObject token"); case JsonTokenType.String: { string text = reader.GetString().Trim(); if (TryParseVector2(text, out vector)) { return vector; } throw new JsonException("Vector2 format is not right: " + text); } default: throw new JsonException($"Vector2Json type: {reader.TokenType} is not implemented!"); } } private static bool TryParseVector2(string input, out Vector2 vector) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //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) if (!RegexUtil.TryParseVectorString(input, out float[] vectorArray)) { vector = Vector2.zero; return false; } if (vectorArray.Length < 2) { vector = Vector2.zero; return false; } vector = new Vector2(vectorArray[0], vectorArray[1]); return true; } public override void Write(Utf8JsonWriter writer, Vector2 value, JsonSerializerOptions options) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) writer.WriteStringValue($"({value.x} {value.y})"); } } public sealed class Vector3Converter : JsonConverter { public override bool HandleNull => false; public override Vector3 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { //IL_0002: 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_00d4: Unknown result type (might be due to invalid IL or missing references) Vector3 vector = default(Vector3); switch (reader.TokenType) { case JsonTokenType.StartObject: while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return vector; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string? @string = reader.GetString(); reader.Read(); switch (@string.ToLowerInvariant()) { case "x": vector.x = reader.GetSingle(); break; case "y": vector.y = reader.GetSingle(); break; case "z": vector.z = reader.GetSingle(); break; } } throw new JsonException("Expected EndObject token"); case JsonTokenType.String: { string text = reader.GetString().Trim(); if (TryParseVector3(text, out vector)) { return vector; } throw new JsonException("Vector3 format is not right: " + text); } default: throw new JsonException($"Vector3Json type: {reader.TokenType} is not implemented!"); } } private static bool TryParseVector3(string input, out Vector3 vector) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //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) if (!RegexUtil.TryParseVectorString(input, out float[] vectorArray)) { vector = Vector3.zero; return false; } if (vectorArray.Length < 3) { vector = Vector3.zero; return false; } vector = new Vector3(vectorArray[0], vectorArray[1], vectorArray[2]); return true; } public override void Write(Utf8JsonWriter writer, Vector3 value, JsonSerializerOptions options) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) writer.WriteStringValue($"({value.x} {value.y} {value.z})"); } } } namespace EEC.Utils.Integrations { public static class InjectLibUtil { public const string PLUGIN_GUID = "GTFO.InjectLib"; public static JsonConverter InjectLibConnector { get; private set; } public static bool IsLoaded { get; private set; } static InjectLibUtil() { if (!((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("GTFO.InjectLib", out var value)) { return; } try { Assembly obj = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null; if ((object)obj == null) { throw new Exception("Assembly is Missing!"); } InjectLibConnector = (JsonConverter)Activator.CreateInstance(obj.GetTypes().First((Type t) => t.Name == "InjectLibConnector") ?? throw new Exception("Unable to Find InjectLibConnector Class")); IsLoaded = true; } catch (Exception value2) { Logger.Error($"Exception thrown while reading data from GTFO.AWO: {value2}"); } } } public static class MTFOPartialDataUtil { public delegate bool TryGetDelegate(string guid, out uint id); public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks"; private static readonly TryGetDelegate _tryGetIDDelegate; public static JsonConverter PersistentIDConverter { get; private set; } public static JsonConverter LocalizedTextConverter { get; private set; } public static bool IsLoaded { get; private set; } public static bool Initialized { get; private set; } public static string PartialDataPath { get; private set; } public static string ConfigPath { get; private set; } static MTFOPartialDataUtil() { PersistentIDConverter = null; LocalizedTextConverter = null; IsLoaded = false; Initialized = false; PartialDataPath = string.Empty; ConfigPath = string.Empty; if (!((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("MTFO.Extension.PartialBlocks", out var value)) { return; } try { Assembly obj = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null; if ((object)obj == null) { throw new Exception("Assembly is Missing!"); } Type[] types = obj.GetTypes(); Type type = types.First((Type t) => t.Name == "PersistentIDConverter"); if ((object)type == null) { throw new Exception("Unable to Find PersistentIDConverter Class"); } Type obj2 = types.First((Type t) => t.Name == "PartialDataManager") ?? throw new Exception("Unable to Find PartialDataManager Class"); PropertyInfo property = obj2.GetProperty("Initialized", BindingFlags.Static | BindingFlags.Public); PropertyInfo property2 = obj2.GetProperty("PartialDataPath", BindingFlags.Static | BindingFlags.Public); PropertyInfo? property3 = obj2.GetProperty("ConfigPath", BindingFlags.Static | BindingFlags.Public); if ((object)property == null) { throw new Exception("Unable to Find Property: Initialized"); } if ((object)property2 == null) { throw new Exception("Unable to Find Property: PartialDataPath"); } if ((object)property3 == null) { throw new Exception("Unable to Find Field: ConfigPath"); } Initialized = (bool)property.GetValue(null); PartialDataPath = (string)property2.GetValue(null); ConfigPath = (string)property3.GetValue(null); _tryGetIDDelegate = (TryGetDelegate)(types.First((Type t) => t.Name == "PersistentIDManager") ?? throw new Exception("Unable to Find PersistentIDManager Class")).GetMethod("TryGetId", BindingFlags.Static | BindingFlags.Public).CreateDelegate(typeof(TryGetDelegate)); PersistentIDConverter = (JsonConverter)Activator.CreateInstance(type); IsLoaded = true; } catch (Exception value2) { Logger.Error($"Exception thrown while reading data from MTFO_Extension_PartialData:\n{value2}"); } } public static bool TryGetId(string guid, out uint id) { if (!IsLoaded) { id = 0u; return false; } if (!Initialized) { id = 0u; return false; } if (_tryGetIDDelegate == null) { id = 0u; return false; } return _tryGetIDDelegate(guid, out id); } } public static class MTFOUtil { public const string PLUGIN_GUID = "com.dak.MTFO"; public const BindingFlags PUBLIC_STATIC = BindingFlags.Static | BindingFlags.Public; public static readonly Version MTFO_FORBID; public static readonly Version MTFO_V5; public static string GameDataPath { get; private set; } public static string CustomPath { get; private set; } public static bool HasCustomContent { get; private set; } public static bool IsLoaded { get; private set; } public static bool HasHotReload { get; private set; } public static FieldInfo HotReloaderField { get; private set; } public static event Action HotReloaded; static MTFOUtil() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown MTFO_FORBID = new Version("4.2.0", false); MTFO_V5 = new Version("4.3.5", false); GameDataPath = string.Empty; CustomPath = string.Empty; HasCustomContent = false; IsLoaded = false; HasHotReload = false; HotReloaderField = null; if (!((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("com.dak.MTFO", out var value)) { return; } Version version = value.Metadata.Version; if (version >= MTFO_V5) { InitMTFO_V5(value); return; } if (version > MTFO_FORBID) { InitMTFO_V4(value); return; } throw new Exception("You are using unsupported version of MTFO!"); } private static void InitMTFO_V4(PluginInfo info) { try { Assembly obj = ((info == null) ? null : info.Instance?.GetType()?.Assembly) ?? null; if ((object)obj == null) { throw new Exception("Assembly is Missing!"); } Type obj2 = obj.GetTypes().First((Type t) => t.Name == "ConfigManager") ?? throw new Exception("Unable to Find ConfigManager Class"); FieldInfo field = obj2.GetField("GameDataPath", BindingFlags.Static | BindingFlags.Public); FieldInfo field2 = obj2.GetField("CustomPath", BindingFlags.Static | BindingFlags.Public); FieldInfo? field3 = obj2.GetField("HasCustomContent", BindingFlags.Static | BindingFlags.Public); if ((object)field == null) { throw new Exception("Unable to Find Field: GameDataPath"); } if ((object)field2 == null) { throw new Exception("Unable to Find Field: CustomPath"); } if ((object)field3 == null) { throw new Exception("Unable to Find Field: HasCustomContent"); } GameDataPath = (string)field.GetValue(null); CustomPath = (string)field2.GetValue(null); HasCustomContent = (bool)field3.GetValue(null); IsLoaded = true; } catch (Exception value) { Logger.Error($"Exception thrown while reading path from DataDumper (MTFO V{info.Metadata.Version}): \n{value}"); } } private static void InitMTFO_V5(PluginInfo info) { try { Assembly obj = ((info == null) ? null : info.Instance?.GetType()?.Assembly) ?? null; if ((object)obj == null) { throw new Exception("Assembly is Missing!"); } Type[] types = obj.GetTypes(); Type obj2 = types.First((Type t) => t.Name == "ConfigManager") ?? throw new Exception("Unable to Find ConfigManager Class"); FieldInfo field = obj2.GetField("GameDataPath", BindingFlags.Static | BindingFlags.Public); FieldInfo field2 = obj2.GetField("CustomPath", BindingFlags.Static | BindingFlags.Public); FieldInfo field3 = obj2.GetField("HasCustomContent", BindingFlags.Static | BindingFlags.Public); PropertyInfo? property = obj2.GetProperty("IsHotReloadEnabled", BindingFlags.Static | BindingFlags.Public); if ((object)field == null) { throw new Exception("Unable to Find Field: GameDataPath"); } if ((object)field2 == null) { throw new Exception("Unable to Find Field: CustomPath"); } if ((object)field3 == null) { throw new Exception("Unable to Find Field: HasCustomContent"); } if ((object)field3 == null) { throw new Exception("Unable to Find Field: HasCustomContent"); } if ((object)property == null) { throw new Exception("Unable to Find Property: IsHotReloadEnabled"); } GameDataPath = (string)field.GetValue(null); CustomPath = (string)field2.GetValue(null); HasCustomContent = (bool)field3.GetValue(null); HasHotReload = (bool)property.GetValue(null); if (HasHotReload) { HotReloaderField = (types.First((Type t) => t.Name == "HotReloader") ?? throw new Exception("Unable to Find HotReloader Class")).GetField("Current", BindingFlags.Static | BindingFlags.Public) ?? throw new Exception("Unable to Find Field: Current"); } IsLoaded = true; } catch (Exception value) { Logger.Error($"Exception thrown while reading metadata from MTFO (V{info.Metadata.Version}): \n{value}"); } } internal static void OnHotReloaded(int _) { MTFOUtil.HotReloaded?.Invoke(); } } } namespace EEC.Utils.Integrations.Inject { [HarmonyPatch(typeof(CM_PageRundown_New), "OnEnable")] internal static class Inject_CM_PageRundown_New { private static bool _isInjected; [HarmonyWrapSafe] internal static void Postfix() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (_isInjected) { return; } object obj = MTFOUtil.HotReloaderField?.GetValue(null) ?? null; if (obj != null) { FieldInfo field = obj.GetType().GetField("button", BindingFlags.Instance | BindingFlags.NonPublic); if ((object)field != null) { ((CM_Item)field.GetValue(obj)).OnBtnPressCallback += Action.op_Implicit((Action)MTFOUtil.OnHotReloaded); _isInjected = true; } } } } } namespace EEC.Patches { [CallConstructorOnLoad] public static class PatchManager { static PatchManager() { ConfigManager.EnemyPrefabBuilt += PrefabBuilt; } private static void PrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { if (ConfigManager.Global.UsingFlyerStuckCheck && enemyData.TryGetBehaviourBlock(out EnemyBehaviorDataBlock behaviour) && behaviour.IsFlyer) { ((Component)agent).gameObject.AddComponent().Agent.Value = agent; Logger.Debug($"Added Flyer Check to {((GameDataBlockBase)(object)enemyData).persistentID}"); } } } } namespace EEC.Patches.Inject { [HarmonyPatch(typeof(Dam_SyncedDamageBase))] internal static class Inject_Patch_HealerEnemies { [HarmonyPatch("TentacleAttackDamage")] [HarmonyPrefix] [HarmonyWrapSafe] internal static bool Pre_TentacleDamage(float dam, Dam_SyncedDamageBase __instance) { return DoHealer(dam, __instance); } [HarmonyPatch("MeleeDamage")] [HarmonyPrefix] [HarmonyWrapSafe] internal static bool Pre_PunchDamage(float dam, Dam_SyncedDamageBase __instance) { return DoHealer(dam, __instance); } [HarmonyPatch("ExplosionDamage")] [HarmonyPrefix] [HarmonyWrapSafe] internal static bool Pre_ExplosionDamage(float dam, Dam_SyncedDamageBase __instance) { return DoHealer(dam, __instance); } [HarmonyPatch("ShooterProjectileDamage")] [HarmonyPrefix] [HarmonyWrapSafe] internal static bool Pre_ShooterProjectileDamage(float dam, Dam_SyncedDamageBase __instance) { return DoHealer(dam, __instance); } private static bool DoHealer(float dam, Dam_SyncedDamageBase damBase) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 if (dam >= 0f) { return true; } DamageBaseOwnerType damageBaseOwner = damBase.DamageBaseOwner; if ((int)damageBaseOwner != 0 && (int)damageBaseOwner != 1) { return true; } damBase.AddHealth(Math.Abs(dam), (Agent)null); return false; } } } namespace EEC.Patches.Handlers { [InjectToIl2Cpp] internal sealed class FlyerStuckHandler : MonoBehaviour { public Il2CppReferenceField Agent; public float UpdateInterval = float.MaxValue; public int RetryCount = int.MaxValue; private EnemyAgent _agent; private Vector3 _firstPosition; private Vector2 _lastGoalXZ; private Timer _timer; private int _tryCount = -1; private bool _shouldCheck = true; private void Start() { if (!SNet.IsMaster) { ((Behaviour)this).enabled = false; return; } _agent = Il2CppReferenceField.op_Implicit(Agent); if ((Object)(object)_agent == (Object)null) { ((Behaviour)this).enabled = false; return; } if (!_agent.EnemyBehaviorData.IsFlyer) { ((Behaviour)this).enabled = false; return; } UpdateInterval = ConfigManager.Global.FlyerStuck_Interval; RetryCount = ConfigManager.Global.FlyerStuck_Retry; } private void FixedUpdate() { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (_shouldCheck) { if ((int)((AgentAI)_agent.AI).Mode != 1 || !_timer.TickAndCheckDone()) { return; } _timer.Reset(UpdateInterval); if (_tryCount == -1) { _firstPosition = _agent.Position; _tryCount = 0; } else if (Vector3.Distance(_firstPosition, _agent.Position) < 0.1f) { _tryCount++; if (_tryCount >= RetryCount) { Logger.Debug("Flyer was stuck in Place!"); ((Agent)_agent).m_replicator.Despawn(); } } else { _shouldCheck = false; } return; } Vector3 navmeshAgentGoal = _agent.AI.NavmeshAgentGoal; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(navmeshAgentGoal.x, navmeshAgentGoal.z); Vector2 val2 = val - _lastGoalXZ; if (((Vector2)(ref val2)).sqrMagnitude < 0.1f) { if (((MachineState)(object)((StateMachine)(object)_agent.AI.m_behaviour).CurrentState).ENUM_ID == 5) { _tryCount = -1; _shouldCheck = true; } } else { _tryCount = -1; _shouldCheck = false; } _lastGoalXZ = val; } private void OnDestroy() { Agent = null; } } [Flags] public enum ShitpostType { ForceOff = -1, Enable = 0, Dinnerbone = 1 } } namespace EEC.Patches.Handlers.Yes.Yes.Yes.Yes { [CallConstructorOnLoad] public static class Shitpost2022 { [CompilerGenerated] private sealed class d__2 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public NavMarker marker; public EnemyAgent agent; private WaitForSeconds 5__2; private bool 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_008c: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = WaitFor.Seconds[0.25f]; 5__3 = false; <>2__current = 5__2; <>1__state = 1; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } if (((Agent)agent).Alive) { if ((int)marker.m_currentState == 2) { Vector3 val = agent.Position - ((Component)CameraManager.GetCurrentCamera()).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!5__3 && sqrMagnitude <= 64f) { marker.m_titleSubObj.SetEnabled(true); 5__3 = true; } else if (5__3 && sqrMagnitude > 64f) { marker.m_titleSubObj.SetEnabled(false); 5__3 = false; } } else if (5__3) { marker.m_titleSubObj.SetEnabled(false); 5__3 = false; } <>2__current = 5__2; <>1__state = 2; return true; } 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(); } } static Shitpost2022() { if (Configuration.CanShitpostOf(ShitpostType.Dinnerbone)) { EnemyEvents.Spawned += EnemyEvents_Spawned; } } private static void EnemyEvents_Spawned(EnemyAgent agent) { //IL_00e0: 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) NavMarker marker = GuiManager.NavMarkerLayer.PlaceCustomMarker((NavMarkerOption)16, agent.ModelRef.m_markerTagAlign, "Dinnerbone", 0f, false); marker.SetVisualStates((NavMarkerOption)0, (NavMarkerOption)0, (NavMarkerOption)0, (NavMarkerOption)0); marker.m_titleSubObj.SetEnabled(false); marker.SetPinEnabled(false); ((MonoBehaviour)(object)agent.AI).StartCoroutine(UpdateMarker(agent, marker)); agent.AddOnDeadOnce(delegate { GuiManager.NavMarkerLayer.RemoveMarker(marker); }); Transform boneTransform = agent.Anim.GetBoneTransform((HumanBodyBones)0); if ((Object)(object)boneTransform != (Object)null) { BoneOffsetHandler boneOffsetHandler = ((Component)boneTransform).gameObject.AddComponent(); boneOffsetHandler.Animator = Il2CppReferenceField.op_Implicit(agent.Anim); boneOffsetHandler.RotationOffset = Il2CppValueField.op_Implicit(new Vector3(0f, 180f, 0f)); } else { agent.MainModelTransform.Rotate(Vector3.forward, 180f); } } [IteratorStateMachine(typeof(d__2))] private static IEnumerator UpdateMarker(EnemyAgent agent, NavMarker marker) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__2(0) { agent = agent, marker = marker }; } } } namespace EEC.Networking { public static class NetworkManager { [CompilerGenerated] private sealed class d__15 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemyAgent agent; private WaitForFixedUpdate 5__2; private float 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; 5__2 = WaitFor.FixedUpdate; 5__3 = ((Dam_SyncedDamageBase)agent.Damage).Health; } if (SNet.IsMaster) { float health = ((Dam_SyncedDamageBase)agent.Damage).Health; if (!Mathf.Approximately(5__3, health)) { EnemyHealthState.UpdateInfo(agent); 5__3 = health; } } <>2__current = 5__2; <>1__state = 1; return true; } 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 const ulong LOWEST_STEAMID64 = 76561197960265729uL; public static EnemyAgentModeReplicator EnemyAgentModeState { get; private set; } = new EnemyAgentModeReplicator(); public static EnemyHealthInfoReplicator EnemyHealthState { get; private set; } = new EnemyHealthInfoReplicator(); public static EnemyAnimEvent EnemyAnim { get; private set; } = new EnemyAnimEvent(); internal static void Initialize() { EnemyEvents.Spawned += EnemySpawned; EnemyEvents.Despawn += EnemyDespawn; EnemyAgentModeState.Initialize(); EnemyHealthState.Initialize(); EnemyAnim.Setup(); } private static void EnemySpawned(EnemyAgent agent) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) EnemyAgent agent2 = agent; if (agent2.TryGetSpawnData(out var spawnData)) { EnemyAgentModeReplicator.State state = default(EnemyAgentModeReplicator.State); state.mode = spawnData.mode; EnemyAgentModeReplicator.State startState = state; EnemyAgentModeState.Register(((Agent)agent2).GlobalID, startState, delegate(EnemyAgentModeReplicator.State newState) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ConfigManager.FireAgentModeChangedEvent(agent2, newState.mode); }); } EnemyHealthInfoReplicator.State state2 = default(EnemyHealthInfoReplicator.State); state2.maxHealth = ((Dam_SyncedDamageBase)agent2.Damage).HealthMax; state2.health = ((Dam_SyncedDamageBase)agent2.Damage).Health; EnemyHealthInfoReplicator.State startState2 = state2; EnemyHealthState.Register(((Agent)agent2).GlobalID, startState2, delegate(EnemyHealthInfoReplicator.State newState) { EnemyDamageEvents.OnHealthUpdated(agent2, newState.maxHealth, newState.health); }); ((MonoBehaviour)(object)agent2.AI).StartCoroutine(CheckHealth(agent2)); } [IteratorStateMachine(typeof(d__15))] private static IEnumerator CheckHealth(EnemyAgent agent) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__15(0) { agent = agent }; } private static void EnemyDespawn(EnemyAgent agent) { EnemyAgentModeState.Deregister(((Agent)agent).GlobalID); EnemyHealthState.Deregister(((Agent)agent).GlobalID); } } public delegate void SNetRecallEvent(eBufferType bufferType); public delegate void SNetPlayerEvent(SNet_Player player); public delegate void SNetPlayerEventWithReason(SNet_Player player, SNet_PlayerEventReason reason); public static class SNetEvents { public static event SNetPlayerEvent AgentSpawned; public static event SNetRecallEvent PrepareRecall; public static event SNetRecallEvent RecallComplete; internal static void OnAgentSpawned(SNet_Player player) { SNetEvents.AgentSpawned?.Invoke(player); } internal static void OnPrepareRecall(eBufferType bufferType) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) SNetEvents.PrepareRecall?.Invoke(bufferType); } internal static void OnRecallComplete(eBufferType bufferType) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) SNetEvents.RecallComplete?.Invoke(bufferType); } } internal struct ReplicatorPayload { public ushort key; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)] public byte[] stateBytes; public void Serialize(T stateData) where T : struct { int num = Marshal.SizeOf(stateData); if (num >= 30) { throw new ArgumentException("StateData Exceed size of 30 : Unable to Serialize", "T"); } byte[] destination = new byte[30]; IntPtr intPtr = Marshal.AllocHGlobal(num); Marshal.StructureToPtr(stateData, intPtr, fDeleteOld: false); Marshal.Copy(intPtr, destination, 0, num); Marshal.FreeHGlobal(intPtr); stateBytes = destination; } public T Deserialize() { int num = Marshal.SizeOf(typeof(T)); if (num > stateBytes.Length) { throw new ArgumentException("StateData Exceed size of 30 : Unable to Deserialize", "T"); } IntPtr intPtr = Marshal.AllocHGlobal(num); Marshal.Copy(stateBytes, 0, intPtr, num); T result = (T)Marshal.PtrToStructure(intPtr, typeof(T)); Marshal.FreeHGlobal(intPtr); return result; } } public sealed class StateContext where S : struct { public bool Registered; public Action OnStateChanged; public S State; } public abstract class StateReplicator where S : struct { private static readonly Dictionary> _lookup = new Dictionary>(500); private bool _isInitialized; public abstract bool ClearOnLevelCleanup { get; } public abstract string GUID { get; } public bool IsSetup => _isInitialized; public string SetStateName { get; private set; } = string.Empty; public string ChangeRequestName { get; private set; } = string.Empty; public void Initialize() { if (!_isInitialized) { SNetEvents.AgentSpawned += SNetEvents_AgentSpawned; if (ClearOnLevelCleanup) { LevelEvents.LevelCleanup += Clear; } SetStateName = "EECRp" + GUID + "S"; ChangeRequestName = "EECRp" + GUID + "R"; NetworkAPI.RegisterEvent(SetStateName, (Action)ReceiveSetState_FromMaster); NetworkAPI.RegisterEvent(ChangeRequestName, (Action)ReceiveSetState_FromClient); _isInitialized = true; } } private void SNetEvents_AgentSpawned(SNet_Player player) { if (!SNet.IsMaster) { return; } foreach (KeyValuePair> item in _lookup) { ReplicatorPayload replicatorPayload = default(ReplicatorPayload); replicatorPayload.key = item.Key; ReplicatorPayload replicatorPayload2 = replicatorPayload; replicatorPayload2.Serialize(item.Value.State); NetworkAPI.InvokeEvent(SetStateName, replicatorPayload2, player, (SNet_ChannelType)2); } } public void Register(ushort id, S startState, Action onChanged = null) { if (TryGetContext(id, out StateContext context)) { if (context.Registered) { return; } context.Registered = true; context.OnStateChanged = onChanged; } else { context = new StateContext { Registered = true, OnStateChanged = onChanged, State = startState }; _lookup[id] = context; } context.OnStateChanged?.Invoke(context.State); OnStateChange(id, context.State); } public void Deregister(ushort id) { if (TryGetContext(id, out StateContext context) && context.Registered) { _lookup.Remove(id); } } private void Clear() { _lookup.Clear(); } public void SetState(ushort id, S state) { if (TryGetContext(id, out StateContext context) && context.Registered) { ReplicatorPayload replicatorPayload = default(ReplicatorPayload); replicatorPayload.key = id; ReplicatorPayload replicatorPayload2 = replicatorPayload; replicatorPayload2.Serialize(state); if (SNet.IsMaster) { NetworkAPI.InvokeEvent(SetStateName, replicatorPayload2, (SNet_ChannelType)2); context.State = state; ReceiveSetState_FromMaster(SNet.Master.Lookup, replicatorPayload2); } else if (SNet.HasMaster) { NetworkAPI.InvokeEvent(ChangeRequestName, replicatorPayload2, SNet.Master, (SNet_ChannelType)2); context.State = state; } } } public bool TryGetState(ushort id, out S state) { if (!TryGetContext(id, out StateContext context) || !context.Registered) { Logger.Warning($"KEY: {id} has not registered; backing to Default"); state = default(S); return false; } state = context.State; return true; } private void ReceiveSetState_FromMaster(ulong sender, ReplicatorPayload statePacket) { ushort key = statePacket.key; S val = statePacket.Deserialize(); if (TryGetContext(key, out StateContext context)) { context.State = val; if (context.Registered) { context.OnStateChanged?.Invoke(val); OnStateChange(key, val); } } else { _lookup[key] = new StateContext { Registered = false, State = val }; } } private void ReceiveSetState_FromClient(ulong sender, ReplicatorPayload statePacket) { if (SNet.IsMaster) { SetState(statePacket.key, statePacket.Deserialize()); } } public bool TryGetContext(ushort id, out StateContext context) { return _lookup.TryGetValue(id, out context); } public virtual void OnStateChange(ushort id, S newState) { } } public abstract class SyncedEvent where T : struct { public delegate void ReceiveHandler(T packet); private bool _isSetup; public abstract string GUID { get; } public bool IsSetup => _isSetup; public string EventName { get; private set; } = string.Empty; public event ReceiveHandler OnReceive; public event ReceiveHandler OnReceiveLocal; public void Setup() { if (!_isSetup) { EventName = "EEC" + GUID; NetworkAPI.RegisterEvent(EventName, (Action)ReceiveClient_Callback); _isSetup = true; } } public void Send(T packetData, SNet_Player target = null) { if ((Object)(object)target != (Object)null) { NetworkAPI.InvokeEvent(EventName, packetData, target, (SNet_ChannelType)2); } else { NetworkAPI.InvokeEvent(EventName, packetData, (SNet_ChannelType)2); } ReceiveLocal_Callback(packetData); } private void ReceiveLocal_Callback(T packet) { ReceiveLocal(packet); this.OnReceiveLocal?.Invoke(packet); Receive(packet); this.OnReceive?.Invoke(packet); } private void ReceiveClient_Callback(ulong sender, T packet) { Receive(packet); this.OnReceive?.Invoke(packet); } protected virtual void ReceiveLocal(T packet) { } protected virtual void Receive(T packet) { } } internal struct SyncedPlayerEventPayload { public ulong lookup; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)] public byte[] packetBytes; public void Serialize(T packet) where T : struct { int num = Marshal.SizeOf(packet); if (num >= 30) { throw new ArgumentException("PacketData Exceed size of 30 : Unable to Serialize", "T"); } byte[] destination = new byte[30]; IntPtr intPtr = Marshal.AllocHGlobal(num); Marshal.StructureToPtr(packet, intPtr, fDeleteOld: false); Marshal.Copy(intPtr, destination, 0, num); Marshal.FreeHGlobal(intPtr); packetBytes = destination; } public T Deserialize() { int num = Marshal.SizeOf(typeof(T)); if (num > packetBytes.Length) { throw new ArgumentException("Packet Exceed size of 30 : Unable to Deserialize", "T"); } IntPtr intPtr = Marshal.AllocHGlobal(num); Marshal.Copy(packetBytes, 0, intPtr, num); T result = (T)Marshal.PtrToStructure(intPtr, typeof(T)); Marshal.FreeHGlobal(intPtr); return result; } public bool TryGetPlayer(out SNet_Player player) { if (lookup == 0L) { player = null; return false; } if (lookup < 76561197960265729L) { return SNet.Core.TryGetPlayerBot((int)lookup - 1, ref player); } return SNet.Core.TryGetPlayer(lookup, ref player, false); } } public abstract class SyncedPlayerEvent where T : struct { public delegate void ReceiveHandler(T packet, SNet_Player receivedPlayer); private bool _isSetup; public abstract string GUID { get; } public abstract bool SendToTargetOnly { get; } public abstract bool AllowBots { get; } public bool IsSetup => _isSetup; public string EventName { get; private set; } = string.Empty; public event ReceiveHandler OnReceive; public void Setup() { if (!_isSetup) { EventName = "EECp" + GUID; NetworkAPI.RegisterEvent(EventName, (Action)Received_Callback); _isSetup = true; } } public bool TryGetPlayerAgent(SNet_Player player, out PlayerAgent agent) { if (!player.HasPlayerAgent) { agent = null; return false; } agent = ((Il2CppObjectBase)player.m_playerAgent).TryCast(); return (Object)(object)agent != (Object)null; } public void SendToPlayers(T packetData, params PlayerAgent[] agents) { foreach (PlayerAgent val in agents) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.Owner == (Object)null)) { SendToPlayer(packetData, val.Owner); } } } public void SendToPlayers(T packetData, params SNet_Player[] players) { foreach (SNet_Player player in players) { SendToPlayer(packetData, player); } } public void SendToPlayer(T packetData, PlayerAgent agent) { if (!((Object)(object)agent == (Object)null) && !((Object)(object)agent.Owner == (Object)null)) { SendToPlayer(packetData, agent.Owner); } } public void SendToPlayer(T packetData, SNet_Player player) { if ((Object)(object)player == (Object)null) { Logger.Error(GetType().Name + " - SyncedPlayerEvent player was null!"); return; } if (player.Lookup == 0L) { Logger.Error(GetType().Name + " - SyncedPlayerEvent lookup for player was 0!"); return; } SyncedPlayerEventPayload syncedPlayerEventPayload = default(SyncedPlayerEventPayload); syncedPlayerEventPayload.lookup = player.Lookup; SyncedPlayerEventPayload syncedPlayerEventPayload2 = syncedPlayerEventPayload; syncedPlayerEventPayload2.Serialize(packetData); if (player.IsBot) { if (AllowBots) { if (SNet.IsMaster) { Received_Callback(SNet.Master.Lookup, syncedPlayerEventPayload2); } else if (SNet.HasMaster) { NetworkAPI.InvokeEvent(EventName, syncedPlayerEventPayload2, SNet.Master, (SNet_ChannelType)2); } } } else if (SendToTargetOnly) { if (player.IsLocal) { Received_Callback(player.Lookup, syncedPlayerEventPayload2); } else { NetworkAPI.InvokeEvent(EventName, syncedPlayerEventPayload2, player, (SNet_ChannelType)2); } } else { NetworkAPI.InvokeEvent(EventName, syncedPlayerEventPayload2, (SNet_ChannelType)2); Received_Callback(player.Lookup, syncedPlayerEventPayload2); } } private void Received_Callback(ulong sender, SyncedPlayerEventPayload payload) { if (payload.TryGetPlayer(out SNet_Player player) && (player.IsBot ? AllowBots : (player.IsLocal || !SendToTargetOnly))) { Received(payload.Deserialize(), player); } } private void Received(T packet, SNet_Player receivedPlayer) { Receive(packet, receivedPlayer); this.OnReceive?.Invoke(packet, receivedPlayer); } protected virtual void Receive(T packet, SNet_Player receivedPlayer) { } } } namespace EEC.Networking.Replicators { public sealed class EnemyAgentModeReplicator : StateReplicator { public struct State { public AgentMode mode; } public override bool ClearOnLevelCleanup => true; public override string GUID => "EMD"; public void SetState(ushort id, AgentMode newMode) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) base.SetState(id, new State { mode = newMode }); } } public sealed class EnemyHealthInfoReplicator : StateReplicator { public struct State { public float maxHealth; public float health; } public override bool ClearOnLevelCleanup => true; public override string GUID => "EHI"; public void UpdateInfo(EnemyAgent agent) { SetState(((Agent)agent).GlobalID, new State { maxHealth = ((Dam_SyncedDamageBase)agent.Damage).HealthMax, health = Mathf.Max(0f, ((Dam_SyncedDamageBase)agent.Damage).Health) }); } } } namespace EEC.Networking.Inject { [HarmonyPatch(typeof(EnemyAI), "ModeChange")] internal static class Inject_EnemyAI_ModeChange { [HarmonyWrapSafe] internal static void Postfix(EnemyAI __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (SNet.IsMaster) { NetworkManager.EnemyAgentModeState.SetState(((Agent)__instance.m_enemyAgent).GlobalID, ((AgentAI)__instance).Mode); } } } [HarmonyPatch(typeof(SNet_GlobalManager))] internal static class Inject_SNet_GlobalManager { [HarmonyPatch("OnPlayerEvent")] [HarmonyPostfix] [HarmonyWrapSafe] internal static void Post_PlayerEvent(SNet_Player player, SNet_PlayerEvent playerEvent) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)playerEvent == 5) { SNetEvents.OnAgentSpawned(player); } } [HarmonyPatch("OnPrepareForRecall")] [HarmonyPostfix] [HarmonyWrapSafe] internal static void Post_PrepareRecall(eBufferType bufferType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) SNetEvents.OnPrepareRecall(bufferType); } [HarmonyPatch("OnRecallComplete")] [HarmonyPostfix] [HarmonyWrapSafe] internal static void Post_RecallComplete(eBufferType bufferType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) SNetEvents.OnRecallComplete(bufferType); } } } namespace EEC.Networking.Events { public sealed class EnemyAnimEvent : SyncedEvent { public struct Packet { public ushort enemyID; public int animHash; public bool pauseAI; public float crossfadeTime; } public override string GUID => "EAE"; protected override void Receive(Packet packet) { IReplicator val = default(IReplicator); SNet_Replication.TryGetReplicator(packet.enemyID, ref val); if (val == null || val.ReplicatorSupplier == null) { return; } EnemySync val2 = ((Il2CppObjectBase)val.ReplicatorSupplier).TryCast(); if ((Object)(object)val2 == (Object)null) { return; } EnemyAgent agent = val2.m_agent; if (!((Object)(object)agent == (Object)null)) { Animator animator = agent.Locomotion.m_animator; INavigation navMeshAgent = ((AgentAI)agent.AI).m_navMeshAgent; animator.CrossFadeInFixedTime(packet.animHash, packet.crossfadeTime); if (packet.pauseAI && navMeshAgent.isOnNavMesh) { navMeshAgent.isStopped = true; } } } } } namespace EEC.Managers { [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] internal sealed class ConfigCacheAttribute : Attribute { } public static class ConfigManager { public sealed class EnemyEventHolder where T : class, IEnemyEvent { private readonly List _eventList = new List(); private readonly List _enemyCacheTempList = new List(); private readonly Dictionary _eventsEnemyCache = new Dictionary(); private T _handlerTemp; private EnemyCustomBase _customTemp; private T[] _events = Array.Empty(); private bool _hasDirty; public string EventName { get; set; } = string.Empty; public bool IgnoreLogs { get; set; } public T[] Events { get { if (_hasDirty) { _events = _eventList.ToArray(); _hasDirty = false; } return _events; } } public EnemyEventHolder(string eventName, bool ignoreLogs = false) { EventName = eventName; IgnoreLogs = ignoreLogs; } public void TryAdd(EnemyCustomBase custom) { if (custom is T item) { _eventList.Add(item); _hasDirty = true; } } public void Clear() { _eventsEnemyCache.Clear(); _eventList.Clear(); _hasDirty = true; } internal void RegisterCache(uint enemyID, bool forceRebuild) { if (!forceRebuild && _eventsEnemyCache.ContainsKey(enemyID)) { return; } _enemyCacheTempList.Clear(); T[] events = Events; int num = events.Length; for (int i = 0; i < num; i++) { _handlerTemp = events[i]; _customTemp = _handlerTemp.Base; if (_customTemp.IsTarget(enemyID)) { _enemyCacheTempList.Add(_handlerTemp); } } _eventsEnemyCache[enemyID] = _enemyCacheTempList.ToArray(); } internal void FireEvent(EnemyAgent agent, Action doAction) { if (doAction == null || !_eventsEnemyCache.TryGetValue(agent.EnemyDataID, out T[] value)) { return; } int num = value.Length; for (int i = 0; i < num; i++) { _handlerTemp = value[i]; _customTemp = _handlerTemp.Base; if (!IgnoreLogs && Logger.DevLogAllowed) { _customTemp.LogDev("Apply " + EventName + " Event: " + ((Object)agent).name); } doAction(_handlerTemp); if (!IgnoreLogs && Logger.VerboseLogAllowed) { _customTemp.LogVerbose("Finished!"); } } } } private static readonly Type[] _configTypes; private static readonly Dictionary _configTypeToFileName; private static readonly Dictionary _configFileNameToType; private static readonly Dictionary _configInstances; private static readonly IEnumerable _cacheProperties; private static readonly List _customizationBuffer; private static readonly EnemyEventHolder _enemyPrefabBuiltHolder; private static readonly EnemyEventHolder _enemySpawnedHolder; private static readonly EnemyEventHolder _enemyDeadHolder; private static readonly EnemyEventHolder _enemyDespawnedHolder; private static readonly EnemyEventHolder _enemyModeChangedHolder; private static readonly EnemyEventHolder _enemyGlowHolder; public static bool UseLiveEdit { get; private set; } public static bool LinkMTFOHotReload { get; private set; } public static string BasePath => EntryPoint.BasePath; [ConfigCache] public static GlobalConfig Global { get; private set; } [ConfigCache] public static CategoryConfig Categories { get; private set; } [ConfigCache] public static ModelCustomConfig ModelCustom { get; private set; } [ConfigCache] public static AbilityCustomConfig AbilityCustom { get; private set; } [ConfigCache] public static ProjectileCustomConfig ProjectileCustom { get; private set; } [ConfigCache] public static TentacleCustomConfig TentacleCustom { get; private set; } [ConfigCache] public static DetectionCustomConfig DetectionCustom { get; private set; } [ConfigCache] public static PropertyCustomConfig PropertyCustom { get; private set; } [ConfigCache] public static SpawnCostCustomConfig SpawnCostCustom { get; private set; } [ConfigCache] public static EnemyAbilityCustomConfig EnemyAbilityCustom { get; private set; } public static IEnumerable CustomizationBuffer => _customizationBuffer; public static event Action EnemyPrefabBuilt; static ConfigManager() { Global = new GlobalConfig(); Categories = new CategoryConfig(); ModelCustom = new ModelCustomConfig(); AbilityCustom = new AbilityCustomConfig(); ProjectileCustom = new ProjectileCustomConfig(); TentacleCustom = new TentacleCustomConfig(); DetectionCustom = new DetectionCustomConfig(); PropertyCustom = new PropertyCustomConfig(); SpawnCostCustom = new SpawnCostCustomConfig(); EnemyAbilityCustom = new EnemyAbilityCustomConfig(); _configTypes = new Type[11] { typeof(GlobalConfig), typeof(CategoryConfig), typeof(ScoutWaveConfig), typeof(AbilityCustomConfig), typeof(DetectionCustomConfig), typeof(EnemyAbilityCustomConfig), typeof(ModelCustomConfig), typeof(ProjectileCustomConfig), typeof(PropertyCustomConfig), typeof(SpawnCostCustomConfig), typeof(TentacleCustomConfig) }; _configTypeToFileName = new Dictionary(); _configFileNameToType = new Dictionary(); _configInstances = new Dictionary(); _customizationBuffer = new List(); _enemyPrefabBuiltHolder = new EnemyEventHolder("PrefabBuilt"); _enemySpawnedHolder = new EnemyEventHolder("Spawned"); _enemyDeadHolder = new EnemyEventHolder("Dead"); _enemyDespawnedHolder = new EnemyEventHolder("Despawned"); _enemyModeChangedHolder = new EnemyEventHolder("AgentModeChange", ignoreLogs: true); _enemyGlowHolder = new EnemyEventHolder("Glow", ignoreLogs: true); _cacheProperties = from x in typeof(ConfigManager).GetProperties() where Attribute.IsDefined(x, typeof(ConfigCacheAttribute)) select x; } internal static void Initialize() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown UseLiveEdit = Configuration.UseLiveEdit; LinkMTFOHotReload = Configuration.LinkMTFOHotReload; Type[] configTypes = _configTypes; foreach (Type type in configTypes) { Config config = Activator.CreateInstance(type) as Config; string fileName = config.FileName; _configTypeToFileName[type] = fileName; _configFileNameToType[fileName] = type; _configFileNameToType[fileName.ToLowerInvariant()] = type; _configInstances[fileName] = config; } LoadAllConfig(); GenerateBuffer(); if (LinkMTFOHotReload) { MTFOUtil.HotReloaded += ReloadConfig; } if (UseLiveEdit) { LiveEditListener obj = LiveEdit.CreateListener(BasePath, "*.*", true); obj.FileChanged += new LiveEditEventHandler(LiveEdit_FileChanged); obj.StartListen(); } } internal static void FireAssetLoaded() { foreach (EnemyCustomBase item in _customizationBuffer) { item.OnAssetLoaded(); } } internal static void DumpDefault() { string text = Path.Combine(BasePath, "Dump"); Directory.CreateDirectory(text); foreach (KeyValuePair configInstance in _configInstances) { File.WriteAllText(Path.Combine(text, configInstance.Key + ".json"), JSON.Serialize(configInstance.Value.CreateBlankConfig(), configInstance.Value.GetType())); } } internal static void ReloadConfig() { Logger.Log("HOT RELOADING CONFIG!"); UnloadAllConfig(doClear: true); LoadAllConfig(); GenerateBuffer(); FireAssetLoaded(); FirePrefabBuildEventAll(rebuildPrefabs: true); } internal static void UnloadAllConfig(bool doClear) { foreach (EnemyCustomBase item in _customizationBuffer) { item.OnConfigUnloaded(); item.ClearTargetLookup(); } foreach (KeyValuePair configInstance in _configInstances) { configInstance.Value.Unloaded(); } if (doClear) { ClearConfigs(); } } internal static void ClearConfigs() { KeyValuePair[] array = _configInstances.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; _configInstances[keyValuePair.Key] = Activator.CreateInstance(keyValuePair.Value.GetType()) as Config; } } internal static void LoadAllConfig() { if (MTFOUtil.IsLoaded && MTFOUtil.HasCustomContent) { Type[] configTypes = _configTypes; for (int i = 0; i < configTypes.Length; i++) { LoadConfig(configTypes[i]); } } else { Logger.Warning("No Custom content were found, No Customization will be applied"); } } internal static void LoadConfig(Type configType) { Type configType2 = configType; try { if (!_configTypeToFileName.TryGetValue(configType2, out string value)) { throw new ArgumentOutOfRangeException("configType"); } Logger.Debug("Loading '" + value + "' Config..."); if (TryGetExistingConfigPath(value, out string path)) { Logger.Verbose(" - Full Path: " + path); if (!TryLoadConfigData(path, configType2, out Config config)) { return; } _configInstances[value] = config; config.Loaded(); } else if (!Attribute.IsDefined(configType2, typeof(ObsoleteAttribute))) { Logger.Warning("Config file for '" + value + "' is not exist, ignoring this config..."); } PropertyInfo propertyInfo = _cacheProperties.Where((PropertyInfo x) => x.PropertyType == configType2).FirstOrDefault(); if (propertyInfo != null) { propertyInfo.SetValue(null, _configInstances[value]); } } catch (Exception value2) { Logger.Error($"Error Occured While reading Config from type: {configType2.Name}\n{value2}"); } } private static bool TryGetExistingConfigPath(string name, out string path) { string path2 = name + ".jsonc"; string text = Path.Combine(BasePath, path2); if (File.Exists(text)) { path = text; return true; } path2 = name + ".json"; text = Path.Combine(BasePath, path2); if (File.Exists(text)) { path = text; return true; } path = string.Empty; return false; } private static bool TryLoadConfigData(string filePath, Type type, out Config config) { if (File.Exists(filePath)) { try { config = JSON.Deserialize(type, File.ReadAllText(filePath)) as Config; return true; } catch (Exception value) { Logger.Error($"Exception Occured While reading {filePath} file: {value}"); config = null; return false; } } Logger.Warning("File: " + filePath + " is not exist, ignoring this config..."); config = null; return false; } private static void GenerateBuffer() { _customizationBuffer.Clear(); foreach (IEnumerable item in from x in _configInstances.Values where x is CustomizationConfig select ((CustomizationConfig)x).GetAllSettings()) { _customizationBuffer.AddRange(item); } _customizationBuffer.RemoveAll((EnemyCustomBase x) => !x.Enabled); foreach (EnemyCustomBase item2 in _customizationBuffer) { item2.OnConfigLoaded(); if (Logger.DevLogAllowed) { item2.LogDev("Initialized:"); } if (Logger.VerboseLogAllowed) { item2.LogVerbose(item2.Target.ToDebugString()); } } GenerateEventBuffer(); } private static void RegisterTargetEnemyLookup(EnemyDataBlock enemy) { foreach (EnemyCustomBase item in _customizationBuffer) { item.RegisterTargetEnemyLookup(enemy); } } private static void TargetEnemyLookupFullyBuilt() { foreach (EnemyCustomBase item in _customizationBuffer) { item.OnTargetIDLookupBuilt(); } } private static void GenerateEventBuffer() { _enemyPrefabBuiltHolder.Clear(); _enemySpawnedHolder.Clear(); _enemyDeadHolder.Clear(); _enemyDespawnedHolder.Clear(); _enemyModeChangedHolder.Clear(); _enemyGlowHolder.Clear(); foreach (EnemyCustomBase item in _customizationBuffer) { _enemyPrefabBuiltHolder.TryAdd(item); _enemySpawnedHolder.TryAdd(item); _enemyDeadHolder.TryAdd(item); _enemyDespawnedHolder.TryAdd(item); _enemyModeChangedHolder.TryAdd(item); _enemyGlowHolder.TryAdd(item); } } private static void CacheEnemyEventBuffer(uint enemyID) { _enemyPrefabBuiltHolder.RegisterCache(enemyID, forceRebuild: false); _enemySpawnedHolder.RegisterCache(enemyID, forceRebuild: false); _enemyDeadHolder.RegisterCache(enemyID, forceRebuild: false); _enemyDespawnedHolder.RegisterCache(enemyID, forceRebuild: false); _enemyModeChangedHolder.RegisterCache(enemyID, forceRebuild: false); _enemyGlowHolder.RegisterCache(enemyID, forceRebuild: false); } internal static void FirePrefabBuildEventAll(bool rebuildPrefabs, bool firePrefabEvents = true) { EnemyDataBlock[] array = Il2CppArrayBase.op_Implicit(GameDataBlockBase.GetAllBlocks()); foreach (EnemyDataBlock val in array) { GameObject enemyPrefab = EnemyPrefabManager.GetEnemyPrefab(((GameDataBlockBase)(object)val).persistentID); if (enemyPrefab == null) { Logger.Error($"EnemyData id: {((GameDataBlockBase)(object)val).persistentID} doesn't have EnemyPrefab!"); continue; } if (rebuildPrefabs) { Object.Destroy((Object)(object)enemyPrefab); EnemyPrefabManager.GenerateEnemy(val); enemyPrefab = EnemyPrefabManager.GetEnemyPrefab(((GameDataBlockBase)(object)val).persistentID); } EnemyAgent componentInChildren = enemyPrefab.GetComponentInChildren(true); if (componentInChildren == null) { Logger.Error($"EnemyData id: {((GameDataBlockBase)(object)val).persistentID} prefab doesn't have EnemyAgent!"); continue; } RegisterTargetEnemyLookup(val); CacheEnemyEventBuffer(((GameDataBlockBase)(object)val).persistentID); if (firePrefabEvents) { FirePrefabBuiltEvent(componentInChildren, val); ConfigManager.EnemyPrefabBuilt?.Invoke(componentInChildren, val); } } TargetEnemyLookupFullyBuilt(); if (rebuildPrefabs) { ((SNet_ReplicationManager)(object)EnemyAllocator.Current.m_enemyReplicationManager).ClearPrefabs(); EnemyAllocator.Current.GetEnemyPrefabs(); } } internal static void FirePrefabBuiltEvent(EnemyAgent agent, EnemyDataBlock enemyData) { EnemyAgent agent2 = agent; EnemyDataBlock enemyData2 = enemyData; _enemyPrefabBuiltHolder.FireEvent(agent2, delegate(IEnemyPrefabBuiltEvent e) { e.OnPrefabBuilt(agent2, enemyData2); }); } internal static void FireSpawnedEvent(EnemyAgent agent) { EnemyAgent agent2 = agent; if (Configuration.Profiler) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Restart(); Stopwatch innerStopwatch = new Stopwatch(); _enemySpawnedHolder.FireEvent(agent2, delegate(IEnemySpawnedEvent e) { innerStopwatch.Restart(); e.OnSpawned(agent2); Logger.Log($" - {e.Base.GetProcessName()} ElapsedTick: {innerStopwatch.ElapsedTicks}({innerStopwatch.ElapsedMilliseconds}ms)"); }); Logger.Log($"FireSpawned Event ElapsedTick: {stopwatch.ElapsedTicks}({stopwatch.ElapsedMilliseconds}ms) {((Object)agent2).name}"); CustomizationAPI.OnSpawnCustomizationDone_Internal(agent2); } else { _enemySpawnedHolder.FireEvent(agent2, delegate(IEnemySpawnedEvent e) { e.OnSpawned(agent2); }); CustomizationAPI.OnSpawnCustomizationDone_Internal(agent2); } } internal static void FireDeadEvent(EnemyAgent agent) { EnemyAgent agent2 = agent; _enemyDeadHolder.FireEvent(agent2, delegate(IEnemyDeadEvent e) { e.OnDead(agent2); }); } internal static void FireDespawnedEvent(EnemyAgent agent) { EnemyAgent agent2 = agent; _enemyDespawnedHolder.FireEvent(agent2, delegate(IEnemyDespawnedEvent e) { e.OnDespawned(agent2); }); } internal static void FireAgentModeChangedEvent(EnemyAgent agent, AgentMode newMode) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) EnemyAgent agent2 = agent; _enemyModeChangedHolder.FireEvent(agent2, delegate(IEnemyAgentModeEvent e) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) e.OnAgentModeChanged(agent2, newMode); }); } internal static bool FireGlowEvent(EnemyAgent agent, ref GlowInfo glowInfo) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) EnemyAgent agent2 = agent; bool altered = false; GlowInfo newGlowInfo = new GlowInfo(glowInfo.Color, glowInfo.Position); _enemyGlowHolder.FireEvent(agent2, delegate(IEnemyGlowEvent e) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) GlowInfo glowInfo2 = new GlowInfo(newGlowInfo.Color, newGlowInfo.Position); if (e.OnGlow(agent2, ref glowInfo2)) { newGlowInfo = glowInfo2; altered = true; } }); if (altered) { glowInfo = newGlowInfo; } return altered; } private static void LiveEdit_FileChanged(LiveEditEventArgs e) { LiveEditEventArgs e2 = e; string extension = Path.GetExtension(e2.FullPath); if (!extension.InvariantEquals(".json", ignoreCase: true) && !extension.InvariantEquals(".jsonc", ignoreCase: true)) { return; } LiveEdit.TryReadFileContent(e2.FullPath, (Action)delegate(string content) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(e2.FullPath); if (_configFileNameToType.TryGetValue(fileNameWithoutExtension.ToLowerInvariant(), out Type type)) { fileNameWithoutExtension = _configTypeToFileName[type]; Logger.Log("Config File Changed: " + fileNameWithoutExtension); _configInstances[fileNameWithoutExtension].Unloaded(); if (_configInstances[fileNameWithoutExtension] is CustomizationConfig customizationConfig) { foreach (EnemyCustomBase allSetting in customizationConfig.GetAllSettings()) { allSetting.OnConfigUnloaded(); } } try { Config config = (Config)JSON.Deserialize(type, content); _configInstances[fileNameWithoutExtension] = config; config.Loaded(); _cacheProperties.Where((PropertyInfo x) => x.PropertyType == type).FirstOrDefault()?.SetValue(null, _configInstances[fileNameWithoutExtension]); } catch (Exception value) { Logger.Error($"Exception occurred while reading {e2.FullPath} file: {value}"); } if (_configInstances[fileNameWithoutExtension] is CustomizationConfig) { try { IEnumerable allSettings = ((CustomizationConfig)_configInstances[fileNameWithoutExtension]).GetAllSettings(); bool flag = false; foreach (EnemyCustomBase item in allSettings) { item.OnAssetLoaded(); if (!flag && item is IEnemyPrefabBuiltEvent) { flag = true; } } GenerateBuffer(); FirePrefabBuildEventAll(flag, flag); } catch (Exception value2) { Logger.Error($"Exception occurred while re-applying configs: {value2}"); } } } }); } } } namespace EEC.Managers.Properties { [CallConstructorOnLoad] public static class EnemySpawnDataManager { private static readonly Dictionary _lookup; static EnemySpawnDataManager() { _lookup = new Dictionary(500); EnemyEvents.Spawn += Spawn; EnemyEvents.Despawn += Despawn; LevelEvents.LevelCleanup += OnLevelCleanup; } private static void Spawn(EnemyAgent agent, pEnemySpawnData spawnData) { //IL_0005: 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_0010: Unknown result type (might be due to invalid IL or missing references) _lookup[spawnData.replicationData.ReplicatorKey] = spawnData; } private static void Despawn(EnemyAgent agent) { _lookup.Remove(((Agent)agent).GlobalID); } private static void OnLevelCleanup() { _lookup.Clear(); } public static bool TryGet(ushort id, out pEnemySpawnData data) { return _lookup.TryGetValue(id, out data); } } public static class ProjectileOwnerManager { private static readonly Dictionary _lookup; private static readonly Dictionary _enemyDataIDLookup; static ProjectileOwnerManager() { _lookup = new Dictionary(); _enemyDataIDLookup = new Dictionary(); LevelEvents.LevelCleanup += OnLevelCleanup; } private static void OnLevelCleanup() { _lookup.Clear(); _enemyDataIDLookup.Clear(); } public static void Set(int instanceID, EnemyAgent agent) { _lookup[instanceID] = agent; _enemyDataIDLookup[instanceID] = agent.EnemyDataID; } public static void Remove(int instanceID) { _lookup.Remove(instanceID); _enemyDataIDLookup.Remove(instanceID); } public static bool TryGet(int instanceID, out EnemyAgent agent) { return _lookup.TryGetValue(instanceID, out agent); } public static bool TryGetDataID(int instanceID, out uint enemyDataID) { return _enemyDataIDLookup.TryGetValue(instanceID, out enemyDataID); } } } namespace EEC.Managers.Properties.Inject { [HarmonyPatch(typeof(EAB_ProjectileShooter), "FireAtAgent")] internal static class Inject_EAB_Shooter { public static Agent LastAgent; internal static void Prefix(EAB_ProjectileShooter __instance) { LastAgent = (Agent)(object)((EnemyAbility)__instance).m_owner; } internal static void Postfix() { LastAgent = null; } } [HarmonyPatch(typeof(EAB_ProjectileShooterSquidBoss), "FireAtAgent")] internal static class Inject_EAB_ShooterSquidBoss { internal static void Prefix(EAB_ProjectileShooterSquidBoss __instance) { Inject_EAB_Shooter.LastAgent = (Agent)(object)((EnemyAbility)__instance).m_owner; } internal static void Postfix() { Inject_EAB_Shooter.LastAgent = null; } } [HarmonyPatch(typeof(ProjectileManager), "DoFireTargeting")] internal static class Inject_ProjectileManager_DoFire { [HarmonyWrapSafe] internal static void Postfix(pFireTargeting data) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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) if (data.burstSize == 1 || data.burstSize > 65535 || data.burstSize < 0) { return; } GameObject s_tempGO = ProjectileManager.s_tempGO; if ((Object)(object)s_tempGO == (Object)null) { return; } int instanceID = ((Object)s_tempGO).GetInstanceID(); IReplicator val = default(IReplicator); if (s_tempGO.GetComponent() == null || !SNet_Replication.TryGetReplicator(checked((ushort)data.burstSize), ref val) || ((val != null) ? val.ReplicatorSupplier : null) == null) { return; } EnemySync val2 = ((Il2CppObjectBase)val.ReplicatorSupplier).TryCast(); if ((Object)(object)val2 != (Object)null) { ProjectileOwnerManager.Set(instanceID, val2.m_agent); MonoBehaviourEventHandler.AttatchToObject(s_tempGO, null, null, null, delegate { ProjectileOwnerManager.Remove(instanceID); }); } } } [HarmonyPatch(typeof(ProjectileManager), "WantToFireTargeting")] internal static class Inject_ProjectileManager_WantToFire { internal static void Prefix(ref int burstSize) { if ((Object)(object)Inject_EAB_Shooter.LastAgent != (Object)null) { burstSize = Inject_EAB_Shooter.LastAgent.GlobalID; } } } } namespace EEC.Managers.Assets { public static class AssetCacheManager { public enum OutputType { None, Console, File } public sealed class MaterialAssets : Assets { public override string DoResolveNameConflict(Material obj, string currentName) { string text = currentName + "::" + ((Object)obj.shader).name; if (Contains(text)) { text = "DUPLICATE ITEM"; } return text; } public override bool ShouldCache(Material mat) { if ((Object)(object)mat == (Object)null) { return false; } if ((Object)(object)mat.shader == (Object)null) { return false; } if (!ConfigManager.Global.CacheAllMaterials && !((Object)mat.shader).name.InvariantContains("EnemyFlesh")) { return false; } return true; } } public class Assets where T : Material { private StreamWriter _streamWriter; private readonly Dictionary _lookup = new Dictionary(); public string Name => typeof(T).Name; public virtual string DoResolveNameConflict(T obj, string currentName) { return currentName; } public virtual bool ShouldCache(T obj) { return true; } internal void Cache() { StartLog(); foreach (Object item in (Il2CppArrayBase)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of())) { T val = ((Il2CppObjectBase)item).Cast(); object obj = val; string text = ((obj != null) ? ((Object)obj).name : null) ?? string.Empty; if (_lookup.ContainsKey(text)) { text = DoResolveNameConflict(val, text); if (_lookup.ContainsKey(text)) { continue; } } if (!string.IsNullOrEmpty(text) && ShouldCache(val)) { _lookup[text] = val; DoLog(text); } } EndLog(); } internal void Set(string name, T obj) { _lookup[name] = obj; } public bool TryGet(string name, out T obj) { return _lookup.TryGetValue(name, out obj); } public bool Contains(string name) { return _lookup.ContainsKey(name); } private void StartLog() { switch (OutputMethod) { case OutputType.Console: Logger.Debug("Caching " + Name + " Lists..."); break; case OutputType.File: { FileStream stream = File.Open(Path.Combine(ConfigManager.BasePath, "_dump." + Name.ToLowerInvariant() + ".txt"), FileMode.Create, FileAccess.Write); _streamWriter = new StreamWriter(stream); break; } } } private void DoLog(string assetName) { switch (OutputMethod) { case OutputType.Console: Logger.Debug(assetName); break; case OutputType.File: _streamWriter.WriteLine(assetName); break; } } private void EndLog() { switch (OutputMethod) { case OutputType.Console: Logger.Debug("Done!"); break; case OutputType.File: _streamWriter.Dispose(); break; } } } public class Assets1 where T : Texture { private StreamWriter _streamWriter; private readonly Dictionary _lookup = new Dictionary(); public string Name => typeof(T).Name; public virtual string DoResolveNameConflict(T obj, string currentName) { return currentName; } public virtual bool ShouldCache(T obj) { return true; } internal void Cache() { StartLog(); foreach (Object item in (Il2CppArrayBase)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of())) { T val = ((Il2CppObjectBase)item).Cast(); object obj = val; string text = ((obj != null) ? ((Object)obj).name : null) ?? string.Empty; if (_lookup.ContainsKey(text)) { text = DoResolveNameConflict(val, text); if (_lookup.ContainsKey(text)) { continue; } } if (!string.IsNullOrEmpty(text) && ShouldCache(val)) { _lookup[text] = val; DoLog(text); } } EndLog(); } internal void Set(string name, T obj) { _lookup[name] = obj; } public bool TryGet(string name, out T obj) { return _lookup.TryGetValue(name, out obj); } public bool Contains(string name) { return _lookup.ContainsKey(name); } private void StartLog() { switch (OutputMethod) { case OutputType.Console: Logger.Debug("Caching " + Name + " Lists..."); break; case OutputType.File: { FileStream stream = File.Open(Path.Combine(ConfigManager.BasePath, "_dump." + Name.ToLowerInvariant() + ".txt"), FileMode.Create, FileAccess.Write); _streamWriter = new StreamWriter(stream); break; } } } private void DoLog(string assetName) { switch (OutputMethod) { case OutputType.Console: Logger.Debug(assetName); break; case OutputType.File: _streamWriter.WriteLine(assetName); break; } } private void EndLog() { switch (OutputMethod) { case OutputType.Console: Logger.Debug("Done!"); break; case OutputType.File: _streamWriter.Dispose(); break; } } } public static OutputType OutputMethod { get; set; } = OutputType.None; public static Assets Materials { get; } = new MaterialAssets(); public static Assets1 Texture3Ds { get; } = new Assets1(); internal static void AssetLoaded() { Materials.Cache(); Texture3Ds.Cache(); } } public static class SpriteManager { private static readonly Dictionary _textureCache = new Dictionary(); private static readonly Dictionary _spriteCache = new Dictionary(); public static string BaseSpritePath { get; private set; } public static void Initialize() { if (string.IsNullOrEmpty(ConfigManager.BasePath)) { return; } BaseSpritePath = Path.Combine(ConfigManager.BasePath, "icons"); if (Directory.Exists(BaseSpritePath)) { string[] files = Directory.GetFiles(BaseSpritePath, "*.png", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { TryCacheTexture2D(files[i]); } } } public static void TryCacheTexture2D(string file) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!File.Exists(file)) { return; } string text = Path.GetFileNameWithoutExtension(file).ToLowerInvariant(); if (!_textureCache.ContainsKey(text)) { byte[] array = File.ReadAllBytes(file); Texture2D val = new Texture2D(2, 2); if (ImageConversion.LoadImage(val, Il2CppStructArray.op_Implicit(array))) { ((Object)val).name = text; ((Object)val).hideFlags = (HideFlags)61; Logger.Debug("GeneratedTexture: " + text); _textureCache.Add(text, val); } } } public static Sprite GenerateSprite(string fileName, float pixelsPerUnit = 64f) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) SetFilenameFormat(ref fileName); if (!_textureCache.TryGetValue(fileName, out Texture2D value)) { return null; } string spriteKey = GetSpriteKey(fileName, pixelsPerUnit); if (_spriteCache.TryGetValue(spriteKey, out Sprite value2)) { return value2; } Sprite val = Sprite.Create(value, new Rect(0f, 0f, (float)((Texture)value).width, (float)((Texture)value).height), new Vector2(0.5f, 0.5f), pixelsPerUnit); ((Object)val).name = spriteKey; ((Object)val).hideFlags = (HideFlags)61; Logger.Debug("GeneratedSprite: " + spriteKey); _spriteCache.Add(spriteKey, val); return val; } public static bool TryGetSpriteCache(string fileName, float pixelsPerUnit, out Sprite sprite) { SetFilenameFormat(ref fileName); return _spriteCache.TryGetValue(GetSpriteKey(fileName, pixelsPerUnit), out sprite); } private static string GetSpriteKey(string name, float pixelsPerUnit) { return $"{name}__{pixelsPerUnit:0.##}"; } private static void SetFilenameFormat(ref string fileName) { fileName = fileName.ToLowerInvariant(); if (Path.HasExtension(fileName)) { fileName = Path.GetFileNameWithoutExtension(fileName); } } } } namespace EEC.Inject { [HarmonyPatch(typeof(EnemyAgent), "OnDeSpawn")] internal static class Inject_EnemyAgent_DeSpawn { [HarmonyWrapSafe] internal static void Prefix(EnemyAgent __instance) { EnemyEvents.OnDespawn(__instance); } [HarmonyWrapSafe] internal static void Postfix(EnemyAgent __instance) { EnemyEvents.OnDespawned(__instance); ConfigManager.FireDespawnedEvent(__instance); } } [HarmonyPatch(typeof(EnemyAgent), "Setup")] internal static class Inject_EnemyAgent_Setup { [HarmonyWrapSafe] internal static void Prefix(EnemyAgent __instance, pEnemySpawnData spawnData) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) EnemyAgent __instance2 = __instance; if (!__instance2.m_isSetup) { EnemyEvents.OnSpawn(__instance2, spawnData); return; } EnemyEvents.OnSpawned(__instance2); ConfigManager.FireSpawnedEvent(__instance2); __instance2.AddOnDeadOnce(delegate { ConfigManager.FireDeadEvent(__instance2); }); } } [HarmonyPatch(typeof(EnemyAppearance))] internal static class Inject_EnemyAppearance_InterpolateGlows { [HarmonyPatch("InterpolateGlow", new Type[] { typeof(Color), typeof(Vector4), typeof(float) })] [HarmonyPrefix] [HarmonyWrapSafe] internal static void Pre_InterpolateGlow(ref Color col, ref Vector4 pos, EnemyAppearance __instance) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) GlowInfo glowInfo = new GlowInfo(col, pos); if (ConfigManager.FireGlowEvent(__instance.m_owner, ref glowInfo)) { col = glowInfo.Color; pos = glowInfo.Position; } } } [HarmonyPatch(typeof(EnemyLocomotion), "HashAnimationParams")] internal static class Inject_EnemyLocomotion { [HarmonyWrapSafe] internal static void Postfix() { EnemyAnimUtil.Initialize(); } } [HarmonyPatch(typeof(PlayerAgent), "Setup")] internal static class Inject_PlayerAgent_Setup { [HarmonyWrapSafe] internal static void Postfix(PlayerAgent __instance) { PlayerData.MaxHealth = __instance.PlayerData.health; } } } namespace EEC.Events { public delegate void AssetLoadedHandler(); public static class AssetEvents { public static bool IsStartupAssetLoaded { get; private set; } public static bool IsEnemyAssetLoaded { get; private set; } public static bool IsShardAssetLoaded { get; private set; } public static bool IsAllAssetLoaded { get; private set; } public static event AssetLoadedHandler StartupAssetLoaded; public static event AssetLoadedHandler EnemyAssetLoaded; public static event AssetLoadedHandler ShardAssetLoaded; public static event AssetLoadedHandler AllAssetLoaded; static AssetEvents() { IsStartupAssetLoaded = AssetShardManager.StartupAssetsIsLoaded; IsEnemyAssetLoaded = AssetShardManager.EnemyAssetsIsLoaded; IsShardAssetLoaded = AssetShardManager.SharedAssetsIsLoaded; } internal static void OnStartupAssetLoaded() { IsStartupAssetLoaded = true; AssetEvents.StartupAssetLoaded?.Invoke(); CheckLoadedStatus(); } internal static void OnEnemyAssetLoaded() { IsEnemyAssetLoaded = true; AssetEvents.EnemyAssetLoaded?.Invoke(); CheckLoadedStatus(); } internal static void OnShardAssetLoaded() { IsShardAssetLoaded = true; AssetEvents.ShardAssetLoaded?.Invoke(); CheckLoadedStatus(); } private static void CheckLoadedStatus() { if (!IsAllAssetLoaded) { IsAllAssetLoaded = IsStartupAssetLoaded & IsEnemyAssetLoaded & IsShardAssetLoaded; if (IsAllAssetLoaded) { AssetEvents.AllAssetLoaded?.Invoke(); } } } } public delegate void EnemyTakeDamageHandler(EnemyAgent enemyAgent, Agent inflictor, float damage); public delegate void EnemyHealthUpdateHandler(EnemyAgent enemyAgent, float maxHealth, float health); public static class EnemyDamageEvents { public static event EnemyTakeDamageHandler Damage; [Obsolete("Disabled Due to Patching Error", true)] public static event EnemyTakeDamageHandler MeleeDamage; [Obsolete("Disabled Due to Patching Error", true)] public static event EnemyTakeDamageHandler BulletDamage; [Obsolete("Disabled Due to Patching Error", true)] public static event EnemyTakeDamageHandler ExplosionDamage; public static event EnemyHealthUpdateHandler HealthUpdated; internal static void OnDamage(EnemyAgent enemyAgent, Agent inflictor, float damage) { EnemyDamageEvents.Damage?.Invoke(enemyAgent, inflictor, damage); } internal static void OnMeleeDamage(EnemyAgent enemyAgent, Agent inflictor, float damage) { EnemyDamageEvents.MeleeDamage?.Invoke(enemyAgent, inflictor, damage); } internal static void OnBulletDamage(EnemyAgent enemyAgent, Agent inflictor, float damage) { EnemyDamageEvents.BulletDamage?.Invoke(enemyAgent, inflictor, damage); } internal static void OnExplosionDamage(EnemyAgent enemyAgent, Agent inflictor, float damage) { EnemyDamageEvents.ExplosionDamage?.Invoke(enemyAgent, inflictor, damage); } internal static void OnHealthUpdated(EnemyAgent enemyAgent, float maxHealth, float health) { EnemyDamageEvents.HealthUpdated?.Invoke(enemyAgent, maxHealth, health); } } public delegate void EnemyAgentHandlerWithSpawnData(EnemyAgent agent, pEnemySpawnData spawnData); public delegate void EnemyAgentHandler(EnemyAgent agent); public static class EnemyEvents { public static event EnemyAgentHandlerWithSpawnData Spawn; public static event EnemyAgentHandler Spawned; public static event EnemyAgentHandler Despawn; public static event EnemyAgentHandler Despawned; internal static void OnSpawn(EnemyAgent agent, pEnemySpawnData spawnData) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) EnemyEvents.Spawn?.Invoke(agent, spawnData); } internal static void OnSpawned(EnemyAgent agent) { EnemyEvents.Spawned?.Invoke(agent); } internal static void OnDespawn(EnemyAgent agent) { EnemyEvents.Despawn?.Invoke(agent); } internal static void OnDespawned(EnemyAgent agent) { EnemyEvents.Despawned?.Invoke(agent); } } public delegate void EnemyLimbHandler(Dam_EnemyDamageLimb limb); public static class EnemyLimbEvents { public static event EnemyLimbHandler Destroyed; internal static void OnDestroyed(Dam_EnemyDamageLimb limb) { EnemyLimbEvents.Destroyed?.Invoke(limb); } } public delegate void EnemyMarkerHandler(EnemyAgent agent, NavMarker marker); public static class EnemyMarkerEvents { public static event EnemyMarkerHandler Marked; internal static void OnMarked(EnemyAgent agent, NavMarker marker) { EnemyMarkerEvents.Marked?.Invoke(agent, marker); } } public delegate void InventoryEventHandler(GearPartFlashlight flashlight); public static class InventoryEvents { public static event InventoryEventHandler ItemWielded; internal static void OnWieldItem(GearPartFlashlight flashlight) { InventoryEvents.ItemWielded?.Invoke(flashlight); } } public delegate void LevelEventHandler(); public static class LevelEvents { public static event LevelEventHandler BuildStart; public static event LevelEventHandler BuildDone; public static event LevelEventHandler LevelCleanup; internal static void OnBuildStart() { LevelEvents.BuildStart?.Invoke(); } internal static void OnBuildDone() { LevelEvents.BuildDone?.Invoke(); } internal static void OnLevelCleanup() { LevelEvents.LevelCleanup?.Invoke(); } } public delegate void PlayerAliveHandler(PlayerAgent playerAgent); public static class LocalPlayerAliveEvents { public static event PlayerAliveHandler Down; public static event PlayerAliveHandler Revive; internal static void OnDown(PlayerAgent playerAgent) { LocalPlayerAliveEvents.Down?.Invoke(playerAgent); } internal static void OnRevive(PlayerAgent playerAgent) { LocalPlayerAliveEvents.Revive?.Invoke(playerAgent); } } public delegate void PlayerTakeDamageHandler(PlayerAgent playerAgent, Agent inflictor, float damage); public delegate void PlayerTakeDamageFromProjectileHandler(PlayerAgent playerAgent, Agent inflictor, ProjectileBase projectile, float damage); public static class LocalPlayerDamageEvents { public static event PlayerTakeDamageHandler Damage; public static event PlayerTakeDamageHandler MeleeDamage; public static event PlayerTakeDamageHandler TentacleDamage; public static event PlayerTakeDamageFromProjectileHandler ProjectileDamage; internal static void OnDamage(PlayerAgent playerAgent, Agent inflictor, float damage) { LocalPlayerDamageEvents.Damage?.Invoke(playerAgent, inflictor, damage); } internal static void OnMeleeDamage(PlayerAgent playerAgent, Agent inflictor, float damage) { LocalPlayerDamageEvents.MeleeDamage?.Invoke(playerAgent, inflictor, damage); } internal static void OnTentacleDamage(PlayerAgent playerAgent, Agent inflictor, float damage) { LocalPlayerDamageEvents.TentacleDamage?.Invoke(playerAgent, inflictor, damage); } internal static void OnProjectileDamage(PlayerAgent playerAgent, Agent inflictor, ProjectileBase projectile, float damage) { LocalPlayerDamageEvents.ProjectileDamage?.Invoke(playerAgent, inflictor, projectile, damage); } } public delegate void UnityEventHandler(GameObject caller); [InjectToIl2Cpp] public sealed class MonoBehaviourEventHandler : MonoBehaviour { [HideFromIl2Cpp] public event UnityEventHandler OnUpdate; [HideFromIl2Cpp] public event UnityEventHandler OnFixedUpdate; [HideFromIl2Cpp] public event UnityEventHandler OnDestroyed; [HideFromIl2Cpp] public event UnityEventHandler OnLateUpdate; public static void AttatchToObject(GameObject obj, UnityEventHandler onUpdate = null, UnityEventHandler onLateUpdate = null, UnityEventHandler onFixedUpdate = null, UnityEventHandler onDestroyed = null) { MonoBehaviourEventHandler monoBehaviourEventHandler = obj.AddOrGetComponent(); if (onUpdate != null) { monoBehaviourEventHandler.OnUpdate += onUpdate; } if (onLateUpdate != null) { monoBehaviourEventHandler.OnLateUpdate += onLateUpdate; } if (onFixedUpdate != null) { monoBehaviourEventHandler.OnFixedUpdate += onFixedUpdate; } if (onDestroyed != null) { monoBehaviourEventHandler.OnDestroyed += onDestroyed; } } private void Update() { this.OnUpdate?.Invoke(((Component)this).gameObject); } private void LateUpdate() { this.OnLateUpdate?.Invoke(((Component)this).gameObject); } private void FixedUpdate() { this.OnFixedUpdate?.Invoke(((Component)this).gameObject); } private void OnDestroy() { this.OnDestroyed?.Invoke(((Component)this).gameObject); this.OnUpdate = null; this.OnLateUpdate = null; this.OnFixedUpdate = null; this.OnDestroyed = null; } } public static class ProjectileEvents { public static event Action CollidedWorld; public static event Action CollidedPlayer; public static event Action LifeTimeDone; internal static void OnCollisionWorld(ProjectileBase projectile, GameObject collideObject) { ProjectileEvents.CollidedWorld?.Invoke(projectile, collideObject); } internal static void OnCollisionPlayer(ProjectileBase projectile, PlayerAgent collidePlayer) { ProjectileEvents.CollidedPlayer?.Invoke(projectile, collidePlayer); } internal static void OnLifeTimeDone(ProjectileTargeting projectile) { ProjectileEvents.LifeTimeDone?.Invoke(projectile); } } public delegate void ReceivePackHandler(iResourcePackReceiver receiver); public delegate void ReceiveMediHandler(iResourcePackReceiver receiver, float health); public delegate void ReceiveAmmoHandler(iResourcePackReceiver receiver, float main, float special); public delegate void ReceiveToolHandler(iResourcePackReceiver receiver, float tool); public delegate void ReceiveDisinfectHandler(iResourcePackReceiver receiver, float disinfect); public static class ResourcePackEvents { public static event ReceiveMediHandler ReceiveMedi; public static event ReceiveAmmoHandler ReceiveAmmo; public static event ReceiveToolHandler ReceiveTool; public static event ReceiveDisinfectHandler ReceiveDisinfect; internal static void OnReceiveMedi(iResourcePackReceiver receiver, float health) { ResourcePackEvents.ReceiveMedi?.Invoke(receiver, health); } internal static void OnReceiveAmmo(iResourcePackReceiver receiver, float main_rel, float special_rel) { ResourcePackEvents.ReceiveAmmo?.Invoke(receiver, main_rel, special_rel); } internal static void OnReceiveTool(iResourcePackReceiver receiver, float tool_rel) { ResourcePackEvents.ReceiveTool?.Invoke(receiver, tool_rel); } internal static void OnReceiveDisinfect(iResourcePackReceiver receiver, float disinfect) { ResourcePackEvents.ReceiveDisinfect?.Invoke(receiver, disinfect); } } public delegate void ScoutDetectionHandler(EnemyAgent enemyAgent, ScoutAntennaDetection detection); public delegate void ScoutAntennaHandler(EnemyAgent enemyAgent, ScoutAntennaDetection detection, ScoutAntenna antenna); public static class ScoutAntennaSpawnEvent { public static event ScoutDetectionHandler DetectionSpawn; public static event ScoutAntennaHandler AntennaSpawn; internal static void OnDetectionSpawn(EnemyAgent enemyAgent, ScoutAntennaDetection detection) { ScoutAntennaSpawnEvent.DetectionSpawn?.Invoke(enemyAgent, detection); } internal static void OnAntennaSpawn(EnemyAgent enemyAgent, ScoutAntennaDetection detection, ScoutAntenna antenna) { ScoutAntennaSpawnEvent.AntennaSpawn?.Invoke(enemyAgent, detection, antenna); } } } namespace EEC.Events.Inject { [HarmonyPatch(typeof(AssetShardManager), "LoadAllShardsForBundleAsync")] internal static class Inject_AssetShardManager { [HarmonyWrapSafe] internal static void Prefix(AssetBundleName name, ref Action callback) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 if ((int)name != 1) { if ((int)name != 5) { if ((int)name == 300) { callback += Action.op_Implicit((Action)AssetEvents.OnEnemyAssetLoaded); } } else { callback += Action.op_Implicit((Action)AssetEvents.OnStartupAssetLoaded); } } else { callback += Action.op_Implicit((Action)AssetEvents.OnShardAssetLoaded); } } } [HarmonyPatch(typeof(Builder))] internal static class Inject_Builder { [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("Build")] internal static void Pre_BuildStart() { LevelEvents.OnBuildStart(); } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("OnFactoryDone")] internal static void Post_BuildDone() { LevelEvents.OnBuildDone(); } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("OnLevelCleanup")] internal static void Post_LevelCleanup() { LevelEvents.OnLevelCleanup(); } } [HarmonyPatch(typeof(Dam_EnemyDamageBase))] internal static class Inject_Enemy_Limb { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("ReceiveDestroyLimb")] internal static void Post_DestroyLimb(pDestroyLimbData data, Dam_EnemyDamageBase __instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) EnemyLimbEvents.OnDestroyed(((Il2CppArrayBase)(object)__instance.DamageLimbs)[(int)data.limbID]); } } [HarmonyPatch(typeof(EnemyAgent), "SyncPlaceNavMarkerTag")] internal static class Inject_Enemy_Marked { [HarmonyWrapSafe] internal static void Postfix(EnemyAgent __instance) { EnemyMarkerEvents.OnMarked(__instance, __instance.m_tagMarker); } } [HarmonyPatch(typeof(Dam_EnemyDamageBase))] internal static class Inject_Enemy_RecieveDamages { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("ProcessReceivedDamage")] internal static void Post_Damage(float damage, Agent damageSource, Dam_EnemyDamageBase __instance) { EnemyDamageEvents.OnDamage(__instance.Owner, damageSource, damage); } internal static void Post_BulletDamage(pBulletDamageData data, Dam_EnemyDamageBase __instance) { Agent inflictor = default(Agent); ((pAgent)(ref data.source)).TryGet(ref inflictor); float damage = ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax); EnemyDamageEvents.OnDamage(__instance.Owner, inflictor, damage); EnemyDamageEvents.OnBulletDamage(__instance.Owner, inflictor, damage); } internal static void Post_MeleeDamage(pFullDamageData data, Dam_EnemyDamageBase __instance) { Agent inflictor = default(Agent); ((pAgent)(ref data.source)).TryGet(ref inflictor); float damage = ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax); EnemyDamageEvents.OnDamage(__instance.Owner, inflictor, damage); EnemyDamageEvents.OnMeleeDamage(__instance.Owner, inflictor, damage); } internal static void Post_ExplosionDamage(pFullDamageData data, Dam_EnemyDamageBase __instance) { Agent inflictor = default(Agent); ((pAgent)(ref data.source)).TryGet(ref inflictor); float damage = ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax); EnemyDamageEvents.OnDamage(__instance.Owner, inflictor, damage); EnemyDamageEvents.OnExplosionDamage(__instance.Owner, inflictor, damage); } } [HarmonyPatch(typeof(PlayerAgent))] internal static class Inject_PlayerAgent_GivePack { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("GiveHealth")] internal static void Post_Health(float amountRel, PlayerAgent __instance) { ResourcePackEvents.OnReceiveMedi(((Il2CppObjectBase)__instance).Cast(), amountRel); } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("GiveAmmoRel")] internal static void Post_Ammo(float ammoStandardRel, float ammoSpecialRel, float ammoClassRel, PlayerAgent __instance) { if (ammoStandardRel > 0f || ammoSpecialRel > 0f) { ResourcePackEvents.OnReceiveAmmo(((Il2CppObjectBase)__instance).Cast(), ammoStandardRel, ammoSpecialRel); } if (ammoClassRel > 0f) { ResourcePackEvents.OnReceiveTool(((Il2CppObjectBase)__instance).Cast(), ammoClassRel); } } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("GiveDisinfection")] internal static void Post_Disinect(float amountRel, PlayerAgent __instance) { ResourcePackEvents.OnReceiveDisinfect(((Il2CppObjectBase)__instance).Cast(), amountRel); } } [HarmonyPatch(typeof(PlayerInventoryBase))] internal static class Inject_PlayerInventoryBase { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("OnItemEquippableFlashlightWielded")] internal static void Post_DoWieldItem(GearPartFlashlight flashlight) { InventoryEvents.OnWieldItem(flashlight); } } [HarmonyPatch(typeof(Dam_PlayerDamageLocal))] internal static class Inject_Player_ReceiveDamages { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("ReceiveMeleeDamage")] internal static void Post_Melee(pFullDamageData data, Dam_PlayerDamageBase __instance) { Agent inflictor = default(Agent); if (((pAgent)(ref data.source)).TryGet(ref inflictor)) { float damage = ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax); LocalPlayerDamageEvents.OnDamage(__instance.Owner, inflictor, damage); LocalPlayerDamageEvents.OnMeleeDamage(__instance.Owner, inflictor, damage); } } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("ReceiveTentacleAttackDamage")] internal static void Post_Tentacle(pMediumDamageData data, Dam_PlayerDamageLocal __instance) { Agent inflictor = default(Agent); if (((pAgent)(ref data.source)).TryGet(ref inflictor)) { float damage = ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax); LocalPlayerDamageEvents.OnDamage(((Dam_PlayerDamageBase)__instance).Owner, inflictor, damage); LocalPlayerDamageEvents.OnTentacleDamage(((Dam_PlayerDamageBase)__instance).Owner, inflictor, damage); } } } [HarmonyPatch(typeof(PLOC_Downed))] internal static class Inject_PLOC_Downed { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("Enter")] private static void Post_Downed(PLOC_Downed __instance) { LocalPlayerAliveEvents.OnDown(((PLOC_Base)__instance).m_owner); } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("Exit")] private static void Post_Revived(PLOC_Downed __instance) { LocalPlayerAliveEvents.OnRevive(((PLOC_Base)__instance).m_owner); } } [HarmonyPatch(typeof(ProjectileBase), "Collision")] internal static class Inject_ProjectileBase { [HarmonyWrapSafe] internal static void Prefix(ProjectileBase __instance, RaycastHit hit) { if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) { return; } if (!((Component)((RaycastHit)(ref hit)).collider).gameObject.TryGetComp(out var component)) { ProjectileEvents.OnCollisionWorld(__instance, ((Component)((RaycastHit)(ref hit)).collider).gameObject); return; } Agent baseAgent = component.GetBaseAgent(); if ((Object)(object)baseAgent == (Object)null) { return; } if (!baseAgent.TryCastToPlayerAgent(out PlayerAgent playerAgent)) { ProjectileEvents.OnCollisionWorld(__instance, ((Component)((RaycastHit)(ref hit)).collider).gameObject); return; } ProjectileEvents.OnCollisionPlayer(__instance, playerAgent); if (__instance.TryGetOwner(out EnemyAgent agent) && !((Object)(object)agent == (Object)null) && !((Il2CppObjectBase)agent).WasCollected) { LocalPlayerDamageEvents.OnProjectileDamage(playerAgent, (Agent)(object)agent, __instance, __instance.m_maxDamage); } } } [HarmonyPatch(typeof(ProjectileTargeting), "OnDestroy")] internal static class Inject_ProjectileTargeting { [HarmonyWrapSafe] internal static void Prefix(ProjectileTargeting __instance) { if (!__instance.m_active && __instance.m_endLifeTime < Clock.Time) { ProjectileEvents.OnLifeTimeDone(__instance); } } } [HarmonyPatch(typeof(ScoutAntenna), "Init")] internal static class Inject_ScoutAntenna { [HarmonyWrapSafe] internal static void Postfix(ScoutAntennaDetection detection, ScoutAntenna __instance) { ScoutAntennaSpawnEvent.OnAntennaSpawn(detection.m_owner, detection, __instance); } } [HarmonyPatch(typeof(ScoutAntennaDetection), "OnSpawn")] internal static class Inject_ScoutAntennaDetection { [HarmonyWrapSafe] internal static void Prefix(pScoutAntennaDetectionSpawnData spawnData, ScoutAntennaDetection __instance) { EnemyAgent enemyAgent = default(EnemyAgent); if (((pEnemyAgent)(ref spawnData.owner)).TryGet(ref enemyAgent)) { ScoutAntennaSpawnEvent.OnDetectionSpawn(enemyAgent, __instance); } } } } namespace EEC.EnemyCustomizations { public abstract class EnemyCustomBase { private readonly Dictionary _isTargetLookup = new Dictionary(); public string DebugName { get; set; } = string.Empty; public bool Enabled { get; set; } = true; public TargetSetting Target { get; set; } = new TargetSetting(); [JsonIgnore] public IEnumerable TargetEnemyIDs => from x in _isTargetLookup where x.Value select x.Key; public EnemyCustomBase Base => this; public virtual void OnAssetLoaded() { } public virtual void OnConfigLoaded() { } public virtual void OnTargetIDLookupBuilt() { } public virtual void OnConfigUnloaded() { } public abstract string GetProcessName(); internal void RegisterTargetEnemyLookup(EnemyDataBlock enemyData) { if (Enabled) { uint persistentID = ((GameDataBlockBase)(object)enemyData).persistentID; if (!_isTargetLookup.ContainsKey(persistentID)) { _isTargetLookup.Add(persistentID, Target.IsMatch(enemyData)); } } } internal void ClearTargetLookup() { _isTargetLookup.Clear(); } public bool IsTarget(EnemyAgent enemyAgent) { return IsTarget(enemyAgent.EnemyDataID); } public bool IsTarget(uint id) { if (_isTargetLookup.TryGetValue(id, out var value)) { return value; } return false; } public void LogVerbose(string str) { LogFormatDebug(str, verbose: true); } public void LogDev(string str) { LogFormatDebug(str, verbose: false); } public void LogError(string str) { LogFormat((LogLevel)2, str); } public void LogWarning(string str) { LogFormat((LogLevel)4, str); } private void LogFormat(LogLevel level, string str) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); if (!string.IsNullOrEmpty(DebugName)) { ManualLogSource logInstance = Logger.LogInstance; LogLevel val = level; LogLevel val2 = val; BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(4, 3, val, ref flag); if (flag) { val3.AppendLiteral("["); val3.AppendFormatted(GetProcessName()); val3.AppendLiteral("-"); val3.AppendFormatted(DebugName); val3.AppendLiteral("] "); val3.AppendFormatted(str); } logInstance.Log(val2, val3); } else { ManualLogSource logInstance2 = Logger.LogInstance; LogLevel val2 = level; LogLevel val = val2; BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(3, 2, val2, ref flag); if (flag) { val3.AppendLiteral("["); val3.AppendFormatted(GetProcessName()); val3.AppendLiteral("] "); val3.AppendFormatted(str); } logInstance2.Log(val, val3); } } private void LogFormatDebug(string str, bool verbose) { string text = (string.IsNullOrEmpty(DebugName) ? ("[" + GetProcessName() + "]") : $"[{GetProcessName()}-{DebugName}]"); if (verbose) { Logger.Verbose(text + " " + str); } else { Logger.Debug(text + " " + str); } } } public sealed class TargetSetting { public TargetMode Mode { get; set; } public uint[] PersistentIDs { get; set; } = new uint[1]; public string NameParam { get; set; } = string.Empty; public bool NameIgnoreCase { get; set; } public string[] Categories { get; set; } = Array.Empty(); public bool IsMatch(uint enemyID) { EnemyDataBlock block = GameDataBlockBase.GetBlock(enemyID); return IsMatch(block); } public bool IsMatch(EnemyDataBlock enemyBlock) { if (enemyBlock == null) { return false; } return Mode switch { TargetMode.PersistentID => PersistentIDs.Contains(((GameDataBlockBase)(object)enemyBlock).persistentID), TargetMode.NameEquals => ((GameDataBlockBase)(object)enemyBlock).name?.InvariantEquals(NameParam, NameIgnoreCase) ?? false, TargetMode.NameContains => ((GameDataBlockBase)(object)enemyBlock).name?.InvariantContains(NameParam, NameIgnoreCase) ?? false, TargetMode.Everything => true, TargetMode.CategoryAny => ConfigManager.Categories.Any(Categories, ((GameDataBlockBase)(object)enemyBlock).persistentID), TargetMode.CategoryAll => ConfigManager.Categories.All(Categories, ((GameDataBlockBase)(object)enemyBlock).persistentID), _ => false, }; } public string ToDebugString() { return $"TargetDebug, Mode: {Mode}, persistentIDs: [{string.Join(", ", PersistentIDs)}], nameParam: {NameParam}, categories: [{string.Join(", ", Categories)}]"; } } public enum TargetMode { PersistentID, NameEquals, NameContains, Everything, CategoryAny, CategoryAll } public interface IEnemyAgentModeEvent : IEnemyEvent { void OnAgentModeChanged(EnemyAgent agent, AgentMode newMode); } public interface IEnemyDeadEvent : IEnemyEvent { void OnDead(EnemyAgent agent); } public interface IEnemyDespawnedEvent : IEnemyEvent { void OnDespawned(EnemyAgent agent); } public interface IEnemyEvent { EnemyCustomBase Base { get; } } public interface IEnemyGlowEvent : IEnemyEvent { bool OnGlow(EnemyAgent agent, ref GlowInfo glowInfo); } public struct GlowInfo { public Color Color; public Vector4 Position; public GlowInfo(Color color, Vector4 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Color = color; Position = position; } public GlowInfo ChangeColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return new GlowInfo(color, Position); } public GlowInfo ChangePosition(Vector4 position) { //IL_0001: 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) return new GlowInfo(Color, position); } } public interface IEnemyPrefabBuiltEvent : IEnemyEvent { void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData); } public interface IEnemySpawnedEvent : IEnemyEvent { void OnSpawned(EnemyAgent agent); } } namespace EEC.EnemyCustomizations._EnemyEvents { internal interface IEnemySpawn { } } namespace EEC.EnemyCustomizations.Strikers { public sealed class StrikerTentacleCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public sealed class TentacleSettingData { public eEasingType InEaseType { get; set; } = (eEasingType)20; public eEasingType OutEaseType { get; set; } = (eEasingType)16; public ValueBase InDuration { get; set; } = ValueBase.Unchanged; public ValueBase OutDuration { get; set; } = ValueBase.Unchanged; public ValueBase HangDuration { get; set; } = ValueBase.Unchanged; public ValueBase SplineWidthSafe { get; set; } = ValueBase.Unchanged; public ValueBase SplineWidthPos1 { get; set; } = ValueBase.Unchanged; public ValueBase SplineWidthPos2 { get; set; } = ValueBase.Unchanged; public ValueBase SplineHeightPos1 { get; set; } = ValueBase.Unchanged; public ValueBase SplineHeightPos2 { get; set; } = ValueBase.Unchanged; public Func GetInEaseFunction() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return InEaseType.GetEaseFunction(); } public Func GetOutEaseFunction() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return OutEaseType.GetEaseFunction(); } } public GPUCurvyType[] TentacleTypes { get; set; } = Array.Empty(); public TentacleSettingData[] TentacleSettings { get; set; } = Array.Empty(); public ValueBase MaxRange { get; set; } = ValueBase.Unchanged; public override string GetProcessName() { return "Tentacle"; } public void OnSpawned(EnemyAgent agent) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) Il2CppArrayBase componentsInChildren = ((Component)agent).GetComponentsInChildren(true); bool flag = TentacleTypes.Length != 0; bool flag2 = TentacleSettings.Length != 0; EAB_MovingEnemeyTentacle componentInChildren = ((Component)agent).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.m_absoluteMaxDistanceToHitTarget = MaxRange.GetAbsValue(componentInChildren.m_absoluteMaxDistanceToHitTarget); } for (int i = 0; i < componentsInChildren.Length; i++) { MovingEnemyTentacleBase val = componentsInChildren[i]; if (flag) { GPUCurvyType value = (val.m_GPUCurvyType = TentacleTypes[i % TentacleTypes.Length]); if (Logger.VerboseLogAllowed) { LogVerbose($" - Applied Tentacle Type!, index: {i} type: {value}"); } } if (flag2) { TentacleSettingData tentacleSettingData = TentacleSettings[i % TentacleSettings.Length]; val.m_easingIn = DelegateSupport.ConvertDelegate((Delegate)tentacleSettingData.GetInEaseFunction()); val.m_easingOut = DelegateSupport.ConvertDelegate((Delegate)tentacleSettingData.GetOutEaseFunction()); val.m_attackInDuration = tentacleSettingData.InDuration.GetAbsValue(val.m_attackInDuration); val.m_attackOutDuration = tentacleSettingData.OutDuration.GetAbsValue(val.m_attackOutDuration); val.m_attackHangDuration = tentacleSettingData.HangDuration.GetAbsValue(val.m_attackHangDuration); val.m_splineWidthSafe = tentacleSettingData.SplineWidthSafe.GetAbsValue(val.m_splineWidthSafe); val.m_splineWidthPos1 = tentacleSettingData.SplineWidthPos1.GetAbsValue(val.m_splineWidthPos1); val.m_splineWidthPos2 = tentacleSettingData.SplineWidthPos2.GetAbsValue(val.m_splineWidthPos2); val.m_splineHeightPos1 = tentacleSettingData.SplineHeightPos1.GetAbsValue(val.m_splineHeightPos1); val.m_splineHeightPos2 = tentacleSettingData.SplineHeightPos2.GetAbsValue(val.m_splineHeightPos2); if (Logger.VerboseLogAllowed) { LogVerbose($" - Applied Tentacle Setting!, index: {i}"); } } } } } } namespace EEC.EnemyCustomizations.Shooters { public sealed class ShooterFireCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent, IEnemyAgentModeEvent { public sealed class FireSetting { public float FromDistance { get; set; } = -1f; public bool OverrideProjectileType { get; set; } = true; public ProjectileType ProjectileType { get; set; } = (ProjectileType)2; public ValueBase BurstCount { get; set; } = ValueBase.Unchanged; public ValueBase BurstDelay { get; set; } = ValueBase.Unchanged; public ValueBase ShotDelayMin { get; set; } = ValueBase.Unchanged; public ValueBase ShotDelayMax { get; set; } = ValueBase.Unchanged; public ValueBase InitialFireDelay { get; set; } = ValueBase.Unchanged; public ValueBase ShotSpreadXMin { get; set; } = ValueBase.Unchanged; public ValueBase ShotSpreadXMax { get; set; } = ValueBase.Unchanged; public ValueBase ShotSpreadYMin { get; set; } = ValueBase.Unchanged; public ValueBase ShotSpreadYMax { get; set; } = ValueBase.Unchanged; public void ApplyToEAB(EAB_ProjectileShooter eab, ShooterFireOption defValue) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (OverrideProjectileType) { eab.m_type = ProjectileType; } eab.m_burstCount = BurstCount.GetAbsValue(defValue.burstCount); eab.m_burstDelay = BurstDelay.GetAbsValue(defValue.burstDelay); eab.m_shotDelayMin = ShotDelayMin.GetAbsValue(defValue.shotDelayMin); eab.m_shotDelayMax = ShotDelayMax.GetAbsValue(defValue.shotDelayMax); eab.m_initialFireDelay = InitialFireDelay.GetAbsValue(defValue.initialFireDelay); eab.m_shotSpreadX = new Vector2(ShotSpreadXMin.GetAbsValue(defValue.shotSpreadX.x), ShotSpreadXMax.GetAbsValue(defValue.shotSpreadX.y)); eab.m_shotSpreadY = new Vector2(ShotSpreadYMin.GetAbsValue(defValue.shotSpreadY.x), ShotSpreadYMax.GetAbsValue(defValue.shotSpreadY.y)); } } public FireSetting[] FireSettings { get; set; } = Array.Empty(); public override string GetProcessName() { return "ShooterFire"; } public override void OnConfigLoaded() { FireSettings = FireSettings.OrderByDescending((FireSetting f) => f.FromDistance).ToArray(); } public void OnSpawned(EnemyAgent agent) { EAB_ProjectileShooter componentInChildren = ((Component)agent).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { ShooterFireOption defValue = default(ShooterFireOption); defValue.CopyFrom(componentInChildren); if (FireSettings.Length == 1) { FireSettings[0].ApplyToEAB(componentInChildren, defValue); } } } public void OnAgentModeChanged(EnemyAgent agent, AgentMode newMode) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if (FireSettings.Length <= 1 || (int)newMode != 1) { return; } EAB_ProjectileShooter componentInChildren = ((Component)agent).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { ShooterFireOption shooterFireOption = default(ShooterFireOption); shooterFireOption.CopyFrom(componentInChildren); float distance = GetCurrentDistance(agent); FireSetting fireSetting = FireSettings.First((FireSetting x) => x.FromDistance <= distance); fireSetting.ApplyToEAB(componentInChildren, shooterFireOption); if (FireSettings.Length > 1) { ShooterDistSettingRoutine shooterDistSettingRoutine = new ShooterDistSettingRoutine(fireSetting) { EAB_Shooter = componentInChildren, DefaultValue = shooterFireOption, FireSettings = FireSettings }; ((MonoBehaviour)(object)agent.AI).StartCoroutine(shooterDistSettingRoutine.Routine()); } } } private float GetCurrentDistance(EnemyAgent agent) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (((AgentAI)agent.AI).IsTargetValid) { return ((AgentAI)agent.AI).Target.m_distance; } float fromDistance = FireSettings.First((FireSetting setting) => setting.FromDistance > 0f).FromDistance; float num = float.MaxValue; Enumerator enumerator = agent.AI.m_behaviourData.Targets.GetEnumerator(); while (enumerator.MoveNext()) { AgentTarget current = enumerator.Current; if (current.m_agent.Alive && num > current.m_distance && !Physics.Linecast(((Agent)agent).EyePosition, current.m_agent.EyePosition, LayerManager.MASK_WORLD)) { num = current.m_distance; if (num < fromDistance) { return num; } } } return num; } } public struct ShooterFireOption { public int burstCount; public float burstDelay; public float shotDelayMin; public float shotDelayMax; public float initialFireDelay; public Vector2 shotSpreadX; public Vector2 shotSpreadY; public void CopyFrom(EAB_ProjectileShooter eabShooter) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) burstCount = eabShooter.m_burstCount; burstDelay = eabShooter.m_burstDelay; shotDelayMin = eabShooter.m_shotDelayMin; shotDelayMax = eabShooter.m_shotDelayMax; initialFireDelay = eabShooter.m_initialFireDelay; shotSpreadX = eabShooter.m_shotSpreadX; shotSpreadY = eabShooter.m_shotSpreadY; } public void CopyTo(EAB_ProjectileShooter eabShooter) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) eabShooter.m_burstCount = burstCount; eabShooter.m_burstDelay = burstDelay; eabShooter.m_shotDelayMin = shotDelayMin; eabShooter.m_shotDelayMax = shotDelayMax; eabShooter.m_initialFireDelay = initialFireDelay; eabShooter.m_shotSpreadX = shotSpreadX; eabShooter.m_shotSpreadY = shotSpreadY; } } } namespace EEC.EnemyCustomizations.Shooters.Handlers { public sealed class ShooterDistSettingRoutine { [CompilerGenerated] private sealed class <>c__DisplayClass6_0 { public float distance; internal bool b__0(ShooterFireCustom.FireSetting x) { return x.FromDistance <= distance; } } [CompilerGenerated] private sealed class d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ShooterDistSettingRoutine <>4__this; private <>c__DisplayClass6_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 int num = <>1__state; ShooterDistSettingRoutine shooterDistSettingRoutine = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; ES_StateEnum currentStateEnum = ((EnemyAbility)shooterDistSettingRoutine.EAB_Shooter).m_owner.Locomotion.CurrentStateEnum; if ((int)currentStateEnum != 18 && (int)currentStateEnum != 30 && ((AgentAI)((EnemyAbility)shooterDistSettingRoutine.EAB_Shooter).m_owner.AI).IsTargetValid) { <>8__1.distance = ((AgentAI)((EnemyAbility)shooterDistSettingRoutine.EAB_Shooter).m_owner.AI).Target.m_distance; ShooterFireCustom.FireSetting fireSetting = shooterDistSettingRoutine.FireSettings.First((ShooterFireCustom.FireSetting x) => x.FromDistance <= <>8__1.distance); if (fireSetting != shooterDistSettingRoutine._currentSetting) { fireSetting.ApplyToEAB(shooterDistSettingRoutine.EAB_Shooter, shooterDistSettingRoutine.DefaultValue); shooterDistSettingRoutine._currentSetting = fireSetting; } <>8__1 = null; } } else { <>1__state = -1; } <>8__1 = new <>c__DisplayClass6_0(); <>2__current = _yielder; <>1__state = 1; return true; } 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 ShooterFireOption DefaultValue; public EAB_ProjectileShooter EAB_Shooter; public ShooterFireCustom.FireSetting[] FireSettings; private ShooterFireCustom.FireSetting _currentSetting; private static readonly WaitForSeconds _yielder = WaitFor.Seconds[0.125f]; public ShooterDistSettingRoutine(ShooterFireCustom.FireSetting startSetting = null) { _currentSetting = startSetting; } [IteratorStateMachine(typeof(d__6))] public IEnumerator Routine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0) { <>4__this = this }; } } } namespace EEC.EnemyCustomizations.Shared { public interface IBleedSetting { ValueBase Damage { get; set; } float ChanceToBleed { get; set; } float Interval { get; set; } float Duration { get; set; } bool HasLiquid { get; set; } bool CanBeStacked { get; set; } ScreenLiquidSettingName LiquidSetting { get; set; } uint OverrideBleedingTextID { get; set; } } public sealed class BleedSetting { public bool Enabled { get; set; } public ValueBase Damage { get; set; } = ValueBase.Zero; public float ChanceToBleed { get; set; } public float Interval { get; set; } public float Duration { get; set; } public bool HasLiquid { get; set; } = true; public bool CanBeStacked { get; set; } public ScreenLiquidSettingName LiquidSetting { get; set; } = (ScreenLiquidSettingName)2; public uint OverrideBleedingTextID { get; set; } public unsafe BleedingData ToPacket() { //IL_0064: 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_0069->IL0069: Incompatible stack types: Ref vs I4 //IL_0063->IL0069: Incompatible stack types: I4 vs Ref //IL_0063->IL0069: Incompatible stack types: Ref vs I4 BleedingData result = default(BleedingData); result.interval = Interval; result.duration = Duration; result.damage = Damage.GetAbsValue(PlayerData.MaxHealth); result.chanceToBleed = ChanceToBleed; result.doStack = CanBeStacked; ref BleedingData reference = ref result; int num; if (HasLiquid) { reference = ref *(BleedingData*)LiquidSetting; num = (int)(ref reference); } else { num = -1; reference = ref *(BleedingData*)num; num = (int)(ref reference); } Unsafe.Write(&((BleedingData*)num)->liquid, (ScreenLiquidSettingName)(ref reference)); result.textSpecialOverride = OverrideBleedingTextID; return result; } public void DoBleed(PlayerAgent agent) { BleedManager.DoBleed(agent, ToPacket()); } public static void StopBleed(PlayerAgent agent) { BleedManager.StopBleed(agent); } } public interface IDrainStaminaSetting { float DrainAmount { get; set; } float DrainAmountInCombat { get; set; } bool ResetRecoverTimer { get; set; } bool ResetRecoverTimerInCombat { get; set; } } public sealed class DrainStaminaSetting : IDrainStaminaSetting { public bool Enabled { get; set; } public float DrainAmount { get; set; } public float DrainAmountInCombat { get; set; } public bool ResetRecoverTimer { get; set; } public bool ResetRecoverTimerInCombat { get; set; } public DrainStaminaData ToPacket() { DrainStaminaData result = default(DrainStaminaData); result.amount = DrainAmount; result.amountInCombat = DrainAmountInCombat; result.resetRecover = ResetRecoverTimer; result.resetRecoverInCombat = ResetRecoverTimerInCombat; return result; } public void DoDrain(PlayerAgent agent) { DrainStaminaManager.DoDrain(agent, ToPacket()); } } public interface IEffectVolumeSetting { bool Enabled { get; set; } eEffectVolumeContents Contents { get; set; } eEffectVolumeModification Modification { get; set; } float Scale { get; set; } } public sealed class EffectVolumeSetting : IEffectVolumeSetting { public bool Enabled { get; set; } public eEffectVolumeContents Contents { get; set; } = (eEffectVolumeContents)2; public eEffectVolumeModification Modification { get; set; } public float Scale { get; set; } = 1f; public EV_Sphere CreateSphere(Vector3 position, float minRadius, float maxRadius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown return new EV_Sphere { position = position, minRadius = minRadius, maxRadius = maxRadius, modificationScale = Scale, invert = true, contents = Contents, modification = Modification }; } } public interface IExplosionSetting { ValueBase Damage { get; set; } Color LightColor { get; set; } bool KillInflictor { get; set; } float EnemyDamageMulti { get; set; } float MinRange { get; set; } float MaxRange { get; set; } ValueBase EnemyMinRange { get; set; } ValueBase EnemyMaxRange { get; set; } float NoiseMinRange { get; set; } float NoiseMaxRange { get; set; } NM_NoiseType NoiseType { get; set; } KnockbackSetting Knockback { get; set; } BleedSetting Bleed { get; set; } DrainStaminaSetting DrainStamina { get; set; } InfectionSetting Infection { get; set; } ExplosionData ToPacket(Vector3 position) { //IL_0082: 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_0118: Unknown result type (might be due to invalid IL or missing references) ExplosionData result = default(ExplosionData); result.damage = Damage.GetAbsValue(PlayerData.MaxHealth); result.enemyMulti = EnemyDamageMulti; result.minRange = MinRange; result.maxRange = MaxRange; result.enemyMinRange = EnemyMinRange.GetAbsValue(MinRange); result.enemyMaxRange = EnemyMaxRange.GetAbsValue(MaxRange); result.lightColor = LightColor; result.bleeding = new ExpBleedingData { enabled = Bleed.Enabled, packet = Bleed.ToPacket() }; result.drainStamina = new ExpDrainStaminaData { enabled = DrainStamina.Enabled, packet = DrainStamina.ToPacket() }; result.knockback = new ExpKnockbackData { enabled = Knockback.Enabled, packet = Knockback.ToPacket(position) }; result.infection = new ExpInfectionData { enabled = Infection.Enabled, packet = ((IInfectionSetting)Infection).ToPacket() }; return result; } } public sealed class ExplosionSetting : IExplosionSetting { public bool Enabled { get; set; } public ValueBase Damage { get; set; } = ValueBase.Zero; public Color LightColor { get; set; } = new Color(1f, 0.2f, 0f, 1f); public bool KillInflictor { get; set; } = true; public float EnemyDamageMulti { get; set; } = 1f; public float MinRange { get; set; } = 2f; public float MaxRange { get; set; } = 5f; public ValueBase EnemyMinRange { get; set; } = ValueBase.Unchanged; public ValueBase EnemyMaxRange { get; set; } = ValueBase.Unchanged; public float NoiseMinRange { get; set; } = 5f; public float NoiseMaxRange { get; set; } = 10f; public NM_NoiseType NoiseType { get; set; } = (NM_NoiseType)1; public KnockbackSetting Knockback { get; set; } = new KnockbackSetting(); public BleedSetting Bleed { get; set; } = new BleedSetting(); public DrainStaminaSetting DrainStamina { get; set; } = new DrainStaminaSetting(); public InfectionSetting Infection { get; set; } = new InfectionSetting(); } public static class ExplosionExtension { public static void TryKillInflictor(this IExplosionSetting setting, Agent inflictor) { //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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (setting.KillInflictor) { PlayerAgent playerAgent; if (inflictor.TryCastToEnemyAgent(out EnemyAgent enemyAgent)) { Dam_EnemyDamageBase damage = enemyAgent.Damage; damage.ExplosionDamage(((Dam_SyncedDamageBase)damage).HealthMax, Vector3.zero, Vector3.zero, 0, 0u); } else if (inflictor.TryCastToPlayerAgent(out playerAgent)) { Dam_PlayerDamageBase damage2 = playerAgent.Damage; ((Dam_SyncedDamageBase)damage2).ExplosionDamage(((Dam_SyncedDamageBase)damage2).HealthMax, Vector3.zero, Vector3.zero, 0u); } } } public static void DoExplode(this IExplosionSetting setting, Agent from, bool useRagdoll = false, bool useClientPos = true) { //IL_0001: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Vector3 position = from.EyePosition; if (useRagdoll) { from.GetRagdollPosition(ref position); } if (useClientPos) { setting.MakeExplosion(from, useRagdoll); } else { setting.MakeExplosion(position); } setting.MakeNoise(from.CourseNode, position); } public static void DoLocalExplode(this IExplosionSetting setting, Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) setting.MakeLocalExplosion(position); if (SNet.IsMaster) { setting.TryMakeNoise(position); } } public static void MakeExplosion(this IExplosionSetting setting, Agent agent, bool useRagdoll = false) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (setting.Damage.GetAbsValue(PlayerData.MaxHealth) != 0f) { ExplosionAgentData explosionAgentData = default(ExplosionAgentData); explosionAgentData.useRagdoll = useRagdoll; explosionAgentData.data = setting.ToPacket(agent.Position); ExplosionAgentData data = explosionAgentData; ((pAgent)(ref data.agent)).Set(agent); ExplosionManager.DoExplosion(data); } } public static void MakeExplosion(this IExplosionSetting setting, Vector3 position) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (setting.Damage.GetAbsValue(PlayerData.MaxHealth) != 0f) { ExplosionPosData data = default(ExplosionPosData); data.position = position; data.data = setting.ToPacket(position); ExplosionManager.DoExplosion(data); } } public static void MakeLocalExplosion(this IExplosionSetting setting, Vector3 position) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (setting.Damage.GetAbsValue(PlayerData.MaxHealth) != 0f) { ExplosionPosData data = default(ExplosionPosData); data.position = position; data.data = setting.ToPacket(position); ExplosionManager.DoLocalExplosion(data); } } public static void TryMakeNoise(this IExplosionSetting setting, Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = position; AIG_CourseNode node = default(AIG_CourseNode); if (PhysicsUtil.SlamPos(ref val, Vector3.down, 64f, LayerManager.MASK_LEVELGEN, false, 0f, 0f) && AIG_GeomorphNodeVolume.TryGetCourseNode(Dimension.GetDimensionFromPos(val).DimensionIndex, val, ref node)) { setting.MakeNoise(node, position); } } public static void MakeNoise(this IExplosionSetting setting, AIG_CourseNode node, Vector3 position) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown if (node != null) { NoiseManager.MakeNoise(new NM_NoiseData { noiseMaker = null, position = position, radiusMin = setting.NoiseMinRange, radiusMax = setting.NoiseMaxRange, yScale = 1f, node = node, type = setting.NoiseType, includeToNeightbourAreas = true, raycastFirstNode = false }); } } } public static class SpawnProjectileExtension { public struct SpawnProjectileData { public Agent Target; public Transform Align; public Vector3 LastSavedPosition; public bool KeepTrackAlign; public Vector3 BaseDirection; public ushort OwnerID; public Vector3 UpVector; public Vector3 RightVector; public Vector3 Position { get { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (KeepTrackAlign && (Object)(object)Align != (Object)null) { return Align.position; } return LastSavedPosition; } } } [CompilerGenerated] private sealed class d__1 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SpawnProjectileData data; public ISpawnProjectileSetting setting; private bool 5__2; private bool 5__3; private int 5__4; private bool 5__5; private int 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((Object)(object)data.Align == (Object)null) { return false; } 5__2 = setting.Delay > 0f; 5__3 = setting.BurstCount > 1; 5__4 = 0; goto IL_016b; case 1: <>1__state = -1; goto IL_00f2; case 2: { <>1__state = -1; goto IL_015b; } IL_0102: if (5__6 <= setting.BurstCount) { Spawn(setting, data); if (5__5 && 5__6 < setting.BurstCount) { <>2__current = WaitFor.Seconds[setting.BurstDelay]; <>1__state = 1; return true; } goto IL_00f2; } goto IL_0128; IL_0128: if (5__2) { <>2__current = WaitFor.Seconds[setting.Delay]; <>1__state = 2; return true; } goto IL_015b; IL_016b: if (5__4 < setting.Count) { if (5__3) { 5__5 = setting.BurstDelay > 0f; 5__6 = 1; goto IL_0102; } Spawn(setting, data); goto IL_0128; } return false; IL_015b: 5__4++; goto IL_016b; IL_00f2: 5__6++; goto IL_0102; } } 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 Coroutine DoSpawn(this ISpawnProjectileSetting setting, EnemyAgent owner, Agent target, Transform fireAlign, bool keepTrack) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) Vector3 baseDirection = (setting.BackwardDirection ? (-fireAlign.forward) : fireAlign.forward); return InLevelCoroutine.Start(SpawnProjectiles(setting, new SpawnProjectileData { Target = target, Align = fireAlign, LastSavedPosition = fireAlign.position, KeepTrackAlign = keepTrack, BaseDirection = baseDirection, OwnerID = ((Agent)owner).GlobalID, UpVector = fireAlign.up, RightVector = fireAlign.right })); } [IteratorStateMachine(typeof(d__1))] private static IEnumerator SpawnProjectiles(ISpawnProjectileSetting setting, SpawnProjectileData data) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(0) { setting = setting, data = data }; } private static void Spawn(ISpawnProjectileSetting setting, SpawnProjectileData data) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) float num = Rand.Range(setting.ShotSpreadXMin, setting.ShotSpreadXMax); float num2 = Rand.Range(setting.ShotSpreadYMin, setting.ShotSpreadYMax); Vector3 val = Quaternion.LookRotation(data.BaseDirection) * Quaternion.AngleAxis(num2, data.UpVector) * Quaternion.AngleAxis(num, data.RightVector) * Vector3.forward; ProjectileManager.WantToFireTargeting(setting.ProjectileType, data.Target, data.Position, val, (int)data.OwnerID, 0f); } } public interface IInfectionSetting { ValueBase Infection { get; set; } uint SoundEventID { get; set; } bool UseEffect { get; set; } float ScreenLiquidRange { get; set; } InfectionData ToPacket() { InfectionData result = default(InfectionData); result.infection = Infection.GetAbsValue(PlayerData.MaxInfection); result.soundEventID = SoundEventID; result.useEffect = UseEffect; result.screenLiquidRange = ScreenLiquidRange; return result; } } public sealed class InfectionSetting : IInfectionSetting { public bool Enabled { get; set; } public ValueBase Infection { get; set; } = ValueBase.Zero; public uint SoundEventID { get; set; } public bool UseEffect { get; set; } public float ScreenLiquidRange { get; set; } } public interface IKnockbackSetting { float Velocity { get; set; } float VelocityZ { get; set; } bool DoMultDistance { get; set; } bool DoMultDistanceZ { get; set; } } public sealed class KnockbackSetting : IKnockbackSetting { public bool Enabled { get; set; } public float Velocity { get; set; } public float VelocityZ { get; set; } public bool DoMultDistance { get; set; } public bool DoMultDistanceZ { get; set; } public KnockbackData ToPacket(Vector3 inflictorPos) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) KnockbackData result = default(KnockbackData); result.inflictorPos = inflictorPos; result.velocity = Velocity; result.velocityZ = VelocityZ; result.doMultDistance = DoMultDistance; result.doMultDistanceZ = DoMultDistanceZ; return result; } public void DoKnockback(Agent inflictor, PlayerAgent player) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DoKnockback(inflictor.Position, player); } public void DoKnockback(Vector3 inflictorPos, PlayerAgent player) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) KnockbackManager.DoKnockback(player, ToPacket(inflictorPos)); } public void DoKnockbackIgnoreDistance(Agent inflictor, PlayerAgent player) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DoKnockbackIgnoreDistance(inflictor.Position, player); } public void DoKnockbackIgnoreDistance(Vector3 inflictorPos, PlayerAgent player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) KnockbackData data = ToPacket(inflictorPos); data.doMultDistance = false; data.doMultDistanceZ = false; KnockbackManager.DoKnockback(player, data); } } public enum RepeatMode { Clamped, Unclamped, PingPong, Repeat } public interface IMultiplierShiftSetting { float MinMulti { get; set; } float MaxMulti { get; set; } float Duration { get; set; } bool StopAfterDuration { get; set; } float StopMulti { get; set; } eEasingType EasingMode { get; set; } RepeatMode Mode { get; set; } } public sealed class MultiplierShiftSetting : IMultiplierShiftSetting { public bool Enabled { get; set; } public float MinMulti { get; set; } = 1f; public float MaxMulti { get; set; } = 1f; public float Duration { get; set; } = 1f; public bool StopAfterDuration { get; set; } = true; public float StopMulti { get; set; } = 1f; public eEasingType EasingMode { get; set; } public RepeatMode Mode { get; set; } public float EvaluateMultiplier(float progress) { return Mode switch { RepeatMode.Unclamped => Mathf.LerpUnclamped(MinMulti, MaxMulti, Ease(progress)), RepeatMode.PingPong => Mathf.Lerp(MinMulti, MaxMulti, Ease(Mathf.PingPong(progress, 1f))), RepeatMode.Repeat => Mathf.Lerp(MinMulti, MaxMulti, Ease(Mathf.Repeat(progress, 1f))), _ => Mathf.LerpUnclamped(MinMulti, MaxMulti, Mathf.Clamp01(Ease(progress))), }; } private float Ease(float p) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Easing.GetEasingValue(EasingMode, p, false); } } public interface ISpawnProjectileSetting { ProjectileType ProjectileType { get; set; } bool BackwardDirection { get; set; } int Count { get; set; } int BurstCount { get; set; } float Delay { get; set; } float BurstDelay { get; set; } float ShotSpreadXMin { get; set; } float ShotSpreadXMax { get; set; } float ShotSpreadYMin { get; set; } float ShotSpreadYMax { get; set; } } public sealed class SpawnProjectileSetting : ISpawnProjectileSetting { public bool Enabled { get; set; } public ProjectileType ProjectileType { get; set; } public bool BackwardDirection { get; set; } public int Count { get; set; } = 1; public int BurstCount { get; set; } = 1; public float Delay { get; set; } = 0.1f; public float BurstDelay { get; set; } = 0.05f; public float ShotSpreadXMin { get; set; } public float ShotSpreadXMax { get; set; } public float ShotSpreadYMin { get; set; } public float ShotSpreadYMax { get; set; } public Coroutine DoSpawn(EnemyAgent owner, Agent target, Transform fireAlign, bool keepTrack) { if (!Enabled) { return null; } if (!SNet.IsMaster) { return null; } return SpawnProjectileExtension.DoSpawn(this, owner, target, fireAlign, keepTrack); } } } namespace EEC.EnemyCustomizations.Shared.Handlers { [InjectToIl2Cpp] internal sealed class EffectFogSphereHandler : MonoBehaviour { public FogSphereHandler Handler; public EV_Sphere EVSphere; private Timer _updateTimer = new Timer(0.1f); private bool _updatedOnce; private void Update() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (Handler.m_sphere != null && _updateTimer.TickAndCheckDone()) { FogSphere sphere = Handler.m_sphere; float num = Mathf.Sqrt(1f / sphere.m_data.InvRangeSqr); EVSphere.minRadius = num * 0.8f; EVSphere.maxRadius = num; _updateTimer.Reset(); _updatedOnce = true; } if (Handler.m_sphere == null && _updatedOnce) { Object.Destroy((Object)(object)this); } } private void OnDestroy() { EffectVolumeManager.UnregisterVolume((EffectVolume)(object)EVSphere); Handler = null; EVSphere = null; } } } namespace EEC.EnemyCustomizations.Properties { public enum RoarSoundOverride : byte { Striker, Shooter, Birther, Shadow, Tank, Flyer, Immortal, Bullrush, Pouncer, Striker_Berserk, Shooter_Spread, None, OldDistantRoar, Custom, CustomDynamic } public enum RoarSizeOverride : byte { Unchanged, Small, Medium, Big } public sealed class DistantRoarCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public class RoarData { public DistantRoarCustom RoarSettings { get; set; } = new DistantRoarCustom(); public uint SwitchID { get; set; } public byte EnemyType { get; set; } public bool IsInWave { get; set; } } private float _timer; private CellSoundPlayer? _soundPlayer; private static readonly Dictionary _waveRoars = new Dictionary { { "Striker", SWITCH.STRIKER }, { "Shooter", SWITCH.SHOOTER }, { "Bullrush", SWITCH.BULLRUSHER }, { "Shadow", SWITCH.SHADOW }, { "Flyer", SWITCH.FLYER }, { "Tank", SWITCH.TANK }, { "Birther", SWITCH.BIRTHER }, { "Pouncer", SWITCH.POUNCER }, { "Immortal", SWITCH.IMMORTAL }, { "Striker_Berserk", SWITCH.STRIKER_BERSERK }, { "Shooter_Spread", SWITCH.SHOOTER_SPREAD }, { "None", 11u }, { "OldDistantRoar", 12u }, { "Custom", 13u }, { "CustomDynamic", 14u } }; [JsonIgnore] public static Dictionary SharedRoarData { get; internal set; } = new Dictionary(); public uint SoundID { get; set; } public float Interval { get; set; } public bool OnlyForSurvivalWave { get; set; } = true; public bool IsGlobal { get; set; } = true; public bool OnlyUseOverrides { get; set; } public RoarSoundOverride RoarSound { get; set; } public List DynamicSoundIDs { get; set; } = new List(); public RoarSizeOverride RoarSize { get; set; } public BoolBase IsOutside { get; set; } = BoolBase.Unchanged; public override string GetProcessName() { return "DistantRoar"; } public override void OnAssetLoaded() { //IL_0001: 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_0010: Expected O, but got Unknown _soundPlayer = new CellSoundPlayer(Vector3.zero); } public override void OnConfigLoaded() { SharedRoarData.Clear(); if (ConfigManager.Global.AddUnusedVanillaRoars) { SharedRoarData = new Dictionary { { 46u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Pouncer, OnlyUseOverrides = true }, SwitchID = SWITCH.POUNCER, EnemyType = 8 } }, { 47u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Immortal, OnlyUseOverrides = true }, SwitchID = SWITCH.IMMORTAL, EnemyType = 6 } }, { 55u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Birther, OnlyUseOverrides = true }, SwitchID = SWITCH.BIRTHER, EnemyType = 2 } }, { 53u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Striker_Berserk, OnlyUseOverrides = true }, SwitchID = SWITCH.STRIKER_BERSERK, EnemyType = 9 } }, { 62u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Striker_Berserk, OnlyUseOverrides = true }, SwitchID = SWITCH.STRIKER_BERSERK, EnemyType = 9 } }, { 63u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Striker_Berserk, OnlyUseOverrides = true }, SwitchID = SWITCH.STRIKER_BERSERK, EnemyType = 9 } }, { 52u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Shooter_Spread, OnlyUseOverrides = true }, SwitchID = SWITCH.SHOOTER_SPREAD, EnemyType = 10 } }, { 56u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.Shooter_Spread, OnlyUseOverrides = true }, SwitchID = SWITCH.SHOOTER_SPREAD, EnemyType = 10 } }, { 44u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.None, OnlyUseOverrides = true }, SwitchID = 11u, EnemyType = 11 } }, { 61u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.None, OnlyUseOverrides = true }, SwitchID = 11u, EnemyType = 11 } }, { 58u, new RoarData { RoarSettings = new DistantRoarCustom { RoarSound = RoarSoundOverride.None, OnlyUseOverrides = true }, SwitchID = 11u, EnemyType = 11 } } }; } } public override void OnTargetIDLookupBuilt() { foreach (uint targetEnemyID in base.TargetEnemyIDs) { if (_waveRoars.TryGetValue(RoarSound.ToString(), out var value)) { SharedRoarData[targetEnemyID] = new RoarData { RoarSettings = this, SwitchID = value, EnemyType = (byte)RoarSound }; } } } public override void OnConfigUnloaded() { CellSoundPlayer? soundPlayer = _soundPlayer; if (soundPlayer != null) { soundPlayer.Recycle(); } _soundPlayer = null; SharedRoarData.Clear(); } public void OnSpawned(EnemyAgent agent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (!OnlyUseOverrides && agent.TryGetSpawnData(out var spawnData) && (int)spawnData.mode == 1 && (!OnlyForSurvivalWave || (agent.TryGetEnemyGroup(out EnemyGroup group) && !((Object)(object)group.SurvivalWave == (Object)null))) && _timer <= Clock.Time) { if (_soundPlayer != null) { _soundPlayer.UpdatePosition(agent.Position); _soundPlayer.Post(SoundID, IsGlobal); } _timer = Clock.Time + Interval; } } } public sealed class EventsCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent, IEnemyDeadEvent, IEnemyAgentModeEvent { public sealed class EventSetting { public bool Enabled { get; set; } public EventWrapper[] Events { get; set; } = Array.Empty(); public void CacheAll() { if (Events != null) { EventWrapper[] events = Events; for (int i = 0; i < events.Length; i++) { events[i].Cache(); } } } public void FireEvents() { if (Events != null) { EventWrapper[] events = Events; for (int i = 0; i < events.Length; i++) { WardenObjectiveManager.CheckAndExecuteEventsOnTrigger(events[i].ToEvent(), (eWardenObjectiveEventTrigger)0, true, 0f); } } } public void DisposeAll() { if (Events != null) { EventWrapper[] events = Events; for (int i = 0; i < events.Length; i++) { events[i].Dispose(); } Events = null; } } } public EventSetting OnSpawnedEvent { get; set; } = new EventSetting(); public EventSetting OnWakeupEvent { get; set; } = new EventSetting(); public EventSetting OnDeadEvent { get; set; } = new EventSetting(); public List LevelLayoutIDs { get; set; } = new List(); public bool TriggerOnBossDeathEventOnDead { get; set; } public override string GetProcessName() { return "Events"; } public override void OnAssetLoaded() { OnSpawnedEvent.CacheAll(); OnWakeupEvent.CacheAll(); OnDeadEvent.CacheAll(); } public override void OnConfigUnloaded() { OnSpawnedEvent.DisposeAll(); OnWakeupEvent.DisposeAll(); OnDeadEvent.DisposeAll(); } public void OnSpawned(EnemyAgent agent) { if (LevelLayoutIDs.Count > 0 && !LevelLayoutIDs.Contains(RundownManager.ActiveExpedition.LevelLayoutData)) { return; } EventSetting onSpawnedEvent = OnSpawnedEvent; if (onSpawnedEvent != null && onSpawnedEvent.Enabled) { OnSpawnedEvent.FireEvents(); } if (!TriggerOnBossDeathEventOnDead) { return; } AIG_CourseNode spawnedNode = agent.GetSpawnedNode(); if (spawnedNode == null || (Object)(object)spawnedNode.m_zone == (Object)null || spawnedNode.m_zone.m_settings == null) { return; } LG_ZoneSettings settings = spawnedNode.m_zone.m_settings; List events = ((settings != null) ? settings.m_zoneData.EventsOnBossDeath : null) ?? null; if (events != null) { agent.AddOnDeadOnce(delegate { WardenObjectiveManager.CheckAndExecuteEventsOnTrigger(events, (eWardenObjectiveEventTrigger)0, true, 0f, (Il2CppStructArray)null); }); } } public void OnAgentModeChanged(EnemyAgent agent, AgentMode newMode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)newMode == 1 && (LevelLayoutIDs.Count <= 0 || LevelLayoutIDs.Contains(RundownManager.ActiveExpedition.LevelLayoutData))) { EventSetting onWakeupEvent = OnWakeupEvent; if (onWakeupEvent != null && onWakeupEvent.Enabled) { OnWakeupEvent.FireEvents(); } } } public void OnDead(EnemyAgent agent) { if (LevelLayoutIDs.Count <= 0 || LevelLayoutIDs.Contains(RundownManager.ActiveExpedition.LevelLayoutData)) { EventSetting onDeadEvent = OnDeadEvent; if (onDeadEvent != null && onDeadEvent.Enabled) { OnDeadEvent.FireEvents(); } } } } public sealed class SpawnCostCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public float SpawnCost { get; set; } public override string GetProcessName() { return "SpawnCost"; } public void OnSpawned(EnemyAgent agent) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected I4, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) agent.m_enemyCost = SpawnCost; if ((int)((AgentAI)agent.AI).Mode == 1) { float num = ((Il2CppArrayBase)(object)EnemyCostManager.Current.m_enemyTypeCosts)[(int)agent.EnemyData.EnemyType] - SpawnCost; EnemyCostManager.AddCost(((Agent)agent).DimensionIndex, 0f - num); if (Logger.DevLogAllowed) { LogDev($"Decremented cost by {num}!"); } } else if (Logger.DevLogAllowed) { LogDev($"Set Enemy Cost to {SpawnCost}!"); } } } } namespace EEC.EnemyCustomizations.Properties.Inject { [HarmonyPatch(typeof(LG_LevelInteractionManager), "DoSetWaveRoarSoundInformation")] internal static class Inject_DoSetWaveRoar { [HarmonyPrefix] [HarmonyWrapSafe] private static bool Pre_DoSetWaveRoarSound(pWaveRoarSettings settings) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) if (!TryCondense(settings.enemyType, out DistantRoarCustom largest)) { return true; } CellSoundPlayer val = new CellSoundPlayer(); int num = ((largest.RoarSize == RoarSizeOverride.Unchanged) ? ((int)settings.roarSize) : ((int)largest.RoarSize)); byte enemyType = settings.enemyType; if (enemyType >= 11) { switch (enemyType) { case 12: val.PostWithCleanup((num < 3) ? EVENTS.DISTANT_ROAR_MEDIUM : EVENTS.DISTANT_ROAR_LARGE, settings.position); return false; case 13: val.PostWithCleanup(largest.SoundID, settings.position); return false; case 14: { int count = largest.DynamicSoundIDs.Count; if (count >= 1 && count <= 3) { val.PostWithCleanup(largest.DynamicSoundIDs[Math.Clamp(num - 1, 0, largest.DynamicSoundIDs.Count - 1)], settings.position); return false; } break; } } return settings.enemyType != 11; } CellSoundPlayer val2 = val; uint gROUP = ENEMY_TYPE.GROUP; val2.SetSwitch(gROUP, settings.enemyType switch { 0 => SWITCH.STRIKER, 1 => SWITCH.SHOOTER, 2 => SWITCH.BIRTHER, 3 => SWITCH.SHADOW, 4 => SWITCH.TANK, 5 => SWITCH.FLYER, 6 => SWITCH.IMMORTAL, 7 => SWITCH.BULLRUSHER, 8 => SWITCH.POUNCER, 9 => SWITCH.STRIKER_BERSERK, 10 => SWITCH.SHOOTER_SPREAD, _ => 0u, }); val2 = val; uint gROUP2 = ROAR_SIZE.GROUP; val2.SetSwitch(gROUP2, num switch { 1 => SWITCH.SMALL, 2 => SWITCH.MEDIUM, 3 => SWITCH.BIG, _ => 0u, }); val.SetSwitch(ENVIROMENT.GROUP, largest.IsOutside.GetValue(settings.isOutside) ? SWITCH.DESERT : SWITCH.COMPLEX); val.PostWithCleanup(EVENTS.PLAY_WAVE_DISTANT_ROAR, settings.position); return false; } private static bool TryCondense(byte enemyType, [NotNullWhen(true)] out DistantRoarCustom? largest) { List> list = DistantRoarCustom.SharedRoarData.Where>((KeyValuePair entry) => entry.Value.EnemyType == enemyType && entry.Value.IsInWave).ToList(); if (!list.Any()) { largest = null; return false; } foreach (KeyValuePair item in list) { item.Value.IsInWave = false; } largest = list.OrderByDescending((KeyValuePair entry) => entry.Value.RoarSettings.RoarSize).FirstOrDefault().Value.RoarSettings; return largest != null; } } [HarmonyPatch] internal static class Inject_EnemyGroup { [HarmonyPatch(typeof(EnemyGroup), "TryGetAKSwitchIDFromEnemyType")] [HarmonyPrefix] [HarmonyWrapSafe] private static bool OverrideSwitchID(ref bool __result, EnemyAgent agent, out uint switchID) { switchID = 0u; if (DistantRoarCustom.SharedRoarData.TryGetValue(((GameDataBlockBase)(object)agent.EnemyData).persistentID, out DistantRoarCustom.RoarData value)) { switchID = value.SwitchID; value.IsInWave = true; __result = true; } return switchID == 0; } [HarmonyPatch(typeof(EnemyGroup), "GetByteFromEnemyType")] [HarmonyPrefix] [HarmonyWrapSafe] private static bool AppendAKEnemyTypes(ref byte __result, uint enemyType) { if (enemyType == SWITCH.POUNCER) { __result = 8; return false; } if (enemyType == SWITCH.STRIKER_BERSERK) { __result = 9; return false; } if (enemyType == SWITCH.SHOOTER_SPREAD) { __result = 10; return false; } if (enemyType >= 11 && enemyType <= 14) { __result = (byte)enemyType; return false; } return true; } } } namespace EEC.EnemyCustomizations.Models { public class AnimHandleCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public ValueBase TentacleAttackWindUpLen { get; set; } = ValueBase.Unchanged; public ValueBase JumpMoveSpeed { get; set; } = ValueBase.Unchanged; public ValueBase JumpLandLen { get; set; } = ValueBase.Unchanged; public ValueBase JumpStartLen { get; set; } = ValueBase.Unchanged; public BoolBase AllowMelee180 { get; set; } = BoolBase.Unchanged; public BoolBase NeedsArmsToMove { get; set; } = BoolBase.Unchanged; public BoolBase TwitchHit { get; set; } = BoolBase.Unchanged; public ValueBase StrafeRunSpeed { get; set; } = ValueBase.Unchanged; public ValueBase StrafeWalkSpeed { get; set; } = ValueBase.Unchanged; public ValueBase InPlayerRoomSpeed { get; set; } = ValueBase.Unchanged; public ValueBase RunSpeed { get; set; } = ValueBase.Unchanged; public ValueBase WalkSpeed { get; set; } = ValueBase.Unchanged; public ValueBase ClimbSpeed { get; set; } = ValueBase.Unchanged; public MeleeAttackData MeleeAttackFwd { get; set; } = new MeleeAttackData(); public MeleeAttackData MeleeAttackBwd { get; set; } = new MeleeAttackData(); public override string GetProcessName() { return "AnimHandle"; } public void OnSpawned(EnemyAgent agent) { //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) AnimatorControllerHandle animHandle = agent.Locomotion.AnimHandle; animHandle.TentacleAttackWindUpLen = TentacleAttackWindUpLen.GetAbsValue(animHandle.TentacleAttackWindUpLen); animHandle.JumpMoveSpeed = JumpMoveSpeed.GetAbsValue(animHandle.JumpMoveSpeed); animHandle.JumpLandLen = JumpLandLen.GetAbsValue(animHandle.JumpLandLen); animHandle.JumpStartLen = JumpStartLen.GetAbsValue(animHandle.JumpStartLen); animHandle.AllowMelee180 = AllowMelee180.GetValue(animHandle.AllowMelee180); animHandle.NeedsArmsToMove = NeedsArmsToMove.GetValue(animHandle.NeedsArmsToMove); animHandle.TwitchHit = TwitchHit.GetValue(animHandle.TwitchHit); animHandle.StrafeRunSpeed = StrafeRunSpeed.GetAbsValue(animHandle.StrafeRunSpeed); animHandle.StrafeWalkSpeed = StrafeWalkSpeed.GetAbsValue(animHandle.StrafeWalkSpeed); animHandle.InPlayerRoomSpeed = InPlayerRoomSpeed.GetAbsValue(animHandle.InPlayerRoomSpeed); animHandle.RunSpeed = RunSpeed.GetAbsValue(animHandle.RunSpeed); animHandle.WalkSpeed = WalkSpeed.GetAbsValue(animHandle.WalkSpeed); animHandle.ClimbSpeed = ClimbSpeed.GetAbsValue(animHandle.ClimbSpeed); animHandle.MeleeAttackFwd = MeleeAttackFwd.GetData(animHandle.MeleeAttackFwd); animHandle.MeleeAttackBwd = MeleeAttackBwd.GetData(animHandle.MeleeAttackBwd); agent.RegisterOrGetProperty().TentacleAttackSpeedAdjustmentMult = agent.Locomotion.AnimHandle.TentacleAttackWindUpLen / animHandle.TentacleAttackWindUpLen; agent.Locomotion.AnimHandle = animHandle; } } public sealed class MeleeAttackData { public ValueBase Duration { get; set; } = ValueBase.Unchanged; public ValueBase DamageStart { get; set; } = ValueBase.Unchanged; public ValueBase DamageEnd { get; set; } = ValueBase.Unchanged; public bool ChangeSFX { get; set; } public uint SFXId { get; set; } public MeleeAttackTimingData GetData(MeleeAttackTimingData original) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) MeleeAttackTimingData result = default(MeleeAttackTimingData); result.Duration = Duration.GetAbsValue(original.Duration); result.DamageStart = DamageStart.GetAbsValue(original.DamageStart); result.DamageEnd = DamageEnd.GetAbsValue(original.DamageEnd); result.SFXId = (ChangeSFX ? SFXId : original.SFXId); return result; } } internal sealed class TentacleAttackSpeedProperty { public float TentacleAttackSpeedAdjustmentMult; } public sealed class BoneCustom : EnemyCustomBase, IEnemyPrefabBuiltEvent, IEnemyEvent { public sealed class BoneTransform { public HumanBodyBones Bone { get; set; } = (HumanBodyBones)10; public bool UsingRelativeScale { get; set; } public Vector3 Scale { get; set; } = Vector3.zero; public Vector3 Offset { get; set; } = Vector3.zero; public Vector3 RotationOffset { get; set; } = Vector3.zero; } public sealed class BonePrefab { public HumanBodyBones Bone { get; set; } = (HumanBodyBones)10; public string Prefab { get; set; } = string.Empty; public Vector3 Scale { get; set; } = Vector3.zero; public Vector3 Position { get; set; } = Vector3.zero; public Vector3 Rotation { get; set; } = Vector3.zero; } public BoneTransform[] Bones { get; set; } = Array.Empty(); public BonePrefab[] Prefabs { get; set; } = Array.Empty(); public override string GetProcessName() { return "Bone"; } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { BoneTransform[] bones = Bones; foreach (BoneTransform boneTransform in bones) { TryApplyBoneTransform(agent, boneTransform); } BonePrefab[] prefabs = Prefabs; foreach (BonePrefab bonePrefab in prefabs) { TryApplyBonePrefab(agent, bonePrefab); } } private void TryApplyBoneTransform(EnemyAgent agent, BoneTransform boneTransform) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00bf: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) try { Animator component = ((Component)agent).GetComponent(); Transform boneTransform2 = component.GetBoneTransform(boneTransform.Bone); if (boneTransform.Offset != Vector3.zero || boneTransform.Offset != Vector3.zero) { BoneOffsetHandler boneOffsetHandler = ((Component)boneTransform2).gameObject.AddComponent(); boneOffsetHandler.Animator = Il2CppReferenceField.op_Implicit(component); boneOffsetHandler.Offset = Il2CppValueField.op_Implicit(boneTransform.Offset); boneOffsetHandler.RotationOffset = Il2CppValueField.op_Implicit(boneTransform.RotationOffset); } if (boneTransform.UsingRelativeScale) { Vector3 val = default(Vector3); val.x = boneTransform2.localScale.x * boneTransform.Scale.x; val.y = boneTransform2.localScale.y * boneTransform.Scale.y; val.z = boneTransform2.localScale.z * boneTransform.Scale.z; Vector3 localScale = val; boneTransform2.localScale = localScale; } else { boneTransform2.localScale = boneTransform.Scale; } if (Logger.VerboseLogAllowed) { LogVerbose($"Applied Bone Setting: {((Object)boneTransform2).name}, offset: {boneTransform.Offset}, scale: {boneTransform.Scale} rotationOffset: {boneTransform.RotationOffset}"); } } catch (Exception value) { LogError($"Bone Transform owner: [{((Object)agent).name}] bone: [{boneTransform.Bone}] were not set! : {value}"); } } private void TryApplyBonePrefab(EnemyAgent agent, BonePrefab bonePrefab) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0088: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) try { Transform boneTransform = agent.Anim.GetBoneTransform(bonePrefab.Bone); if ((Object)(object)boneTransform == (Object)null) { throw new NullReferenceException("Bone is missing in prefab!"); } Object loadedAsset = AssetAPI.GetLoadedAsset(bonePrefab.Prefab); if (loadedAsset == (Object)null) { throw new NullReferenceException("Prefab '" + bonePrefab.Prefab + "' is missing!"); } GameObject obj = ((Il2CppObjectBase)Object.Instantiate(loadedAsset, boneTransform)).Cast(); obj.transform.localPosition = bonePrefab.Position; obj.transform.localEulerAngles = bonePrefab.Rotation; obj.transform.localScale = bonePrefab.Scale; LogVerbose($"Attached Bone Prefab: {((Object)boneTransform).name} '{bonePrefab.Prefab}', pos: {bonePrefab.Position}, scale: {bonePrefab.Scale} rot: {bonePrefab.Rotation}"); } catch (Exception value) { LogError($"Bone Transform owner: [{((Object)agent).name}] bone: [{bonePrefab.Bone}] prefab: [{bonePrefab.Prefab}] were not attached! : {value}"); } } } public sealed class GlowCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent, IEnemyGlowEvent { public static readonly Color DefaultPropaWakeColor = Color.op_Implicit(ES_HibernateWakeUp.m_propagatedWakeupColor); public Color DefaultColor { get; set; } = Color.black; public Color DetectionColor { get; set; } = new Color(9f, 3.9f, 3f, 1f); public Color HeartbeatColor { get; set; } = new Color(9f, 3.9f, 3f, 1f); public Color SelfWakeupColor { get; set; } = Color.op_Implicit(new Vector4(3f, 0.2f, 0.2f, 0.5f) * 3f); public Color PropagateWakeupColor { get; set; } = Color.op_Implicit(new Vector4(3f, 0.2f, 0.2f, 0.5f) * 3f); public Color TentacleAttackColor { get; set; } = Color.op_Implicit(new Vector4(1.5f, 0.1f, 0.1f, 1f) * 1.75f); public Color ShooterFireColor { get; set; } = Color.op_Implicit(new Vector4(1f, 0.5f, 0.45f, 1f) * 2.15f); public PulseEffectData[] PulseEffects { get; set; } = Array.Empty(); public override string GetProcessName() { return "Glow"; } public override void OnConfigLoaded() { for (int i = 0; i < PulseEffects.Length; i++) { PulseEffectData pulseEffectData = PulseEffects[i]; if (Logger.DevLogAllowed) { LogDev("PatternFound!: " + pulseEffectData.GlowRawPattern); } pulseEffectData.CachePattern(); PatternDataCache[] patternData = pulseEffectData.PatternData; for (int j = 0; j < patternData.Length; j++) { PatternDataCache patternDataCache = patternData[j]; if (Logger.DevLogAllowed) { LogDev($" - Data, step: {patternDataCache.StepDuration}, progression: {patternDataCache.Progression}"); } } PulseEffects[i] = pulseEffectData; } } public void OnSpawned(EnemyAgent agent) { //IL_0007: 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) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) agent.MaterialHandler.m_defaultGlowColor = Color.op_Implicit(DefaultColor); agent.Locomotion.ShooterAttack.m_attackGlowColor_End = Color.op_Implicit(ShooterFireColor); agent.Locomotion.StrikerAttack.m_attackGlowColor = Color.op_Implicit(TentacleAttackColor); agent.Locomotion.TankMultiTargetAttack.m_attackGlowColor = Color.op_Implicit(TentacleAttackColor); agent.Locomotion.HibernateWakeup.m_selfWakeupColor = Color.op_Implicit(SelfWakeupColor); agent.Locomotion.Hibernate.m_heartbeatColorVec = Color.op_Implicit(HeartbeatColor); PulseEffectData[] pulseEffects = PulseEffects; for (int i = 0; i < pulseEffects.Length; i++) { PulseEffectData pulseData = pulseEffects[i]; PulseRoutine pulseRoutine = new PulseRoutine { Agent = agent, PulseData = pulseData }; if (pulseData.RandomizeTime) { float num = Math.Max(0f, pulseData.Duration); float startDelay = Rand.NextFloat() * num; pulseRoutine.StartDelay = startDelay; } ((MonoBehaviour)(object)agent.AI).StartCoroutine(pulseRoutine.Routine()); } } public bool OnGlow(EnemyAgent agent, ref GlowInfo glowInfo) { //IL_0001: 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_0027: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0075: 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) if (glowInfo.Color == DefaultPropaWakeColor) { glowInfo = glowInfo.ChangeColor(PropagateWakeupColor); return true; } if (glowInfo.Color == Color.op_Implicit(agent.Locomotion.Hibernate.m_detectingColorVec)) { glowInfo = new GlowInfo(new Color(DetectionColor.r, DetectionColor.g, DetectionColor.b, glowInfo.Color.a), glowInfo.Position); return true; } return false; } } public struct PulseEffectData { public PatternDataCache[] PatternData; public AgentModeTarget Target { get; set; } public float Duration { get; set; } [JsonPropertyName("GlowPattern")] public string GlowRawPattern { get; set; } public Color GlowColor { get; set; } public bool RandomizeTime { get; set; } public bool KeepOnDead { get; set; } public bool AlwaysPulse { get; set; } public PulseEffectData(AgentModeTarget target, float interval, string pattern) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Target = target; Duration = interval; GlowRawPattern = pattern; GlowColor = Color.red; RandomizeTime = true; KeepOnDead = false; AlwaysPulse = false; PatternData = null; } public PatternDataCache[] CachePattern() { List list = new List(); PatternDataCache item = default(PatternDataCache); string glowRawPattern = GlowRawPattern; for (int i = 0; i < glowRawPattern.Length; i++) { float num = glowRawPattern[i] switch { '0' => 0f, '1' => 0.1f, '2' => 0.2f, '3' => 0.3f, '4' => 0.4f, '5' => 0.5f, '6' => 0.6f, '7' => 0.7f, '8' => 0.8f, '9' => 0.9f, 'f' => 1f, '-' => -2f, '+' => -3f, _ => -1f, }; if (num == -1f) { continue; } if (num != -2f) { if (num == -3f) { if (item.StepDuration == 0) { throw new ArgumentException("Pattern '+' has came out first before other value appear!"); } item.StepDuration++; continue; } if (item.StepDuration > 0) { list.Add(item); item = default(PatternDataCache); } item.StepDuration = 1; item.Progression = num; } else { if (item.StepDuration > 0 && item.Progression >= 0f) { list.Add(item); item = default(PatternDataCache); } if (item.Progression < 0f) { item.StepDuration++; continue; } item.StepDuration = 1; item.Progression = -1f; } } if (item.StepDuration > 0) { list.Add(item); } PatternData = list.ToArray(); return PatternData; } } public struct PatternDataCache { public int StepDuration; public float Progression; } public sealed class LimbCustom : EnemyCustomBase, IEnemyPrefabBuiltEvent, IEnemyEvent { public sealed class LimbData { public string LimbName { get; set; } = "Head"; public LimbDamageType LimbType { get; set; } = LimbDamageType.Weakspot; public float CustomMulti { get; set; } = 1f; public ValueBase Health { get; set; } = ValueBase.Unchanged; } public enum LimbDamageType { Normal, Weakspot, WeakspotCustom, Armor, ArmorCustom } public LimbData[] Limbs { get; set; } = Array.Empty(); public override string GetProcessName() { return "Limb"; } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { Dam_EnemyDamageBase componentInChildren = ((Component)agent).GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null || !enemyData.TryGetBalancingBlock(out EnemyBalancingDataBlock balancing)) { return; } LimbData limbData = Limbs.SingleOrDefault((LimbData x) => x.LimbName.InvariantEquals("All", ignoreCase: true)); HealthData health = balancing.Health; foreach (Dam_EnemyDamageLimb limb in (Il2CppArrayBase)(object)componentInChildren.DamageLimbs) { if (Logger.VerboseLogAllowed) { LogVerbose(" - Found Limb: " + ((Object)limb).name); } LimbData limbData2 = Limbs.SingleOrDefault((LimbData x) => x.LimbName.InvariantEquals(((Object)limb).name, ignoreCase: true)); if (limbData2 == null) { if (limbData == null) { continue; } limbData2 = limbData; } if (Logger.VerboseLogAllowed) { LogVerbose($" - Applying Setting to Limb, LimbType: {limbData2.LimbType}, CustomMult: {limbData2.CustomMulti}, HealthValue: {limbData2.Health}"); } float absValue = limbData2.Health.GetAbsValue(balancing.Health.BodypartHealth); LimbDataModifier limbDataModifier = ((Component)limb).gameObject.AddOrGetComponent(); limbDataModifier.Agent.Set(agent); limbDataModifier.Limb.Set(limb); limbDataModifier.NewHealth.Set(absValue); limbDataModifier.NewMaxHealth.Set(absValue); bool flag = limbData2.LimbType == LimbDamageType.ArmorCustom || limbData2.LimbType == LimbDamageType.WeakspotCustom; switch (limbData2.LimbType) { case LimbDamageType.Normal: limbDataModifier.SetMulti((eLimbDamageType)0, 1f, 1f); break; case LimbDamageType.Armor: case LimbDamageType.ArmorCustom: { float weakspot = (flag ? limbData2.CustomMulti : health.ArmorDamageMulti); limbDataModifier.SetMulti((eLimbDamageType)2, weakspot, 1f); break; } case LimbDamageType.Weakspot: case LimbDamageType.WeakspotCustom: { float weakspot = (flag ? limbData2.CustomMulti : health.WeakspotDamageMulti); limbDataModifier.SetMulti((eLimbDamageType)1, 1f, weakspot); break; } } } } } public sealed class MarkerCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public static readonly Vector3 EnemyTextScale = new Vector3(1f, 1f, 1f); public static readonly Vector3 EnemyDistanceTextScale = new Vector3(0.6f, 0.6f, 0.6f); public static readonly Vector3 EnemySpriteScale = new Vector3(54f, 54f, 54f); private Sprite _sprite; private bool _hasText; private bool _textRequiresAutoUpdate; public string SpriteName { get; set; } = string.Empty; public Color MarkerColor { get; set; } = new Color(0.8235f, 0.1843f, 0.1176f); public string MarkerText { get; set; } = string.Empty; public HealthBarFormat MarkerTextHealthBarFormat { get; set; } = new HealthBarFormat(); public float SpriteScale { get; set; } = 1f; public float TextScale { get; set; } = 1f; public float DistanceTextScale { get; set; } = 1f; public bool ShowDistance { get; set; } public bool BlinkIn { get; set; } public bool Blink { get; set; } public float BlinkDuration { get; set; } = 30f; public float BlinkMinDelay { get; set; } = 1f; public float BlinkMaxDelay { get; set; } = 5f; public bool AllowMarkingOnHibernate { get; set; } public override string GetProcessName() { return "Marker"; } public override void OnAssetLoaded() { if (!string.IsNullOrEmpty(SpriteName) && !SpriteManager.TryGetSpriteCache(SpriteName, 64f, out _sprite)) { _sprite = SpriteManager.GenerateSprite(SpriteName); } } public override void OnConfigLoaded() { if (Configuration.ShowMarkerText && !string.IsNullOrEmpty(MarkerText)) { _hasText = true; if (MarkerTextHandler.TextContainsAnyFormat(MarkerText)) { _textRequiresAutoUpdate = true; } } if (!Configuration.ShowMarkerDistance) { ShowDistance = false; } EnemyMarkerEvents.Marked += OnMarked; } public override void OnConfigUnloaded() { EnemyMarkerEvents.Marked -= OnMarked; } public void OnSpawned(EnemyAgent agent) { if (AllowMarkingOnHibernate) { agent.ScannerData.m_soundIndex = 0; } } private void OnMarked(EnemyAgent agent, NavMarker marker) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_00de: 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) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (!IsTarget(agent)) { return; } marker.m_enemySubObj.SetColor(MarkerColor); NavMarkerOption val = (NavMarkerOption)128; if (_hasText) { val = (NavMarkerOption)(val | 0x10); if (_textRequiresAutoUpdate) { if (!((Component)marker).gameObject.TryGetComp(out var component)) { component = ((Component)marker).gameObject.AddComponent(); component.Agent = agent; component.Worker = MarkerTextHealthBarFormat.CreateWorker(); } component.Marker = marker; component.ChangeBaseText(MarkerText); } else { marker.SetTitle(MarkerText); } ((Component)marker.m_titleSubObj).transform.localScale = EnemyTextScale * TextScale; } if (ShowDistance) { val = (NavMarkerOption)(val | 8); ((Component)marker.m_distanceSubObj).transform.localScale = EnemyDistanceTextScale * DistanceTextScale; } marker.SetVisualStates(val, val, (NavMarkerOption)0, (NavMarkerOption)0); ((Component)marker.m_enemySubObj).transform.localScale = EnemySpriteScale * SpriteScale; if ((Object)(object)_sprite != (Object)null) { ((Component)marker.m_enemySubObj).GetComponentInChildren().sprite = _sprite; } if (BlinkIn) { CoroutineManager.BlinkIn(((Component)marker.m_enemySubObj).gameObject, 0f); CoroutineManager.BlinkIn(((Component)marker.m_enemySubObj).gameObject, 0.2f); } if (Blink && BlinkMinDelay >= 0f && BlinkMinDelay < BlinkMaxDelay) { float num = Math.Min(BlinkDuration, agent.EnemyBalancingData.TagTime); for (float num2 = 0.4f + Rand.Range(BlinkMinDelay, BlinkMaxDelay); num2 <= num; num2 += Rand.Range(BlinkMinDelay, BlinkMaxDelay)) { CoroutineManager.BlinkIn(((Component)marker.m_enemySubObj).gameObject, num2); } } } } public sealed class HealthBarFormat { public sealed class Worker { public int Count; public string FilledBarText; public string EmptyBarText; private StringBuilder _stringBuilder; private int _lastFilledBar = -1; private string _lastBarText = string.Empty; public string BuildString(float maxHealth, float health) { int num = Mathf.CeilToInt(Mathf.Lerp(0f, (float)Count, health / maxHealth)); if (num == _lastFilledBar) { return _lastBarText; } _lastFilledBar = num; if (_stringBuilder == null) { _stringBuilder = new StringBuilder(); } else { _stringBuilder.Clear(); } for (int i = 0; i < Count; i++) { if (i < num) { _stringBuilder.Append(FilledBarText); } else { _stringBuilder.Append(EmptyBarText); } } _lastBarText = _stringBuilder.ToString(); return _lastBarText; } } public int Count { get; set; } = 8; public string FilledBarText { get; set; } = "|"; public string EmptyBarText { get; set; } = " "; public Worker CreateWorker() { return new Worker { Count = Count, FilledBarText = FilledBarText, EmptyBarText = EmptyBarText }; } } public sealed class MaterialCustom : EnemyCustomBase, IEnemyPrefabBuiltEvent, IEnemyEvent { public sealed class MaterialSwapSet { public string From { get; set; } = ""; public string To { get; set; } = ""; public SkinNoiseType SkinNoise { get; set; } public string SkinNoiseTexture { get; set; } = string.Empty; public ColorSetting[] ColorProperties { get; set; } = Array.Empty(); public FloatSetting[] FloatProperties { get; set; } = Array.Empty(); } public struct ColorSetting { public string Name { get; set; } public Color Value { get; set; } } public struct FloatSetting { public string Name { get; set; } public float Value { get; set; } } public enum SkinNoiseType { KeepOriginal, ForceOn, ForceOff } public MaterialSwapSet[] MaterialSets { get; set; } = Array.Empty(); public override string GetProcessName() { return "Material"; } public override void OnConfigLoaded() { List list = new List(); foreach (IGrouping item in from x in MaterialSets group x by x.From) { MaterialSwapSet materialSwapSet = item.First(); if (item.Count() > 1) { LogWarning("Duplicate Material Swap Setting: '" + materialSwapSet.From + "' will use first occurrence"); } list.Add(materialSwapSet); } MaterialSets = list.ToArray(); } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) CharacterMaterialHandler materialHandler = agent.MaterialHandler; List materialRefs = materialHandler.m_materialRefs; if (materialRefs.Count == 0) { PopulateMaterialList(agent, materialHandler); } Enumerator enumerator = materialRefs.GetEnumerator(); while (enumerator.MoveNext()) { MaterialRef current = enumerator.Current; string matName = ((Object)current.m_material).name.Replace(" (Instance)", "", StringComparison.InvariantCulture); if (Logger.VerboseLogAllowed) { LogVerbose(" - Debug Info, Material Found: " + matName); } MaterialSwapSet materialSwapSet = MaterialSets.SingleOrDefault((MaterialSwapSet x) => x.From.InvariantEquals(matName)); if (materialSwapSet == null) { continue; } if (!AssetCacheManager.Materials.TryGet(materialSwapSet.To, out Material obj)) { LogError("MATERIAL WAS NOT CACHED!: " + materialSwapSet.To); continue; } if (Logger.DevLogAllowed) { LogDev(" - Trying to Replace Material, Before: " + matName + " After: " + ((Object)obj).name); } _ = current.m_material; Material val = new Material(obj); switch (materialSwapSet.SkinNoise) { case SkinNoiseType.ForceOn: val.SetFloat("_Enable_SkinNoise", 1f); val.EnableKeyword("ENABLE_SKIN_NOISE"); break; case SkinNoiseType.ForceOff: val.SetFloat("_Enable_SkinNoise", 0f); val.DisableKeyword("ENABLE_SKIN_NOISE"); break; } if (!string.IsNullOrEmpty(materialSwapSet.SkinNoiseTexture)) { if (AssetCacheManager.Texture3Ds.TryGet(materialSwapSet.SkinNoiseTexture, out Texture3D obj2)) { val.SetTexture("_VolumeNoise", (Texture)(object)obj2); } else { LogError("TEXTURE3D WAS NOT CACHED!: " + materialSwapSet.SkinNoiseTexture); } } ColorSetting[] colorProperties = materialSwapSet.ColorProperties; for (int i = 0; i < colorProperties.Length; i++) { ColorSetting colorSetting = colorProperties[i]; if (!val.HasProperty(colorSetting.Name)) { LogError("Color Property is missing: " + colorSetting.Name); } else { val.SetColor(colorSetting.Name, colorSetting.Value); } } FloatSetting[] floatProperties = materialSwapSet.FloatProperties; for (int i = 0; i < floatProperties.Length; i++) { FloatSetting floatSetting = floatProperties[i]; if (!val.HasProperty(floatSetting.Name)) { LogError("Float Property is missing: " + floatSetting.Name); } else { val.SetFloat(floatSetting.Name, floatSetting.Value); } } current.m_material = val; if (Logger.VerboseLogAllowed) { LogVerbose(" - Replaced!"); } } } private void PopulateMaterialList(EnemyAgent enemy, CharacterMaterialHandler materialHandler) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown Il2CppArrayBase componentsInChildren = ((Component)enemy).GetComponentsInChildren(true); Dictionary dictionary = new Dictionary(); foreach (MeshRenderer item in componentsInChildren) { Material material = ((Renderer)item).material; if (!((Object)(object)material == (Object)null)) { if (!dictionary.ContainsKey(((Object)material).name)) { dictionary[((Object)material).name] = new MaterialRef { m_material = material }; } dictionary[((Object)material).name].m_renderers.Add((Renderer)(object)item); } } foreach (MaterialRef value in dictionary.Values) { materialHandler.m_materialRefs.Add(value); } } } public sealed class ModelRefCustom : EnemyCustomBase, IEnemyPrefabBuiltEvent, IEnemyEvent { public sealed class ModelRefData { public BaseModelRefType Type { get; set; } public BaseModelRefType CopyFrom { get; set; } public string CreateFromPath { get; set; } = string.Empty; public Vector3 Offset { get; set; } = Vector3.zero; public Vector3 RotateOffset { get; set; } = Vector3.zero; } public enum BaseModelRefType { None, Tentacle, Tentacle2, Tentacle3, TentacleNoHead, TentacleNoCheat, ShooterFire, ScoutFeeler, BioMarker } public struct ModelRefCache { public Transform m_tentacleAlign; public Transform m_tentacleAlign2; public Transform m_tentacleAlign3; public Transform m_tentacleAlignNoHead; public Transform m_tentacleAlignNoChest; public Transform m_shooterFireAlign; public Transform m_detectAbilityAlign; public Transform m_markerTagAlign; public void CopyFrom(EnemyModelRefs modelRef) { m_tentacleAlign = modelRef.m_tentacleAlign; m_tentacleAlign2 = modelRef.m_tentacleAlign2; m_tentacleAlign3 = modelRef.m_tentacleAlign3; m_tentacleAlignNoHead = modelRef.m_tentacleAlignNoHead; m_tentacleAlignNoChest = modelRef.m_tentacleAlignNoChest; m_shooterFireAlign = modelRef.m_shooterFireAlign; m_detectAbilityAlign = modelRef.m_detectAbilityAlign; m_markerTagAlign = modelRef.m_markerTagAlign.transform; } public void CopyTo(ref EnemyModelRefs modelRef) { modelRef.m_tentacleAlign = m_tentacleAlign; modelRef.m_tentacleAlign2 = m_tentacleAlign2; modelRef.m_tentacleAlign3 = m_tentacleAlign3; modelRef.m_tentacleAlignNoHead = m_tentacleAlignNoHead; modelRef.m_tentacleAlignNoChest = m_tentacleAlignNoChest; modelRef.m_shooterFireAlign = m_shooterFireAlign; modelRef.m_detectAbilityAlign = m_detectAbilityAlign; modelRef.m_markerTagAlign = ((Component)m_markerTagAlign).gameObject; } } public ModelRefData[] ModelRefs { get; set; } = Array.Empty(); public override string GetProcessName() { return "MedelRef"; } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) EnemyModelRefs modelRef = agent.ModelRef; ModelRefCache modelRefCache = default(ModelRefCache); modelRefCache.CopyFrom(modelRef); ModelRefData[] modelRefs = ModelRefs; foreach (ModelRefData modelRefData in modelRefs) { Transform val = null; switch (modelRefData.CopyFrom) { case BaseModelRefType.Tentacle: val = modelRef.m_tentacleAlign; break; case BaseModelRefType.Tentacle2: val = modelRef.m_tentacleAlign2; break; case BaseModelRefType.Tentacle3: val = modelRef.m_tentacleAlign3; break; case BaseModelRefType.TentacleNoHead: val = modelRef.m_tentacleAlignNoHead; break; case BaseModelRefType.TentacleNoCheat: val = modelRef.m_tentacleAlignNoChest; break; case BaseModelRefType.ShooterFire: val = modelRef.m_shooterFireAlign; break; case BaseModelRefType.ScoutFeeler: val = modelRef.m_detectAbilityAlign; break; case BaseModelRefType.BioMarker: val = modelRef.m_markerTagAlign.transform; break; default: if (!string.IsNullOrEmpty(modelRefData.CreateFromPath)) { val = ((Component)agent).transform.FindChild(modelRefData.CreateFromPath); } break; } if ((Object)(object)val == (Object)null) { LogError($"Could not find base modelRef to work on, type: {modelRefData.Type} path: {modelRefData.CreateFromPath}"); continue; } GameObject val2 = new GameObject("New_ModelRef"); val2.transform.parent = val.parent; val2.transform.SetPositionAndRotation(val.position, val.rotation); val2.transform.localPosition = val.localPosition + modelRefData.Offset; val2.transform.localRotation = val.localRotation; Quaternion localRotation = val2.transform.localRotation; Vector3 eulerAngles = ((Quaternion)(ref localRotation)).eulerAngles + modelRefData.RotateOffset; localRotation = val2.transform.localRotation; ((Quaternion)(ref localRotation)).SetEulerAngles(eulerAngles); switch (modelRefData.Type) { case BaseModelRefType.Tentacle: modelRefCache.m_tentacleAlign = val2.transform; break; case BaseModelRefType.Tentacle2: modelRefCache.m_tentacleAlign2 = val2.transform; break; case BaseModelRefType.Tentacle3: modelRefCache.m_tentacleAlign3 = val2.transform; break; case BaseModelRefType.TentacleNoHead: modelRefCache.m_tentacleAlignNoHead = val2.transform; break; case BaseModelRefType.TentacleNoCheat: modelRefCache.m_tentacleAlignNoChest = val2.transform; break; case BaseModelRefType.ShooterFire: modelRefCache.m_shooterFireAlign = val2.transform; break; case BaseModelRefType.ScoutFeeler: modelRefCache.m_detectAbilityAlign = val2.transform; break; case BaseModelRefType.BioMarker: modelRefCache.m_markerTagAlign = val2.transform; break; default: LogError($"Type is not valid: {modelRefData.Type}"); continue; } if (Logger.DevLogAllowed) { LogDev("Done!"); } } modelRefCache.CopyTo(ref modelRef); } } public sealed class ScannerCustom : EnemyCustomBase, IEnemyPrefabBuiltEvent, IEnemyEvent { public ScannerColorData ColorData; [JsonPropertyName("DefaultColor")] public Color Internal_DefaultColor { get; set; } = new Color(0.7f, 0.7f, 0.7f); [JsonPropertyName("DefaultSize")] public float Internal_DefaultSize { get; set; } = 1f; [JsonPropertyName("WakeupColor")] public Color Internal_WakeupColor { get; set; } = new Color(1f, 0.1f, 0.1f); [JsonPropertyName("WakeupSize")] public float Internal_WakeupSize { get; set; } = 1f; public float LerpingDuration { get; set; } = 0.5f; public float UpdateInterval { get; set; } = 0.15f; public bool OptimizeAfterAwake { get; set; } = true; public bool UsingDetectionColor { get; set; } [JsonPropertyName("DetectionColor")] public Color Internal_DetectionColor { get; set; } = new Color(0.9882f, 0.4078f, 0f); [JsonPropertyName("DetectionSize")] public float Internal_DetectionSize { get; set; } = 1f; [JsonPropertyName("HeartbeatColor")] public Color Internal_HeartbeatColor { get; set; } = new Color(1f, 0.8431f, 0.8431f); [JsonPropertyName("HeartbeatSize")] public float Internal_HeartbeatSize { get; set; } = 1f; public bool UsingScoutColor { get; set; } [JsonPropertyName("ScoutPatrolColor")] public Color Internal_ScoutPatrolColor { get; set; } = new Color(1f, 0.1f, 0.1f); [JsonPropertyName("ScoutPatrolSize")] public float Internal_ScoutPatrolSize { get; set; } = 0.5f; [JsonPropertyName("ScoutFeelerColor")] public Color Internal_ScoutFeelerColor { get; set; } = new Color(1f, 0.1f, 0.1f); [JsonPropertyName("ScoutFeelerSize")] public float Internal_ScoutFeelerSize { get; set; } = 1f; public override string GetProcessName() { return "Scanner"; } public override void OnConfigLoaded() { //IL_000c: 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_001c: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) ColorData = new ScannerColorData { DefaultColor = CreateNewColor(Internal_DefaultColor, Internal_DefaultSize), WakeupColor = CreateNewColor(Internal_WakeupColor, Internal_WakeupSize), DetectionColor = CreateNewColor(Internal_DetectionColor, Internal_DetectionSize), HeartbeatColor = CreateNewColor(Internal_HeartbeatColor, Internal_HeartbeatSize), PatrolColor = CreateNewColor(Internal_ScoutPatrolColor, Internal_ScoutPatrolSize), FeelerOutColor = CreateNewColor(Internal_ScoutFeelerColor, Internal_ScoutFeelerSize), InterpDuration = LerpingDuration, UpdateInterval = UpdateInterval, UsingScoutColor = UsingScoutColor, UsingDetectionColor = UsingDetectionColor, OptimizeOnAwake = OptimizeAfterAwake }; if (Logger.VerboseLogAllowed) { LogVerbose("Color Initialized!"); LogVerbose(" - Default; " + ((object)(Color)(ref ColorData.DefaultColor)).ToString()); LogVerbose(" - Wakeup; " + ((object)(Color)(ref ColorData.WakeupColor)).ToString()); LogVerbose(" - Detection; " + ((object)(Color)(ref ColorData.DetectionColor)).ToString()); LogVerbose(" - Heartbeat; " + ((object)(Color)(ref ColorData.HeartbeatColor)).ToString()); LogVerbose(" - Patrol; " + ((object)(Color)(ref ColorData.PatrolColor)).ToString()); LogVerbose(" - Feeler; " + ((object)(Color)(ref ColorData.FeelerOutColor)).ToString()); } static Color CreateNewColor(Color c, float alpha) { //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) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return new Color(c.r, c.g, c.b, alpha); } } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0091: Unknown result type (might be due to invalid IL or missing references) ScannerHandler scannerHandler = ((Component)agent).gameObject.AddOrGetComponent(); scannerHandler.OwnerAgent.Value = agent; scannerHandler.DefaultColor.Value = ColorData.DefaultColor; scannerHandler.WakeupColor.Value = ColorData.WakeupColor; scannerHandler.DetectionColor.Value = ColorData.DetectionColor; scannerHandler.HeartbeatColor.Value = ColorData.HeartbeatColor; scannerHandler.PatrolColor.Value = ColorData.PatrolColor; scannerHandler.FeelerOutColor.Value = ColorData.FeelerOutColor; scannerHandler.UsingDetectionColor.Value = ColorData.UsingDetectionColor; scannerHandler.UsingScoutColor.Value = ColorData.UsingScoutColor; scannerHandler.InterpDuration.Value = ColorData.InterpDuration; scannerHandler.UpdateInterval.Value = ColorData.UpdateInterval; scannerHandler.OptimizeOnAwake.Value = ColorData.OptimizeOnAwake; } } public struct ScannerColorData { public Color DefaultColor; public Color WakeupColor; public Color DetectionColor; public Color HeartbeatColor; public Color PatrolColor; public Color FeelerOutColor; public bool UsingDetectionColor; public bool UsingScoutColor; public float InterpDuration; public float UpdateInterval; public bool OptimizeOnAwake; } public enum ShadowType : byte { LegacyShadows, NewShadows } public sealed class ShadowCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent, IEnemyPrefabBuiltEvent { public static readonly string[] g_SER = new string[5] { "g_body_shadow", "g_shooter", "g_tank", "g_birther", "g_pouncer_shadow" }; public bool IncludeEggSack { get; set; } public bool RequireTagForDetection { get; set; } public bool FullyInvisible { get; set; } public ShadowType Type { get; set; } public bool IncludeThermals { get; set; } = true; public bool TumorVisibleFromBehind { get; set; } public override string GetProcessName() { return "Shadow"; } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { if (Type != 0) { return; } agent.RequireTagForDetection = RequireTagForDetection; foreach (Renderer componentsInChild in ((Component)agent).GetComponentsInChildren(true)) { if (!IncludeEggSack && ((Object)((Component)componentsInChild).gameObject).name.InvariantContains("Egg")) { if (Logger.VerboseLogAllowed) { LogVerbose(" - Ignored EggSack Object!"); } componentsInChild.shadowCastingMode = (ShadowCastingMode)1; componentsInChild.enabled = true; continue; } SkinnedMeshRenderer val = ((Il2CppObjectBase)componentsInChild).TryCast(); if ((Object)(object)val != (Object)null) { val.updateWhenOffscreen = true; } if (FullyInvisible) { Object.Destroy((Object)(object)componentsInChild); continue; } componentsInChild.castShadows = true; componentsInChild.shadowCastingMode = (ShadowCastingMode)3; ((Component)componentsInChild).gameObject.AddComponent(); } } public void OnSpawned(EnemyAgent agent) { if (Type == ShadowType.LegacyShadows) { agent.MovingCuller.m_disableAnimatorCullingWhenRenderingShadow = true; agent.MovingCuller.Culler.hasShadowsEnabled = true; ((Agent)agent).SetAnimatorCullingEnabled(false); } else { TSF_SpawnEnemy(agent); } } public void TSF_SpawnEnemy(EnemyAgent agent) { //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) agent.MovingCuller.m_disableAnimatorCullingWhenRenderingShadow = true; agent.MovingCuller.Culler.hasShadowsEnabled = true; ((Agent)agent).SetAnimatorCullingEnabled(false); agent.RequireTagForDetection = RequireTagForDetection; foreach (InstancedRenderFeature componentsInChild in ((Component)agent).GetComponentsInChildren(true)) { ((Behaviour)componentsInChild).enabled = false; } if (IncludeThermals) { ((Component)agent).gameObject.AddComponent().Initialize(agent, IncludeThermals); } foreach (Renderer componentsInChild2 in ((Component)agent).GetComponentsInChildren(true)) { if (FullyInvisible) { Object.Destroy((Object)(object)componentsInChild2); continue; } if (IncludeEggSack) { componentsInChild2.receiveShadows = true; componentsInChild2.castShadows = true; componentsInChild2.shadowCastingMode = (ShadowCastingMode)1; } SkinnedMeshRenderer val = ((Il2CppObjectBase)componentsInChild2).TryCast(); if ((Object)(object)val != (Object)null && g_SER.Contains(((Object)((Component)val).gameObject).name.ToLower())) { val.updateWhenOffscreen = true; } componentsInChild2.shadowCastingMode = (ShadowCastingMode)3; if (!((Object)componentsInChild2).name.InvariantContains("Egg", ignoreCase: true) && !((Object)componentsInChild2).name.InvariantContains("FleshSack", ignoreCase: true)) { continue; } agent.MovingCuller.m_disableAnimatorCullingWhenRenderingShadow = true; componentsInChild2.receiveShadows = false; componentsInChild2.castShadows = false; componentsInChild2.shadowCastingMode = (ShadowCastingMode)0; componentsInChild2.enabled = false; GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)0); GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val2).name = "fd_egg_sphere1"; ((Object)obj).name = "fd_egg_sphere2_shadow"; val2.transform.parent = ((Component)componentsInChild2).transform; val2.transform.localScale = Vector3.one; val2.transform.localPosition = ((Component)componentsInChild2).transform.localPosition; obj.transform.parent = ((Component)componentsInChild2).transform; obj.transform.localScale = Vector3.one; obj.transform.localPosition = ((Component)componentsInChild2).transform.localPosition; MeshRenderer component = val2.GetComponent(); MeshRenderer component2 = obj.GetComponent(); ((Renderer)component).material = Object.Instantiate(((Renderer)component).sharedMaterial); ((Renderer)component2).material = Object.Instantiate(((Renderer)component).sharedMaterial); ((Renderer)component).material.SetTexture("_MainTex", componentsInChild2.sharedMaterial.mainTexture); ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).castShadows = false; ((Renderer)component).material.color = new Color(1f, 1f, 1f, 1f); ((Renderer)component).material.shader = Shader.Find("Cell/Enemy/EnemyFlesh_CD"); ((Renderer)component).material.enableInstancing = false; ((Renderer)component2).shadowCastingMode = (ShadowCastingMode)3; ((Renderer)component2).castShadows = true; ((Renderer)component2).receiveShadows = false; ((Renderer)component2).material.color = new Color(1f, 1f, 1f, 1f); ((Renderer)component2).material.shader = Shader.Find("Cell/Enemy/EnemyFlesh_CD"); ((Renderer)component2).material.enableInstancing = false; ((Collider)val2.GetComponent()).enabled = false; ((Collider)obj.GetComponent()).enabled = false; Renderer component3 = val2.GetComponent(); Renderer component4 = obj.GetComponent(); try { Enumerator enumerator3 = agent.MaterialHandler.m_materialRefs.GetEnumerator(); while (enumerator3.MoveNext()) { enumerator3.Current.m_renderers.Add(component4); } } catch (Exception value) { Debug.LogError(Object.op_Implicit($"cmh error {value}")); } component3.shadowCastingMode = (ShadowCastingMode)0; component4.shadowCastingMode = (ShadowCastingMode)3; agent.MovingCuller.CullBucket.Renderers.Remove(componentsInChild2); agent.MovingCuller.CullBucket.Renderers.Add(component3); agent.MovingCuller.Culler.hasShadowsEnabled = true; agent.MovingCuller.CullBucket.ShadowRenderers.Add(component4); ((Component)componentsInChild2).gameObject.AddComponent().Initialize(agent, componentsInChild2, component3, component4, TumorVisibleFromBehind); } agent.MovingCuller.CullBucket.ComputeTotalBounds(); ((C_Cullable)agent.MovingCuller.CullBucket).NeedsShadowRefresh = true; } } public sealed class SilhouetteCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent, IEnemyPrefabBuiltEvent { public const string PlayerPrefabPath = "ASSETS/ASSETPREFABS/CHARACTERS/CHARACTER_A.PREFAB"; public const string PlayerGhostName = "g_set_military_01_boots_ghost"; private static bool _materialCached; private static Material _silhouetteMaterial; public Color DefaultColor { get; set; } = Color.red; public bool RequireTag { get; set; } = true; public bool ReplaceColorWithMarker { get; set; } = true; public bool KeepOnDead { get; set; } public float DeadEffectDelay { get; set; } = 0.75f; public override string GetProcessName() { return "Silhouette"; } public override void OnAssetLoaded() { if (!_materialCached) { _silhouetteMaterial = ((Renderer)((Il2CppObjectBase)AssetShardManager.s_loadedAssetsLookup["ASSETS/ASSETPREFABS/CHARACTERS/CHARACTER_A.PREFAB".ToUpper()]).Cast().FindChild("g_set_military_01_boots_ghost").GetComponent()).material; _materialCached = true; } } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) Il2CppArrayBase componentsInChildren = ((Component)agent).GetComponentsInChildren(true); List rendererList = new List(); foreach (Renderer item in componentsInChildren) { rendererList.Add(item); } Enumerator enumerator2 = ((Component)agent).GetComponentInChildren().m_materialRefs.GetEnumerator(); while (enumerator2.MoveNext()) { MaterialRef current2 = enumerator2.Current; if (!current2.HasFeature((MaterialSupport)1)) { RemoveFromRendererMatRef(current2); continue; } if (!current2.HasFeature((MaterialSupport)1)) { RemoveFromRendererMatRef(current2); continue; } Enumerator enumerator3 = current2.m_renderers.GetEnumerator(); while (enumerator3.MoveNext()) { Renderer current3 = enumerator3.Current; if (((Object)current3).name.InvariantEquals("g_leg_l", ignoreCase: true)) { RemoveFromRenderer(current3); } } } foreach (Renderer item2 in rendererList) { Logger.Verbose("Silhouette Object Found! : " + ((Object)item2).name); GameObject gameObject = ((Component)item2).gameObject; GameObject obj = gameObject.Instantiate(gameObject.transform, "g_ghost"); obj.layer = LayerMask.NameToLayer("Enemy"); obj.AddComponent(); Renderer component = obj.GetComponent(); component.material = _silhouetteMaterial; component.material.SetVector("_ColorA", Color.op_Implicit(Color.clear)); component.material.SetVector("_ColorB", Color.op_Implicit(Color.clear)); component.lightProbeUsage = (LightProbeUsage)1; component.reflectionProbeUsage = (ReflectionProbeUsage)1; } void RemoveFromRenderer(Renderer renderer) { Renderer renderer2 = renderer; int num = rendererList.FindIndex((Renderer x) => ((Object)x).GetInstanceID() == ((Object)renderer2).GetInstanceID()); if (num != -1) { rendererList.RemoveAt(num); } } void RemoveFromRendererMatRef(MaterialRef matRef) { Enumerator enumerator5 = matRef.m_renderers.GetEnumerator(); while (enumerator5.MoveNext()) { RemoveFromRenderer(enumerator5.Current); } } } public void OnSpawned(EnemyAgent agent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) SilhouetteHandler silhouetteHandler = ((Component)agent).gameObject.AddComponent(); silhouetteHandler.OwnerAgent = agent; silhouetteHandler.DefaultColor = DefaultColor; silhouetteHandler.RequireTag = RequireTag; silhouetteHandler.ReplaceColorWithMarker = ReplaceColorWithMarker; silhouetteHandler.KeepOnDead = KeepOnDead; silhouetteHandler.DeadEffectDelay = DeadEffectDelay; } } } namespace EEC.EnemyCustomizations.Models.Inject { [HarmonyPatch(typeof(ES_EnemyAttackBase))] internal static class Inject_ES_EnemyAttackBase { [HarmonyPatch("DoStartAttack")] [HarmonyPrefix] [HarmonyWrapSafe] public static void OnStartAttack(ES_EnemyAttackBase __instance) { if (((ES_Base)__instance).m_enemyAgent.TryGetProperty(out var property)) { Animator animator = ((ES_Base)__instance).m_locomotion.m_animator; animator.speed *= property.TentacleAttackSpeedAdjustmentMult; } if (!SNet.IsMaster) { __instance.m_attackWindupDuration = ((ES_Base)__instance).m_enemyAgent.Locomotion.AnimHandle.TentacleAttackWindUpLen / ((ES_Base)__instance).m_enemyAgent.Locomotion.AnimSpeedOrg; } } [HarmonyPatch("SyncExit")] [HarmonyPrefix] [HarmonyWrapSafe] public static void OnEndAttack(ES_EnemyAttackBase __instance) { if (((ES_Base)__instance).m_enemyAgent.TryGetProperty(out var property)) { Animator animator = ((ES_Base)__instance).m_locomotion.m_animator; animator.speed /= property.TentacleAttackSpeedAdjustmentMult; } } } } namespace EEC.EnemyCustomizations.Models.Handlers { [InjectToIl2Cpp] public sealed class BoneOffsetHandler : MonoBehaviour { public Il2CppReferenceField Animator; public Il2CppValueField Offset; public Il2CppValueField RotationOffset; private void LateUpdate() { //IL_0019: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (((Behaviour)Animator.Get()).enabled) { Transform transform = ((Component)this).transform; transform.localPosition += Offset.Get(); Transform transform2 = ((Component)this).transform; transform2.localEulerAngles += RotationOffset.Get(); } } } [InjectToIl2Cpp] public sealed class FixEnemySER : MonoBehaviour { private EnemyAgent enemy; private List sammuta = new List(); private List sammuta2 = new List(); private ShadowEnemyRenderer ser; private List sers = new List(); private bool initialized; public void Update() { if (!initialized || (Object)(object)enemy == (Object)null || sers.Count == 0) { return; } foreach (ShadowEnemyRenderer ser in sers) { if (!((Component)ser).gameObject.activeSelf) { ((Component)ser).gameObject.SetActive(true); } } if (!((Agent)enemy).Alive) { return; } foreach (MeshRenderer sammutum in sammuta) { ((Renderer)sammutum).shadowCastingMode = (ShadowCastingMode)3; } foreach (SkinnedMeshRenderer item in sammuta2) { ((Renderer)item).shadowCastingMode = (ShadowCastingMode)3; } } public void Initialize(EnemyAgent enemy, bool thermalShadows) { this.enemy = enemy; Il2CppArrayBase componentsInChildren = ((Component)enemy).GetComponentsInChildren(); if (componentsInChildren != null) { foreach (ShadowEnemyRenderer item in componentsInChildren) { sers.Add(item); } } if (sers.Count > 0) { initialized = true; return; } foreach (MeshRenderer componentsInChild in ((Component)enemy).GetComponentsInChildren()) { if (((Object)((Component)componentsInChild).gameObject).name.ToLower() == "infested") { sammuta.Add(componentsInChild); } } foreach (SkinnedMeshRenderer componentsInChild2 in ((Component)enemy).GetComponentsInChildren()) { if (((Object)((Component)componentsInChild2).gameObject).name.ToLower() == "g_pouncer") { sammuta2.Add(componentsInChild2); } if (((Object)((Component)componentsInChild2).gameObject).name.ToLower() == "g_body") { sammuta2.Add(componentsInChild2); } } foreach (MeshRenderer sammutum in sammuta) { ((Renderer)sammutum).shadowCastingMode = (ShadowCastingMode)3; } foreach (SkinnedMeshRenderer item2 in sammuta2) { ((Renderer)item2).shadowCastingMode = (ShadowCastingMode)3; } if (!thermalShadows) { return; } foreach (SkinnedMeshRenderer componentsInChild3 in ((Component)enemy).GetComponentsInChildren(true)) { if (ShadowCustom.g_SER.Contains(((Object)((Component)componentsInChild3).gameObject).name.ToLower())) { ((Renderer)componentsInChild3).shadowCastingMode = (ShadowCastingMode)3; ser = ((Component)componentsInChild3).gameObject.AddComponent(); ser.Renderer = (Renderer)(object)componentsInChild3; sers.Add(ser); } } if (sers.Count > 0) { ser.MovingCuller = enemy.MovingCuller; initialized = true; } } } [InjectToIl2Cpp] public sealed class FixShadows : MonoBehaviour { private Renderer orig; private EnemyAgent enemy; private Renderer mr1; private Renderer mr2; private bool destroyed; private bool initialized; private List renderers = new List(); private float jee; private Dam_EnemyDamageLimb_Custom bulb; private bool visibleFromBehind; private bool unhide; private PlayerAgent plr = PlayerManager.GetLocalPlayerAgent(); public void Initialize(EnemyAgent enemy, Renderer rend, Renderer sphere, Renderer shadow, bool visibleFromBehind) { jee = Time.realtimeSinceStartup; this.enemy = enemy; mr1 = sphere; ((Component)mr1).gameObject.AddComponent(); mr2 = shadow; orig = rend; foreach (Renderer componentsInChild in ((Component)enemy).GetComponentsInChildren()) { renderers.Add(componentsInChild); } bulb = ((Component)orig).GetComponentInParent(); if ((Object)(object)bulb != (Object)null) { ((Dam_EnemyDamageLimb)bulb).OnLimbDestroyed += Action.op_Implicit((Action)Done); } ((Agent)enemy).SetAnimatorCullingEnabled(false); initialized = true; this.visibleFromBehind = visibleFromBehind; } public void Done() { mr2.forceRenderingOff = true; mr2.castShadows = false; mr2.receiveShadows = false; enemy.MovingCuller.CullBucket.ShadowRenderers.Remove(mr2); Enumerator enumerator = enemy.MaterialHandler.m_materialRefs.GetEnumerator(); while (enumerator.MoveNext()) { MaterialRef current = enumerator.Current; try { current.m_renderers.Remove(mr2); } catch (Exception) { } } enemy.MovingCuller.CullBucket.ComputeTotalBounds(); ((C_Cullable)enemy.MovingCuller.CullBucket).NeedsShadowRefresh = true; destroyed = true; } public void Update() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_012b: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Invalid comparison between Unknown and I4 //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Invalid comparison between Unknown and I4 if (destroyed || !initialized || Time.realtimeSinceStartup - jee < 1f || (Object)(object)enemy == (Object)null) { return; } if (!((Agent)enemy).Alive) { enemy.MovingCuller.CullBucket.Renderers.Remove(mr1); enemy.MovingCuller.CullBucket.ShadowRenderers.Remove(mr2); Enumerator enumerator = enemy.MaterialHandler.m_materialRefs.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.m_renderers.Remove(mr2); } destroyed = true; return; } unhide = false; if ((int)mr1.shadowCastingMode != 0) { mr1.shadowCastingMode = (ShadowCastingMode)0; } if (visibleFromBehind) { Vector3 forward = ((Component)enemy).transform.forward; Vector3 val = ((Component)plr).transform.position - ((Component)enemy).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; if (Vector3.Angle(forward, normalized) > 168f) { unhide = true; } if (unhide) { mr1.forceRenderingOff = false; return; } } if (!mr1.forceRenderingOff) { mr1.forceRenderingOff = true; } foreach (Renderer renderer in renderers) { if ((int)renderer.shadowCastingMode != 3) { renderer.shadowCastingMode = (ShadowCastingMode)3; } if (!renderer.castShadows) { renderer.castShadows = true; } if (!enemy.MovingCuller.m_disableAnimatorCullingWhenRenderingShadow) { enemy.MovingCuller.m_disableAnimatorCullingWhenRenderingShadow = true; } if (enemy.MovingCuller.m_animatorCullingEnabled) { ((Agent)enemy).SetAnimatorCullingEnabled(false); } if (!enemy.MovingCuller.Culler.hasShadowsEnabled) { enemy.MovingCuller.Culler.hasShadowsEnabled = true; } if ((int)mr2.shadowCastingMode != 3) { mr2.shadowCastingMode = (ShadowCastingMode)3; } } } } [InjectToIl2Cpp] internal sealed class LimbDataModifier : MonoBehaviour { public Il2CppReferenceField Agent; public Il2CppReferenceField Limb; public Il2CppValueField NewLimbType; public Il2CppValueField NewHealth; public Il2CppValueField NewMaxHealth; public Il2CppValueField NewArmorMulti; public Il2CppValueField NewWeakspotMulti; public void SetMulti(eLimbDamageType type, float armor, float weakspot) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) NewLimbType.Set(type); NewArmorMulti.Set(armor); NewWeakspotMulti.Set(weakspot); } private void Update() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (Agent.Value.IsSetup) { Dam_EnemyDamageLimb value = Limb.Value; value.m_type = NewLimbType.Value; value.m_health = NewHealth.Value; value.m_healthMax = NewMaxHealth.Value; value.m_armorDamageMulti = NewArmorMulti.Value; value.m_weakspotDamageMulti = NewWeakspotMulti.Value; ((Behaviour)this).enabled = false; } } } [InjectToIl2Cpp] internal sealed class MarkerTextHandler : MonoBehaviour { [CompilerGenerated] private sealed class d__16 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MarkerTextHandler <>4__this; private string 5__2; private StringBuilder 5__3; private float 5__4; private float 5__5; private float 5__6; private int 5__7; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; MarkerTextHandler markerTextHandler = <>4__this; EnemyHealthInfoReplicator.State state; string text; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = string.Empty; 5__3 = new StringBuilder(markerTextHandler._baseText); 5__4 = 0f; goto IL_0054; case 1: <>1__state = -1; goto IL_0054; case 2: <>1__state = -1; goto IL_0132; case 3: { <>1__state = -1; goto IL_0054; } IL_0054: NetworkManager.EnemyHealthState.TryGetState(((Agent)markerTextHandler.Agent).GlobalID, out state); 5__5 = state.maxHealth; 5__6 = state.health; if (5__4 == 5__6 && !markerTextHandler._hasFormat[9]) { <>2__current = _updateYielder; <>1__state = 1; return true; } 5__4 = 5__6; 5__7 = 1; goto IL_0144; IL_0132: 5__7++; goto IL_0144; IL_0144: if (5__7 < _valuesOfEnum.Length) { if (markerTextHandler._hasFormat[5__7]) { string formatText = markerTextHandler.GetFormatText((MarkerFormatText)5__7, 5__6, 5__5); if (!string.IsNullOrEmpty(formatText)) { 5__3.Replace(_formatString[5__7], formatText); } <>2__current = null; <>1__state = 2; return true; } goto IL_0132; } text = 5__3.ToString(); if (!5__2.InvariantEquals(text)) { markerTextHandler.Marker.SetTitle(text); 5__2 = text; } 5__3.Clear(); 5__3.Append(markerTextHandler._baseText); <>2__current = _updateYielder; <>1__state = 3; return true; } } 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 EnemyAgent Agent; public NavMarker Marker; public HealthBarFormat.Worker Worker; private string _baseText; private bool[] _hasFormat; private bool _shouldUpdateRainbow; private Color _rainbow; private IEnumerator _updateLoop; private static readonly MarkerFormatText[] _valuesOfEnum; private static readonly string[] _formatString; private static readonly WaitForSeconds _updateYielder; static MarkerTextHandler() { _valuesOfEnum = null; _formatString = null; _updateYielder = WaitFor.Seconds[0.15f]; _valuesOfEnum = Enum.GetValues(typeof(MarkerFormatText)).Cast().ToArray(); _formatString = new string[_valuesOfEnum.Length]; for (int i = 0; i < _valuesOfEnum.Length; i++) { _formatString[i] = ("[" + Enum.GetName(typeof(MarkerFormatText), i) + "]").ToUpper(); } } internal static bool TextContainsAnyFormat(string baseText) { for (int i = 1; i < _valuesOfEnum.Length; i++) { if (baseText.InvariantContains(_formatString[i], ignoreCase: true)) { return true; } } return false; } [HideFromIl2Cpp] internal void ChangeBaseText(string baseText) { _baseText = baseText; _hasFormat = new bool[_valuesOfEnum.Length]; bool flag = false; for (int i = 1; i < _valuesOfEnum.Length; i++) { if (_baseText.InvariantContains(_formatString[i], ignoreCase: true)) { switch ((MarkerFormatText)i) { case MarkerFormatText.NAME: _baseText = _baseText.Replace(_formatString[i], ((GameDataBlockBase)(object)Agent.EnemyData).name, StringComparison.OrdinalIgnoreCase); _hasFormat[i] = false; break; case MarkerFormatText.GAMING: _baseText = _baseText.Replace(_formatString[i], _formatString[i], StringComparison.OrdinalIgnoreCase); _hasFormat[i] = true; flag = true; _shouldUpdateRainbow = true; break; default: _baseText = _baseText.Replace(_formatString[i], _formatString[i], StringComparison.OrdinalIgnoreCase); _hasFormat[i] = true; flag = true; break; } } else { _hasFormat[i] = false; } } if (!flag) { Marker.SetTitle(_baseText); Object.Destroy((Object)(object)this); } } private void OnEnable() { _updateLoop = UpdateText(); InitializeText(); } private void Update() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (_shouldUpdateRainbow) { _rainbow = Color.HSVToRGB(Mathf.Repeat(Clock.ExpeditionProgressionTime, 1f), 1f, 1f); } _updateLoop.MoveNext(); } [IteratorStateMachine(typeof(d__16))] [HideFromIl2Cpp] private IEnumerator UpdateText() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__16(0) { <>4__this = this }; } private void InitializeText() { NetworkManager.EnemyHealthState.TryGetState(((Agent)Agent).GlobalID, out var state); float maxHealth = state.maxHealth; float health = state.health; StringBuilder stringBuilder = new StringBuilder(_baseText); for (int i = 1; i < _valuesOfEnum.Length; i++) { if (_hasFormat[i]) { string formatText = GetFormatText((MarkerFormatText)i, health, maxHealth); if (!string.IsNullOrEmpty(formatText)) { stringBuilder.Replace(_formatString[i], formatText); } } } Marker.SetTitle(stringBuilder.ToString()); } private string GetFormatText(MarkerFormatText format, float health, float maxHealth) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) return format switch { MarkerFormatText.None => string.Empty, MarkerFormatText.NAME => string.Empty, MarkerFormatText.HP => health.ToString("0.00"), MarkerFormatText.HP_ROUND => Mathf.RoundToInt(health).ToString(), MarkerFormatText.HP_MAX => maxHealth.ToString("0.00"), MarkerFormatText.HP_MAX_ROUND => Mathf.RoundToInt(maxHealth).ToString(), MarkerFormatText.HP_PERCENT => (health / maxHealth * 100f).ToString("0.00"), MarkerFormatText.HP_PERCENT_ROUND => Mathf.RoundToInt(health / maxHealth * 100f).ToString(), MarkerFormatText.HP_BAR => Worker.BuildString(maxHealth, health), MarkerFormatText.GAMING => ColorUtility.ToHtmlStringRGB(_rainbow), _ => string.Empty, }; } private void OnDestroy() { Agent = null; Marker = null; Worker = null; _baseText = null; _hasFormat = null; } } public enum MarkerFormatText { None, NAME, HP, HP_ROUND, HP_MAX, HP_MAX_ROUND, HP_PERCENT, HP_PERCENT_ROUND, HP_BAR, GAMING } public class PulseRoutine { [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PulseRoutine <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; PulseRoutine pulseRoutine = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; if (pulseRoutine.PulseData.PatternData == null) { return false; } pulseRoutine._patternLength = pulseRoutine.PulseData.PatternData.Length; if (pulseRoutine._patternLength <= 1) { return false; } pulseRoutine._defaultColor = Color.op_Implicit(pulseRoutine.Agent.MaterialHandler.m_defaultGlowColor); float num2 = Math.Max(0f, pulseRoutine.PulseData.Duration); pulseRoutine._updateDelay = num2 / (float)pulseRoutine._patternLength; <>2__current = WaitFor.Seconds[pulseRoutine.StartDelay]; <>1__state = 1; return true; } case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } pulseRoutine.DoUpdate(); <>2__current = WaitFor.Seconds[pulseRoutine._updateDelay]; <>1__state = 2; return true; } 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 EnemyAgent Agent; public PulseEffectData PulseData; public float StartDelay; private float _updateDelay; private Color _defaultColor; private int _currentPatternIndex; private int _patternLength; [IteratorStateMachine(typeof(d__7))] public IEnumerator Routine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { <>4__this = this }; } private void DoUpdate() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0072: Expected I4, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Invalid comparison between Unknown and I4 //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Invalid comparison between Unknown and I4 //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Invalid comparison between Unknown and I4 if (!PulseData.Target.IsMatch(Agent) || (!((Agent)Agent).Alive && !PulseData.KeepOnDead)) { return; } if (!PulseData.AlwaysPulse) { AgentMode mode = ((AgentAI)Agent.AI).Mode; switch (mode - 1) { case 3: if (Agent.IsHibernationDetecting) { return; } break; case 0: { if (Agent.Locomotion.IsAttacking()) { return; } ES_StateEnum currentStateEnum = Agent.Locomotion.CurrentStateEnum; if ((int)currentStateEnum == 13 || currentStateEnum - 18 <= 1 || (int)currentStateEnum == 21) { return; } break; } case 2: { ScoutAntennaDetection antennaDetection = Agent.Locomotion.ScoutDetection.m_antennaDetection; if (!((Object)(object)antennaDetection == (Object)null) && antennaDetection.m_wantsToHaveTendrils) { return; } break; } } } if (_currentPatternIndex >= _patternLength) { _currentPatternIndex = 0; } PatternDataCache patternDataCache = PulseData.PatternData[_currentPatternIndex++]; float num = (float)patternDataCache.StepDuration * _updateDelay; if (patternDataCache.Progression >= 0f) { Color val = Color.Lerp(_defaultColor, PulseData.GlowColor, patternDataCache.Progression); Agent.Appearance.InterpolateGlow(val, num); } } } public enum EnemyState { Initial, Hibernate, Detect, Heartbeat, Wakeup, Scout, ScoutDetect } [InjectToIl2Cpp] internal sealed class ScannerHandler : MonoBehaviour { [CompilerGenerated] private sealed class d__23 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ScannerHandler <>4__this; public Color fromColor; public Color toColor; private Timer 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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) int num = <>1__state; ScannerHandler scannerHandler = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = new Timer(Il2CppValueField.op_Implicit(scannerHandler.InterpDuration)); goto IL_0083; case 1: <>1__state = -1; goto IL_0083; case 2: { <>1__state = -1; return false; } IL_0083: if (!5__2.TickAndCheckDone()) { float progress = 5__2.Progress; Color scannerColor = Color.Lerp(fromColor, toColor, progress); scannerHandler._ownerAgent.ScannerColor = scannerColor; <>2__current = null; <>1__state = 1; return true; } scannerHandler._ownerAgent.ScannerColor = toColor; scannerHandler._colorInterpolationCoroutine = null; scannerHandler.TryDisable(); <>2__current = null; <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__20 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ScannerHandler <>4__this; private Il2CppValueField 5__2; private WaitForSeconds 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ScannerHandler scannerHandler = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; 5__2 = scannerHandler.UpdateInterval; 5__3 = WaitFor.Seconds[Il2CppValueField.op_Implicit(scannerHandler.UpdateInterval)]; } scannerHandler.DoUpdate(); if (5__2 != scannerHandler.UpdateInterval) { 5__3 = WaitFor.Seconds[Il2CppValueField.op_Implicit(scannerHandler.UpdateInterval)]; } <>2__current = 5__3; <>1__state = 1; return true; } 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 Il2CppReferenceField OwnerAgent; public Il2CppValueField DefaultColor; public Il2CppValueField WakeupColor; public Il2CppValueField DetectionColor; public Il2CppValueField HeartbeatColor; public Il2CppValueField PatrolColor; public Il2CppValueField FeelerOutColor; public Il2CppValueField UsingDetectionColor; public Il2CppValueField UsingScoutColor; public Il2CppValueField InterpDuration; public Il2CppValueField UpdateInterval; public Il2CppValueField OptimizeOnAwake; private EnemyAgent _ownerAgent; private Coroutine _colorInterpolationCoroutine; private EnemyState _currentState; private Color _previousColor = Color.white; private Color _doneColor = Color.white; private bool _disableScriptAfterDone; private Coroutine _updateRoutine; private void OnEnable() { _ownerAgent = Il2CppReferenceField.op_Implicit(OwnerAgent); if ((Object)(object)_ownerAgent == (Object)null) { Logger.Error("EnemyAgent was missing! - Unable to start ScannerHandler!"); Object.Destroy((Object)(object)this); return; } if (_updateRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_updateRoutine); } _updateRoutine = ((MonoBehaviour)(object)this).StartCoroutine(UpdateLoop()); } [IteratorStateMachine(typeof(d__20))] [HideFromIl2Cpp] private IEnumerator UpdateLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__20(0) { <>4__this = this }; } [HideFromIl2Cpp] private void DoUpdate() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) EnemyState oldState = EnemyState.Initial; if (!_ownerAgent.IsInDetectedList) { if ((int)_ownerAgent.UpdateMode == 1 && HasNewState(ref oldState)) { _ownerAgent.ScannerColor = GetStateColor(_currentState); TryDisable(); } } else if (HasNewState(ref oldState)) { if (oldState == EnemyState.Initial) { _previousColor = GetStateColor(_currentState); _doneColor = _previousColor; } else { _previousColor = _ownerAgent.m_scannerColor; _doneColor = GetStateColor(_currentState); } StartColorInterpolation(_previousColor, _doneColor); } } [HideFromIl2Cpp] private void StartColorInterpolation(Color fromColor, Color toColor) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (_colorInterpolationCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_colorInterpolationCoroutine); } _colorInterpolationCoroutine = ((MonoBehaviour)(object)this).StartCoroutine(ColorInterpolation(fromColor, toColor)); } [IteratorStateMachine(typeof(d__23))] [HideFromIl2Cpp] private IEnumerator ColorInterpolation(Color fromColor, Color toColor) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(0) { <>4__this = this, fromColor = fromColor, toColor = toColor }; } [HideFromIl2Cpp] private void TryDisable() { if (_disableScriptAfterDone) { ((Behaviour)this).enabled = false; _disableScriptAfterDone = false; } } [HideFromIl2Cpp] private bool HasNewState(ref EnemyState oldState) { UpdateState(out var state); if (_currentState != state) { oldState = _currentState; _currentState = state; return true; } return false; } [HideFromIl2Cpp] private void UpdateState(out EnemyState state) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Invalid comparison between Unknown and I4 EnemyLocomotion locomotion = _ownerAgent.Locomotion; ES_StateEnum currentStateEnum = locomotion.CurrentStateEnum; if ((int)currentStateEnum <= 12) { if ((int)currentStateEnum == 2) { if (_ownerAgent.AI.m_scoutPath == null) { state = EnemyState.Wakeup; } else if ((int)locomotion.ScoutScream.m_state == 4) { state = EnemyState.Wakeup; } else { state = EnemyState.Scout; } return; } if ((int)currentStateEnum == 12) { state = EnemyState.ScoutDetect; return; } } else { if ((int)currentStateEnum == 14) { if (locomotion.Hibernate.m_heartbeatActive) { state = EnemyState.Heartbeat; } else { state = ((!_ownerAgent.IsHibernationDetecting) ? EnemyState.Hibernate : EnemyState.Detect); } return; } if ((int)currentStateEnum == 17) { state = EnemyState.Hibernate; return; } if ((int)currentStateEnum == 24) { state = _currentState; return; } } state = EnemyState.Wakeup; } [HideFromIl2Cpp] private Color GetStateColor(EnemyState state) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) return Il2CppValueField.op_Implicit((Il2CppValueField)(state switch { EnemyState.Hibernate => DefaultColor, EnemyState.Detect => DetectionColor, EnemyState.Heartbeat => HeartbeatColor, EnemyState.Wakeup => WakeupColor, EnemyState.Scout => PatrolColor, EnemyState.ScoutDetect => FeelerOutColor, _ => DefaultColor, })); } private void OnDestroy() { _ownerAgent = null; _colorInterpolationCoroutine = null; } } [InjectToIl2Cpp] internal sealed class EnemySilhouette : MonoBehaviour { public Material SilhouetteMaterial; private Color _latestColorB = Color.clear; [HideFromIl2Cpp] public void EnableSilhouette() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetColorB(_latestColorB); } [HideFromIl2Cpp] public void DisableSilhouette() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SetColorB(Color.clear); } [HideFromIl2Cpp] public void SetColorA(Color color) { //IL_000b: 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) SilhouetteMaterial.SetVector("_ColorA", Color.op_Implicit(color)); } [HideFromIl2Cpp] public void SetColorB(Color color) { //IL_000b: 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) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) SilhouetteMaterial.SetVector("_ColorB", Color.op_Implicit(color)); _latestColorB = color; } private void OnDestroy() { SilhouetteMaterial = null; } } [InjectToIl2Cpp] internal sealed class SilhouetteHandler : MonoBehaviour { public EnemyAgent OwnerAgent; public Color DefaultColor; public bool RequireTag; public bool ReplaceColorWithMarker; public bool KeepOnDead; public float DeadEffectDelay; private bool _tagUpdateDone = true; private NavMarker _enemyMarker; private EnemySilhouette[] _silhouettes; private bool _eventRegistered; private void Start() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) _silhouettes = Il2CppArrayBase.op_Implicit(((Component)this).GetComponentsInChildren(true)); EnemySilhouette[] silhouettes = _silhouettes; foreach (EnemySilhouette obj in silhouettes) { Renderer component = ((Component)obj).GetComponent(); obj.SilhouetteMaterial = component.material; if ((int)component.shadowCastingMode == 3 || (int)component.shadowCastingMode == 0) { component.forceRenderingOff = false; component.shadowCastingMode = (ShadowCastingMode)0; ((C_CullBucket)OwnerAgent.MovingCuller.Culler).Renderers.Add(component); component.enabled = true; } } if (RequireTag || ReplaceColorWithMarker) { EnemyMarkerEvents.Marked += OnMarked; _eventRegistered = true; } if (!RequireTag) { SetColorB(DefaultColor); Show(); } } private void FixedUpdate() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (!((Agent)OwnerAgent).Alive && !KeepOnDead) { KillSilhouette(DeadEffectDelay); ((Behaviour)this).enabled = false; } if (_tagUpdateDone) { return; } if (!OwnerAgent.IsTagged) { if (RequireTag) { Hide(); } _tagUpdateDone = true; } float num = 0f; Color val = DefaultColor; if (TryGetEnemyMarkerSpriteRenderer(out SpriteRenderer renderer)) { num = renderer.color.a; val = renderer.color; } if (RequireTag) { Color colorB = (ReplaceColorWithMarker ? ((Color)(ref val)).AlphaMultiplied(num) : ((Color)(ref DefaultColor)).AlphaMultiplied(num)); SetColorB(colorB); } else { Color colorB2 = Color.Lerp(DefaultColor, val, num); SetColorB(colorB2); } } [HideFromIl2Cpp] private void OnMarked(EnemyAgent agent, NavMarker marker) { if (((Agent)agent).GlobalID == ((Agent)OwnerAgent).GlobalID) { _enemyMarker = marker; _tagUpdateDone = false; if (RequireTag) { Show(); } } } [HideFromIl2Cpp] public void KillSilhouette(float delay) { for (int i = 0; i < _silhouettes.Length; i++) { CoroutineManager.BlinkOut(((Component)_silhouettes[i]).gameObject, delay); } } [HideFromIl2Cpp] public void Show() { for (int i = 0; i < _silhouettes.Length; i++) { _silhouettes[i].EnableSilhouette(); } } [HideFromIl2Cpp] public void Hide() { for (int i = 0; i < _silhouettes.Length; i++) { _silhouettes[i].DisableSilhouette(); } } [HideFromIl2Cpp] public void SetColorA(Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _silhouettes.Length; i++) { _silhouettes[i].SetColorA(color); } } [HideFromIl2Cpp] public void SetColorB(Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _silhouettes.Length; i++) { _silhouettes[i].SetColorB(color); } } [HideFromIl2Cpp] private bool TryGetEnemyMarkerSpriteRenderer(out SpriteRenderer renderer) { if ((Object)(object)_enemyMarker == (Object)null && (Object)(object)_enemyMarker.m_enemySubObj == (Object)null) { renderer = null; return false; } NavMarkerComponent enemySubObj = _enemyMarker.m_enemySubObj; if (enemySubObj.m_sprites == null) { renderer = null; return false; } if (((Il2CppArrayBase)(object)enemySubObj.m_sprites).Length < 1) { renderer = null; return false; } renderer = ((Il2CppArrayBase)(object)enemySubObj.m_sprites)[0]; return (Object)(object)renderer != (Object)null; } private void OnDestroy() { if (_eventRegistered) { EnemyMarkerEvents.Marked -= OnMarked; } OwnerAgent = null; _enemyMarker = null; _silhouettes = null; } } } namespace EEC.EnemyCustomizations.EnemyAbilities { public class AbilitySettingBase { public IAbility Ability; public string AbilityName { get; set; } public bool TryCache() { return EnemyAbilityManager.TryGetAbility(AbilityName, out Ability); } } public abstract class EnemyAbilityCustomBase : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent where T : AbilitySettingBase { public T[] Abilities { get; set; } = Array.Empty(); public sealed override void OnConfigLoaded() { Abilities = CacheAbilities(Abilities); OnConfigLoadedPost(); } protected T[] CacheAbilities(T[] settings) { List list = new List(settings); foreach (T val in settings) { if (!val.TryCache()) { LogError("Key: [" + val.AbilityName + "] was missing, unable to apply ability!"); list.Remove(val); } } return list.ToArray(); } public virtual void OnConfigLoadedPost() { } public void OnSpawned(EnemyAgent agent) { int num = Abilities.Length; for (int i = 0; i < num; i++) { T val = Abilities[i]; AbilityBehaviour behaviour = val.Ability.RegisterBehaviour(agent); OnBehaviourAssigned(agent, behaviour, val); } OnSpawnedPost(agent); } public static void DoTriggerDelayed(IAbility ability, EnemyAgent agent, float delay, bool useClientPos) { IAbility ability2 = ability; EnemyAgent agent2 = agent; Task.Factory.StartNew((Func)async delegate { await Task.Delay((int)Math.Round(delay * 1000f)); ThreadDispatcher.Dispatch((Action)delegate { ability2?.TriggerSync(agent2, useClientPos); }); }); } public virtual void OnBehaviourAssigned(EnemyAgent agent, AbilityBehaviour behaviour, T setting) { } public virtual void OnSpawnedPost(EnemyAgent agent) { } } public sealed class BehaviourAbilityCustom : EnemyAbilityCustomBase { public override string GetProcessName() { return "BehaviourAbility"; } public override void OnConfigLoadedPost() { BehaviourAbilitySetting[] abilities = base.Abilities; foreach (BehaviourAbilitySetting obj in abilities) { obj.DistanceWithLOS.ShouldCheckLOS = true; obj.DistanceWithoutLOS.ShouldCheckLOS = false; } } public override void OnBehaviourAssigned(EnemyAgent agent, AbilityBehaviour behaviour, BehaviourAbilitySetting setting) { BehaviourUpdateRoutine behaviourUpdateRoutine = new BehaviourUpdateRoutine { Agent = agent, Behaviour = behaviour, Setting = setting }; ((MonoBehaviour)(object)agent.AI).StartCoroutine(behaviourUpdateRoutine.Routine()); } } public sealed class BehaviourAbilitySetting : AbilitySettingBase { public float UpdateInterval { get; set; } = 0.15f; public ExitConditionTarget ForceExitOnConditionMismatch { get; set; } = ExitConditionTarget.None; public AgentModeTarget AllowedMode { get; set; } = AgentModeTarget.Agressive; public float AllowedModeTransitionTime { get; set; } public bool KeepOnDead { get; set; } public bool AllowWhileAttack { get; set; } public bool RequireEABAllowed { get; set; } public EnemyStateSetting State { get; set; } = new EnemyStateSetting(); public DistanceSetting DistanceWithLOS { get; set; } = new DistanceSetting(); public DistanceSetting DistanceWithoutLOS { get; set; } = new DistanceSetting(); public CooldownSetting Cooldown { get; set; } = new CooldownSetting(); } public sealed class EnemyStateSetting { public enum StateCheckingBehaviour { None, AllowStates, DisallowStates } public StateCheckingBehaviour Mode { get; set; } public ES_StateEnum[] States { get; set; } = Array.Empty(); public bool CanUseAbility(ES_StateEnum currentState) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) return Mode switch { StateCheckingBehaviour.AllowStates => States.Contains(currentState), StateCheckingBehaviour.DisallowStates => !States.Contains(currentState), _ => true, }; } } public sealed class CooldownSetting { public bool Enabled { get; set; } public float InitCooldown { get; set; } public float Cooldown { get; set; } = 5f; } public sealed class DistanceSetting { public enum DistanceCheckingBehaviour { AlwaysAllow, AlwaysDisallow, UsingDistance } public bool ShouldCheckLOS; public DistanceCheckingBehaviour Mode { get; set; } public float Min { get; set; } public float Max { get; set; } = 1f; public bool CanUseAbility(bool hasLosOnTarget, float distanceToClosestTarget) { switch (Mode) { case DistanceCheckingBehaviour.AlwaysAllow: return true; case DistanceCheckingBehaviour.AlwaysDisallow: return false; default: if (ShouldCheckLOS != hasLosOnTarget) { return true; } if (distanceToClosestTarget < Min) { return false; } if (distanceToClosestTarget > Max) { return false; } return true; } } } public sealed class DeathAbilityCustom : EnemyAbilityCustomBase, IEnemyDeadEvent, IEnemyEvent { public override string GetProcessName() { return "DeathAbility"; } public void OnDead(EnemyAgent agent) { DeathAbilitySetting[] abilities = base.Abilities; foreach (DeathAbilitySetting deathAbilitySetting in abilities) { if (!SNet.IsMaster || !deathAbilitySetting.AllowedMode.IsMatch(agent)) { break; } EnemyAbilityCustomBase.DoTriggerDelayed(deathAbilitySetting.Ability, agent, deathAbilitySetting.Delay, useClientPos: true); } } } public sealed class DeathAbilitySetting : AbilitySettingBase { public AgentModeTarget AllowedMode { get; set; } = AgentModeTarget.Agressive; public float Delay { get; set; } } [CallConstructorOnLoad] public static class EnemyAbilityManager { private static ushort _syncIDBuffer; private static readonly AbilityEvent _abilityEvent; private static readonly Dictionary _abilities; private static readonly Dictionary _abilityIDLookup; private static bool _allAssetLoaded; static EnemyAbilityManager() { _syncIDBuffer = 1; _abilityEvent = new AbilityEvent(); _abilities = new Dictionary(); _abilityIDLookup = new Dictionary(); _allAssetLoaded = false; _abilityEvent.Setup(); _abilityEvent.OnReceive += OnReceiveEvent; _allAssetLoaded = AssetEvents.IsAllAssetLoaded; AssetEvents.AllAssetLoaded += AllAssetLoaded; } private static void AllAssetLoaded() { _allAssetLoaded = true; Setup(); } public static void AddAbility(IAbility ability) { string text = ability.Name.ToLowerInvariant(); if (string.IsNullOrEmpty(text)) { Logger.Error("EnemyAbility Name cannot be empty or null!"); } else if (_abilities.ContainsKey(text)) { Logger.Error("Duplicated EnemyAbility Name was detected! : \"" + text + "\""); } else { _abilities.Add(text, ability); } } public static IAbility GetAbility(string key) { key = key.ToLowerInvariant(); _abilities.TryGetValue(key, out IAbility value); return value; } public static bool TryGetAbility(string key, out IAbility ability) { return _abilities.TryGetValue(key.ToLowerInvariant(), out ability); } public static void Setup() { if (!_allAssetLoaded) { return; } foreach (IAbility value in _abilities.Values) { ushort syncIDBuffer = _syncIDBuffer; _abilityIDLookup[syncIDBuffer] = value; value.Setup(syncIDBuffer); _syncIDBuffer++; } } public static void Clear() { foreach (IAbility value in _abilities.Values) { value.Unload(); } _abilities.Clear(); _syncIDBuffer = 1; _abilityIDLookup.Clear(); } public static void SendEvent(ushort syncID, ushort enemyID, AbilityPacketType type, bool useClientPos = false) { if (SNet.IsMaster) { _abilityEvent.Send(new AbilityEvent.Packet { Type = type, UseClientPos = useClientPos, SyncID = syncID, EnemyID = enemyID }); } } private static void OnReceiveEvent(AbilityEvent.Packet packet) { if (_abilityIDLookup.TryGetValue(packet.SyncID, out IAbility value)) { switch (packet.Type) { case AbilityPacketType.DoExit: value.Exit(packet.EnemyID); return; case AbilityPacketType.DoTrigger: value.Trigger(packet.EnemyID, packet.UseClientPos); return; case AbilityPacketType.DoExitAll: value.ExitAll(); return; case AbilityPacketType.DoTriggerAll: value.TriggerAll(); return; } Logger.Error($"PacketType was invalid: {packet.Type}"); } else { Logger.Error($"Packet was invalid: {packet.SyncID} {packet.EnemyID} {packet.Type}"); } } } public class AbilityEvent : SyncedEvent { public struct Packet { public AbilityPacketType Type; public bool UseClientPos; public ushort SyncID; public ushort EnemyID; } public override string GUID => "ABE"; } public enum AbilityPacketType : byte { DoTrigger, DoTriggerAll, DoExit, DoExitAll } public sealed class LimbDestroyedAbilityCustom : EnemyAbilityCustomBase { public override string GetProcessName() { return "LimbDestroyedAbility"; } public override void OnBehaviourAssigned(EnemyAgent agent, AbilityBehaviour behaviour, LimbDestroyedAbilitySetting setting) { LimbDestroyedAbilitySetting setting2 = setting; EnemyAgent agent2 = agent; Dam_EnemyDamageBase componentInChildren = ((Component)agent2).GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null) { return; } string text = setting2.Limbs.SingleOrDefault((string x) => x.InvariantEquals("All", ignoreCase: true)); foreach (Dam_EnemyDamageLimb limb in (Il2CppArrayBase)(object)componentInChildren.DamageLimbs) { if (Logger.VerboseLogAllowed) { LogVerbose(" - Found Limb: " + ((Object)limb).name); } if (setting2.Limbs.SingleOrDefault((string x) => x.InvariantEquals(((Object)limb).name, ignoreCase: true)) == null && text == null) { continue; } limb.OnLimbDestroyed += Action.op_Implicit((Action)delegate { if (SNet.IsMaster && setting2.AllowedMode.IsMatch(agent2)) { EnemyAbilityCustomBase.DoTriggerDelayed(setting2.Ability, agent2, setting2.Delay, useClientPos: true); } }); } } } public sealed class LimbDestroyedAbilitySetting : AbilitySettingBase { public string[] Limbs { get; set; } = Array.Empty(); public AgentModeTarget AllowedMode { get; set; } = AgentModeTarget.Agressive; public float Delay { get; set; } } } namespace EEC.EnemyCustomizations.EnemyAbilities.Handlers { public sealed class BehaviourUpdateRoutine { [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BehaviourUpdateRoutine <>4__this; private WaitForSeconds 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_002a: 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) int num = <>1__state; BehaviourUpdateRoutine behaviourUpdateRoutine = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; behaviourUpdateRoutine._latestMode = ((AgentAI)behaviourUpdateRoutine.Agent.AI).Mode; 5__2 = WaitFor.Seconds[behaviourUpdateRoutine.Setting.UpdateInterval]; } behaviourUpdateRoutine.DoUpdate(); <>2__current = 5__2; <>1__state = 1; return true; } 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 EnemyAgent Agent; public AbilityBehaviour Behaviour; public BehaviourAbilitySetting Setting; private AgentMode _latestMode; private LazyTimer _modeTransitionTimer; private LazyTimer _cooldownTimer; private bool _hasInitialTimerDone; [IteratorStateMachine(typeof(d__7))] public IEnumerator Routine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { <>4__this = this }; } private void DoUpdate() { if (!SNet.IsMaster) { return; } bool canUseAbility = true; bool shouldExitOnMismatch = false; UpdateUseOrExit(Setting.KeepOnDead || ((Agent)Agent).Alive, ExitConditionType.Dead); UpdateUseOrExit(CheckAllowedModeCondition(), ExitConditionType.Mode); UpdateUseOrExit(CheckAllowedStateCondition(), ExitConditionType.State); UpdateUseOrExit(CheckAttackingCondition(), ExitConditionType.Attack); UpdateUseOrExit(!Setting.RequireEABAllowed || Agent.Abilities.CanTriggerAbilities, ExitConditionType.EABAllowed); UpdateUseOrExit(CheckDistanceCondition(), ExitConditionType.Distance); if (!canUseAbility) { if (shouldExitOnMismatch && Behaviour.Executing) { Behaviour.DoExitSync(); } return; } if (Setting.Cooldown.Enabled) { if (!_cooldownTimer.TickAndCheckDone()) { return; } if (!_hasInitialTimerDone) { _cooldownTimer.Reset(Setting.Cooldown.InitCooldown); _hasInitialTimerDone = true; return; } _cooldownTimer.Reset(Setting.Cooldown.Cooldown); } Behaviour.DoTriggerSync(useClientPos: false); void UpdateUseOrExit(bool checkCondition, ExitConditionType exitType) { canUseAbility &= checkCondition; shouldExitOnMismatch |= !checkCondition && Setting.ForceExitOnConditionMismatch.HasFlag(exitType); } } private bool CheckAllowedModeCondition() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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) if (_latestMode != ((AgentAI)Agent.AI).Mode) { _latestMode = ((AgentAI)Agent.AI).Mode; _modeTransitionTimer.Reset(Setting.AllowedModeTransitionTime); } if (!_modeTransitionTimer.TickAndCheckDone()) { return false; } return Setting.AllowedMode.IsMatch(Agent); } private bool CheckAllowedStateCondition() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) return Setting.State.CanUseAbility(Agent.Locomotion.CurrentStateEnum); } private bool CheckAttackingCondition() { if (!Setting.AllowWhileAttack) { return ((Il2CppObjectBase)((StateMachine)(object)Agent.Locomotion).CurrentState).TryCast() == null; } return true; } private bool CheckDistanceCondition() { //IL_0062: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) bool flag = false; float num = float.MaxValue; float distanceToClosestTarget; if (((AgentAI)Agent.AI).IsTargetValid) { distanceToClosestTarget = ((AgentAI)Agent.AI).Target.m_distance; flag = ((AgentAI)Agent.AI).Target.m_hasLineOfSight; } else { for (int i = 0; i < PlayerManager.PlayerAgentsInLevel.Count; i++) { PlayerAgent val = PlayerManager.PlayerAgentsInLevel[i]; Vector3 val2 = ((Agent)Agent).EyePosition - ((Agent)val).EyePosition; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (num >= sqrMagnitude) { num = sqrMagnitude; flag = !Physics.Linecast(((Agent)Agent).EyePosition, ((Agent)val).EyePosition, LayerManager.MASK_WORLD); } } if (num == float.MaxValue) { flag = false; distanceToClosestTarget = float.MaxValue; } else { distanceToClosestTarget = Mathf.Sqrt(num); } } return (flag ? Setting.DistanceWithLOS : Setting.DistanceWithoutLOS).CanUseAbility(flag, distanceToClosestTarget); } } } namespace EEC.EnemyCustomizations.EnemyAbilities.Events { public delegate void GenericAbilitiesHandler(EnemyAbilities enemyAbilities); public delegate void AbilitiesDamageHanalder(EnemyAbilities enemyAbilities, float damage); public static class EnemyAbilitiesEvents { public static event AbilitiesDamageHanalder TakeDamage; public static event GenericAbilitiesHandler Dead; public static event GenericAbilitiesHandler Hitreact; internal static void OnTakeDamage(EnemyAbilities enemyAbilities, float damage) { EnemyAbilitiesEvents.TakeDamage?.Invoke(enemyAbilities, damage); } internal static void OnDead(EnemyAbilities enemyAbilities) { EnemyAbilitiesEvents.Dead?.Invoke(enemyAbilities); } internal static void OnHitreact(EnemyAbilities enemyAbilities) { EnemyAbilitiesEvents.Hitreact?.Invoke(enemyAbilities); } } } namespace EEC.EnemyCustomizations.EnemyAbilities.Events.Inject { [HarmonyPatch(typeof(EnemyAbilities))] internal static class Inject_EnemyAbilities { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("OnTakeDamage")] internal static void Post_OnTakeDamage(float damage, EnemyAbilities __instance) { EnemyAbilitiesEvents.OnTakeDamage(__instance, damage); } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("OnHitreact")] internal static void Post_OnHitreact(EnemyAbilities __instance) { EnemyAbilitiesEvents.OnHitreact(__instance); } [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("OnDead")] internal static void Post_OnDead(EnemyAbilities __instance) { EnemyAbilitiesEvents.OnDead(__instance); } } } namespace EEC.EnemyCustomizations.EnemyAbilities.Abilities { public abstract class AbilityBase : IAbility where T : AbilityBehaviour, new() { private bool _isBehavioursDirty = true; private readonly Dictionary _behaviourLookup = new Dictionary(); private readonly List _behaviours = new List(); private AbilityBehaviour[] _behavioursCache; public string Name { get; set; } = string.Empty; [JsonIgnore] public AbilityBehaviour[] Behaviours { get { if (_isBehavioursDirty) { _behavioursCache = _behaviours.ToArray(); _isBehavioursDirty = false; } return _behavioursCache; } } public ushort SyncID { get; private set; } public void Setup(ushort syncID) { SyncID = syncID; OnAbilityLoaded(); EnemyEvents.Despawn += EnemyDespawn; } private void EnemyDespawn(EnemyAgent agent) { if (_behaviourLookup.TryGetValue(((Agent)agent).GlobalID, out AbilityBehaviour value)) { value.Unload(); _behaviourLookup.Remove(((Agent)agent).GlobalID); } } public void Unload() { _behaviours.Clear(); OnAbilityUnloaded(); EnemyEvents.Despawn -= EnemyDespawn; } public void TriggerSync(ushort enemyID, bool useClientPos) { EnemyAbilityManager.SendEvent(SyncID, enemyID, AbilityPacketType.DoTrigger, useClientPos); } public void Trigger(ushort enemyID, bool useClientPos) { if (TryGetBehaviour(enemyID, out AbilityBehaviour behaviour)) { behaviour.DoTrigger(useClientPos); } } public void TriggerAllSync() { EnemyAbilityManager.SendEvent(SyncID, 0, AbilityPacketType.DoTriggerAll); } public void TriggerAll() { foreach (AbilityBehaviour behaviour in _behaviours) { behaviour.DoTrigger(useClientPos: false); } } public void ExitSync(ushort enemyID) { EnemyAbilityManager.SendEvent(SyncID, enemyID, AbilityPacketType.DoExit); } public void Exit(ushort enemyID) { if (TryGetBehaviour(enemyID, out AbilityBehaviour behaviour)) { behaviour.DoExit(); } } public void ExitAllSync() { EnemyAbilityManager.SendEvent(SyncID, 0, AbilityPacketType.DoExitAll); } public void ExitAll() { foreach (AbilityBehaviour behaviour in _behaviours) { behaviour.DoExit(); } } public AbilityBehaviour RegisterBehaviour(EnemyAgent agent) { ushort globalID = ((Agent)agent).GlobalID; if (_behaviourLookup.TryGetValue(globalID, out AbilityBehaviour value)) { return value; } T val = new T(); val.Setup(this, agent); _behaviours.Add(val); _isBehavioursDirty = true; _behaviourLookup[globalID] = val; OnBehaviourAssigned(agent, val); return val; } public virtual void OnAbilityLoaded() { } public virtual void OnAbilityUnloaded() { } public virtual void OnBehaviourAssigned(EnemyAgent agent, T behaviour) { } public bool TryGetBehaviour(ushort enemyID, out AbilityBehaviour behaviour) { return _behaviourLookup.TryGetValue(enemyID, out behaviour); } public void LogVerbose(string str) { LogFormatDebug(str, verbose: true); } public void LogDev(string str) { LogFormatDebug(str, verbose: false); } public void LogError(string str) { LogFormat((LogLevel)2, str); } public void LogWarning(string str) { LogFormat((LogLevel)4, str); } private void LogFormat(LogLevel level, string str) { //IL_0005: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) ManualLogSource logInstance = Logger.LogInstance; bool flag = default(bool); BepInExLogInterpolatedStringHandler val = new BepInExLogInterpolatedStringHandler(3, 2, level, ref flag); if (flag) { val.AppendLiteral("["); val.AppendFormatted(Name); val.AppendLiteral("] "); val.AppendFormatted(str); } logInstance.Log(level, val); } private void LogFormatDebug(string str, bool verbose) { if (verbose) { Logger.Verbose("[" + Name + "] " + str); } else { Logger.Debug("[" + Name + "] " + str); } } } public abstract class AbilityBehaviour : AbilityBehaviour where AB : class, IAbility { public AB Ability => base.BaseAbility as AB; } public abstract class AbilityBehaviour { [CompilerGenerated] private sealed class d__36 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public AbilityBehaviour <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__36(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; AbilityBehaviour abilityBehaviour = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; } abilityBehaviour.DoUpdate(); <>2__current = null; <>1__state = 1; return true; } 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 const float LAZYUPDATE_DELAY = 0.15f; private Timer _lazyUpdateTimer = new Timer(0.15f); private bool _executing; private int _standStillStack; private ES_StateEnum _prevState; private INavigation _navAgent; public IAbility BaseAbility { get; private set; } public EnemyAgent Agent { get; private set; } public bool AgentDestroyed { get; private set; } public bool IsMasterOnlyAndClient { get { if (IsHostOnlyBehaviour) { return !SNet.IsMaster; } return false; } } public bool Executing { get { return _executing; } private set { bool flag = value; if (flag != _executing) { _executing = flag; if (!AllowEABAbilityWhileExecuting) { Agent.Abilities.CanTriggerAbilities = !_executing && Agent.CanUseAbilities(); } } } } public bool StandStill { get { return _standStillStack > 0; } set { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Invalid comparison between Unknown and I4 //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Invalid comparison between Unknown and I4 //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_00f0: Invalid comparison between Unknown and I4 //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected I4, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Invalid comparison between Unknown and I4 bool standStill = StandStill; _standStillStack = Math.Max(0, _standStillStack + (value ? 1 : (-1))); if (standStill == StandStill) { return; } if (StandStill) { ES_StateEnum val = (_prevState = Agent.Locomotion.CurrentStateEnum); if (((int)val != 7 && (int)val != 29) || (int)Agent.Locomotion.Hitreact.CurrentReactionType != 5) { _navAgent.isStopped = true; _navAgent.velocity = Vector3.zero; Agent.Locomotion.ChangeState((ES_StateEnum)1); } } else { if ((int)_prevState == 1) { return; } ES_StateEnum currentStateEnum = Agent.Locomotion.CurrentStateEnum; if ((int)currentStateEnum <= 17) { if ((int)currentStateEnum == 7) { return; } switch (currentStateEnum - 11) { case 0: case 2: case 4: case 6: return; } } else if ((int)currentStateEnum == 29 || currentStateEnum - 31 <= 1) { return; } if ((int)_prevState == 14 && ((Il2CppObjectBase)((StateMachine)(object)Agent.AI.m_behaviour).CurrentState).TryCast() != null) { Agent.Locomotion.ChangeState((ES_StateEnum)14); } else { ((StateMachine)(object)Agent.Locomotion).ChangeState((ES_Base)(object)Agent.Locomotion.PathMove); } } } } public abstract bool RunUpdateOnlyWhileExecuting { get; } public abstract bool AllowEABAbilityWhileExecuting { get; } public abstract bool IsHostOnlyBehaviour { get; } public virtual bool IsHostOnlySetup => IsHostOnlyBehaviour; public void Setup(IAbility baseAbility, EnemyAgent agent) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown BaseAbility = baseAbility; Agent = agent; _navAgent = ((AgentAI)Agent.AI).m_navMeshAgent; ((MonoBehaviour)(object)Agent.AI).StartCoroutine(Update()); Agent.Locomotion.AddState((ES_StateEnum)1, (ES_Base)new ES_StandStill()); EnemyEvents.Despawn += Despawn_Del; EnemyAbilitiesEvents.TakeDamage += TakeDamage_Del; EnemyAbilitiesEvents.Dead += Dead_Del; EnemyAbilitiesEvents.Hitreact += Hitreact_Del; DoSetup(); } public void Unload() { EnemyEvents.Despawn -= Despawn_Del; EnemyAbilitiesEvents.TakeDamage -= TakeDamage_Del; EnemyAbilitiesEvents.Dead -= Dead_Del; EnemyAbilitiesEvents.Hitreact -= Hitreact_Del; } [IteratorStateMachine(typeof(d__36))] private IEnumerator Update() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__36(0) { <>4__this = this }; } private void Despawn_Del(EnemyAgent agent) { if (((Agent)agent).GlobalID == ((Agent)Agent).GlobalID) { AgentDestroyed = true; } } private void TakeDamage_Del(EnemyAbilities abilities, float damage) { if (!AgentDestroyed && ((Agent)abilities.m_agent).GlobalID == ((Agent)Agent).GlobalID) { DoTakeDamage(damage); } } private void Dead_Del(EnemyAbilities abilities) { if (!AgentDestroyed && ((Agent)abilities.m_agent).GlobalID == ((Agent)Agent).GlobalID) { DoDead(); EnemyAbilitiesEvents.TakeDamage -= TakeDamage_Del; EnemyAbilitiesEvents.Dead -= Dead_Del; EnemyAbilitiesEvents.Hitreact -= Hitreact_Del; EnemyLimbEvents.Destroyed -= LimbDestroyed_Del; } } private void LimbDestroyed_Del(Dam_EnemyDamageLimb limb) { if (limb.GetBaseAgent().GlobalID == ((Agent)Agent).GlobalID) { DoLimbDestroyed(limb); } } private void Hitreact_Del(EnemyAbilities abilities) { if (((Agent)abilities.m_agent).GlobalID == ((Agent)Agent).GlobalID) { DoHitreact(); } } private void DoSetup() { if (!IsHostOnlySetup || SNet.IsMaster) { OnSetup(); } } private void DoDead() { if (!IsMasterOnlyAndClient) { OnDead(); } } private void DoUpdate() { if (!IsMasterOnlyAndClient && (!RunUpdateOnlyWhileExecuting || Executing)) { OnUpdate(); DoAbilityUpdate(); } } private void DoAbilityUpdate() { if (Executing && !AgentDestroyed) { OnAbilityUpdate(); DoAbilityLazyUpdate(); } } private void DoAbilityLazyUpdate() { if (_lazyUpdateTimer.TickAndCheckDone()) { _lazyUpdateTimer.Reset(); OnAbilityLazyUpdate(); } } public void DoTriggerSync(bool useClientPos) { EnemyAbilityManager.SendEvent(BaseAbility.SyncID, ((Agent)Agent).GlobalID, AbilityPacketType.DoTrigger, useClientPos); } public void DoTrigger(bool useClientPos) { DoEnter(useClientPos); } public void DoEnterSync() { EnemyAbilityManager.SendEvent(BaseAbility.SyncID, ((Agent)Agent).GlobalID, AbilityPacketType.DoTrigger); } public void DoEnter(bool useClientPos) { if (!IsMasterOnlyAndClient && !Executing && !AgentDestroyed) { Executing = true; if (useClientPos) { OnEnterUseClientPos(); } else { OnEnter(); } } } public void DoExitSync() { EnemyAbilityManager.SendEvent(BaseAbility.SyncID, ((Agent)Agent).GlobalID, AbilityPacketType.DoExit); } public void DoExit() { if (!IsMasterOnlyAndClient && Executing && !AgentDestroyed) { OnExit(); Executing = false; } } private void DoTakeDamage(float damage) { if (!IsMasterOnlyAndClient) { OnTakeDamage(damage); } } private void DoHitreact() { if (!IsMasterOnlyAndClient) { OnHitreact(); } } private void DoLimbDestroyed(Dam_EnemyDamageLimb limb) { if (!IsMasterOnlyAndClient) { OnLimbDestroyed(limb); } } protected virtual void OnAbilityUpdate() { } protected virtual void OnEnter() { } protected virtual void OnEnterUseClientPos() { OnEnter(); } protected virtual void OnAbilityLazyUpdate() { } protected virtual void OnExit() { } protected virtual void OnSetup() { } protected virtual void OnUpdate() { } protected virtual void OnDead() { } protected virtual void OnTakeDamage(float damage) { } protected virtual void OnHitreact() { } protected virtual void OnLimbDestroyed(Dam_EnemyDamageLimb limb) { } public void LogVerbose(string str) { LogFormatDebug(str, verbose: true); } public void LogDev(string str) { LogFormatDebug(str, verbose: false); } public void LogError(string str) { LogFormat((LogLevel)2, str); } public void LogWarning(string str) { LogFormat((LogLevel)4, str); } private void LogFormat(LogLevel level, string str) { //IL_0005: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) ManualLogSource logInstance = Logger.LogInstance; bool flag = default(bool); BepInExLogInterpolatedStringHandler val = new BepInExLogInterpolatedStringHandler(6, 3, level, ref flag); if (flag) { val.AppendLiteral("["); val.AppendFormatted(BaseAbility.Name); val.AppendLiteral("] ["); val.AppendFormatted(((Object)Agent).name); val.AppendLiteral("] "); val.AppendFormatted(str); } logInstance.Log(level, val); } private void LogFormatDebug(string str, bool verbose) { if (verbose) { Logger.Verbose($"[{BaseAbility.Name}] [{((Object)Agent).name}] {str}"); } else { Logger.Debug($"[{BaseAbility.Name}] [{((Object)Agent).name}] {str}"); } } } public interface IAbility { string Name { get; set; } ushort SyncID { get; } AbilityBehaviour[] Behaviours { get; } void Setup(ushort syncID); void Unload(); void TriggerSync(EnemyAgent agent, bool clientPos = false) { TriggerSync(((Agent)agent).GlobalID, clientPos); } void TriggerSync(ushort enemyID, bool clientPos = false); void Trigger(EnemyAgent agent, bool clientPos) { Trigger(((Agent)agent).GlobalID, clientPos); } void Trigger(ushort enemyID, bool clientPos); void TriggerAllSync(); void TriggerAll(); void ExitSync(EnemyAgent agent) { ExitSync(((Agent)agent).GlobalID); } void ExitSync(ushort enemyID); void Exit(EnemyAgent agent) { Exit(((Agent)agent).GlobalID); } void Exit(ushort enemyID); void ExitAllSync(); void ExitAll(); AbilityBehaviour RegisterBehaviour(EnemyAgent agent); bool TryGetBehaviour(EnemyAgent agent, out AbilityBehaviour behaviour) { return TryGetBehaviour(((Agent)agent).GlobalID, out behaviour); } bool TryGetBehaviour(ushort enemyID, out AbilityBehaviour behaviour); } public sealed class ChainedAbility : AbilityBase { public class EventBlock : AbilitySettingBase { public float Delay { get; set; } } public EventBlock[] Abilities { get; set; } = Array.Empty(); public float ExitDelay { get; set; } public bool ExitWhenAllFinished { get; set; } = true; public bool ExitAllInForceExit { get; set; } = true; public bool ExitAllInForceExitOnly { get; set; } public bool ForceExitOnHitreact { get; set; } public bool ForceExitOnDead { get; set; } public bool ForceExitOnLimbDestroy { get; set; } public override void OnAbilityLoaded() { List list = new List(Abilities); EventBlock[] abilities = Abilities; foreach (EventBlock eventBlock in abilities) { if (!eventBlock.TryCache()) { LogError("Key: [" + eventBlock.AbilityName + "] was missing, unable to apply ability!"); list.Remove(eventBlock); continue; } LogVerbose($"Ability was assigned! name: {eventBlock.AbilityName} delay: {eventBlock.Delay}"); } Abilities = list.ToArray(); } } public sealed class ChainedBehaviour : AbilityBehaviour { public class EventBlockBehaviour { public readonly ChainedAbility.EventBlock AbSetting; public readonly AbilityBehaviour Behaviour; public Timer TriggerTimer; public bool Triggered; public EventBlockBehaviour(ChainedAbility.EventBlock ability, AbilityBehaviour behaviour) { AbSetting = ability; Behaviour = behaviour; } } private EventBlockBehaviour[] _blockBehaviours = Array.Empty(); private Timer _endTimer; private bool _waitingEndTimer; private bool _allFinished; private bool _forceExit; private bool _useClientPos; public override bool RunUpdateOnlyWhileExecuting => true; public override bool AllowEABAbilityWhileExecuting => true; public override bool IsHostOnlyBehaviour => true; public override bool IsHostOnlySetup => false; protected override void OnSetup() { if (SNet.IsMaster) { _blockBehaviours = new EventBlockBehaviour[base.Ability.Abilities.Length]; for (int i = 0; i < base.Ability.Abilities.Length; i++) { ChainedAbility.EventBlock eventBlock = base.Ability.Abilities[i]; _blockBehaviours[i] = new EventBlockBehaviour(eventBlock, eventBlock.Ability.RegisterBehaviour(base.Agent)); } } else { ChainedAbility.EventBlock[] abilities = base.Ability.Abilities; for (int j = 0; j < abilities.Length; j++) { abilities[j].Ability.RegisterBehaviour(base.Agent); } } } protected override void OnEnterUseClientPos() { OnEnter(); _useClientPos = true; } protected override void OnEnter() { EventBlockBehaviour[] blockBehaviours = _blockBehaviours; foreach (EventBlockBehaviour eventBlockBehaviour in blockBehaviours) { eventBlockBehaviour.TriggerTimer.Reset(eventBlockBehaviour.AbSetting.Delay); eventBlockBehaviour.Triggered = false; } _waitingEndTimer = false; _forceExit = true; _useClientPos = false; } protected override void OnUpdate() { bool flag = true; EventBlockBehaviour[] blockBehaviours = _blockBehaviours; foreach (EventBlockBehaviour eventBlockBehaviour in blockBehaviours) { if (!eventBlockBehaviour.Triggered) { if (eventBlockBehaviour.TriggerTimer.TickAndCheckDone()) { eventBlockBehaviour.AbSetting.Ability.TriggerSync(base.Agent, _useClientPos); eventBlockBehaviour.Triggered = true; } else { flag = false; } } } if (!flag) { return; } if (!_allFinished && base.Ability.ExitWhenAllFinished) { blockBehaviours = _blockBehaviours; for (int i = 0; i < blockBehaviours.Length; i++) { if (blockBehaviours[i].Behaviour.Executing) { return; } } _allFinished = true; } if (!_waitingEndTimer) { _endTimer.Reset(base.Ability.ExitDelay); _waitingEndTimer = true; } else if (_waitingEndTimer && _endTimer.TickAndCheckDone()) { _forceExit = false; DoExit(); } } protected override void OnExit() { if ((base.Ability.ExitAllInForceExit && !base.Ability.ExitAllInForceExitOnly) || (_forceExit && base.Ability.ExitAllInForceExitOnly)) { ChainedAbility.EventBlock[] abilities = base.Ability.Abilities; for (int i = 0; i < abilities.Length; i++) { abilities[i].Ability.ExitSync(base.Agent); } } } protected override void OnHitreact() { if (base.Ability.ForceExitOnHitreact) { DoExit(); } } protected override void OnLimbDestroyed(Dam_EnemyDamageLimb _) { if (base.Ability.ForceExitOnLimbDestroy) { DoExit(); } } protected override void OnDead() { if (base.Ability.ForceExitOnDead) { DoExit(); } } } public sealed class CloakAbility : AbilityBase { public float CloakOpacity { get; set; } public float CloakDuration { get; set; } = 1f; public float DecloakDuration { get; set; } = 1f; public float DecloakAfterDelay { get; set; } = -1f; public bool HideShadow { get; set; } public bool RequireTagForDetectionWhileCloaking { get; set; } = true; public bool AllowEABAbilityWhileCloaking { get; set; } = true; public override void OnAbilityLoaded() { CloakDuration = Mathf.Max(CloakDuration, 0f); DecloakDuration = Mathf.Max(DecloakDuration, 0f); } } public sealed class CloakBehaviour : AbilityBehaviour { public enum State { None, Cloaking, Decloaking } private struct Handler { public bool hideShadowMode; public float minOpacity; public Renderer originalRenderer; public Renderer transitionRenderer; public void SetProgress(float p) { //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) Color white; if ((Object)(object)originalRenderer == (Object)null || (Object)(object)transitionRenderer == (Object)null) { Logger.Error($"Cloak Renderer is missing! : orig {(Object)(object)originalRenderer == (Object)null}, trs {(Object)(object)transitionRenderer == (Object)null}"); } else if (p <= 0f) { DisableOriginalRenderer(); if (minOpacity <= 0f) { transitionRenderer.forceRenderingOff = true; return; } transitionRenderer.forceRenderingOff = false; Material material = transitionRenderer.material; white = Color.white; material.color = ((Color)(ref white)).AlphaMultiplied(minOpacity); } else if (p >= 1f) { EnableOriginalRenderer(); transitionRenderer.forceRenderingOff = true; transitionRenderer.material.color = Color.white; } else { DisableOriginalRenderer(); transitionRenderer.forceRenderingOff = false; Material material2 = transitionRenderer.material; white = Color.white; material2.color = ((Color)(ref white)).AlphaMultiplied(Mathf.Lerp(minOpacity, 1f, p)); } } private void EnableOriginalRenderer() { originalRenderer.shadowCastingMode = (ShadowCastingMode)1; originalRenderer.forceRenderingOff = false; } private void DisableOriginalRenderer() { if (hideShadowMode) { originalRenderer.shadowCastingMode = (ShadowCastingMode)0; originalRenderer.forceRenderingOff = true; } else { originalRenderer.shadowCastingMode = (ShadowCastingMode)3; originalRenderer.forceRenderingOff = false; } } } private readonly List _handlers = new List(); private State _cloakState; private Timer _timer; private Timer _decloakTimer; private bool _hasDecloakTimer; private bool _reqTagOriginal; public override bool RunUpdateOnlyWhileExecuting => false; public override bool AllowEABAbilityWhileExecuting => base.Ability.AllowEABAbilityWhileCloaking; public override bool IsHostOnlyBehaviour => false; protected override void OnSetup() { _reqTagOriginal = base.Agent.RequireTagForDetection; Enumerator enumerator = base.Agent.MaterialHandler.m_materialRefs.GetEnumerator(); while (enumerator.MoveNext()) { MaterialRef current = enumerator.Current; if (!current.HasFeature((MaterialSupport)1)) { continue; } Enumerator enumerator2 = current.m_renderers.GetEnumerator(); while (enumerator2.MoveNext()) { Renderer current2 = enumerator2.Current; if (!((Object)current2).name.InvariantEquals("g_leg_l")) { Renderer component = ((Component)current2).gameObject.Instantiate(((Component)current2).gameObject.transform, "TransparentRenderer").GetComponent(); component.material.shader = Shader.Find("GTFO/Glass"); component.material.SetTexture("_MainTex", current.m_material.GetTexture("_MainTex")); component.material.SetTexture("_MetallicGlossMap", (Texture)(object)Texture2D.blackTexture); component.forceRenderingOff = true; ((C_CullBucket)base.Agent.MovingCuller.Culler).AddRenderer(component); _handlers.Add(new Handler { hideShadowMode = base.Ability.HideShadow, minOpacity = base.Ability.CloakOpacity, originalRenderer = current2, transitionRenderer = component }); } } } } protected override void OnEnter() { _cloakState = State.Cloaking; _timer.Reset(base.Ability.CloakDuration); if (base.Ability.DecloakAfterDelay >= 0f) { _hasDecloakTimer = true; _decloakTimer.Reset(base.Ability.DecloakAfterDelay); } else { _hasDecloakTimer = false; } if (base.Ability.RequireTagForDetectionWhileCloaking) { base.Agent.RequireTagForDetection = true; } } protected override void OnExit() { _hasDecloakTimer = false; _cloakState = State.Decloaking; _timer.Reset(base.Ability.DecloakDuration); base.Agent.RequireTagForDetection = _reqTagOriginal; } protected override void OnUpdate() { float progress; switch (_cloakState) { case State.Cloaking: progress = GetProgress(); _handlers.ForEach(delegate(Handler h) { h.SetProgress(1f - progress); }); if (progress >= 1f) { _cloakState = State.None; base.Agent.MovingCuller.m_disableAnimatorCullingWhenRenderingShadow = true; ((Agent)base.Agent).SetAnimatorCullingEnabled(false); } break; case State.Decloaking: progress = GetProgress(); _handlers.ForEach(delegate(Handler h) { h.SetProgress(progress); }); if (progress >= 1f) { _cloakState = State.None; base.Agent.MovingCuller.m_disableAnimatorCullingWhenRenderingShadow = false; ((Agent)base.Agent).SetAnimatorCullingEnabled(true); } break; } if (_hasDecloakTimer && base.Executing && _decloakTimer.TickAndCheckDone()) { DoExit(); } } protected override void OnAbilityLazyUpdate() { ((C_Cullable)base.Agent.MovingCuller.Culler).NeedsShadowRefresh = true; } private float GetProgress() { _timer.Tick(); return _timer.Progress; } } public sealed class DoAnimAbility : AbilityBase { public EnemyAnimType Animation { get; set; } = EnemyAnimType.Screams; public uint SoundEvent { get; set; } public uint VoiceEvent { get; set; } public float Duration { get; set; } = 1f; public float CrossFadeTime { get; set; } public bool AllowUsingEABWhileExecuting { get; set; } public bool StandStill { get; set; } = true; public bool ApplyRootMotion { get; set; } = true; } public sealed class DoAnimBehaviour : AbilityBehaviour { private Animator _animator; private INavigation _navAgent; private Timer _exitTimer; public override bool RunUpdateOnlyWhileExecuting => true; public override bool AllowEABAbilityWhileExecuting => base.Ability.AllowUsingEABWhileExecuting; public override bool IsHostOnlyBehaviour => false; protected override void OnSetup() { _animator = base.Agent.Locomotion.m_animator; _navAgent = ((AgentAI)base.Agent.AI).m_navMeshAgent; } protected override void OnDead() { DoExit(); } protected override void OnEnter() { base.StandStill = base.Ability.StandStill; _exitTimer.Reset(base.Ability.Duration); EnemyAnimUtil.DoAnimationLocal(base.Agent, base.Ability.Animation, base.Ability.CrossFadeTime, pauseAI: true); if (!base.Ability.ApplyRootMotion) { _animator.applyRootMotion = false; } if (base.Ability.SoundEvent != 0) { base.Agent.Sound.Post(base.Ability.SoundEvent, true); } if (base.Ability.VoiceEvent != 0) { base.Agent.Voice.PlayVoiceEvent(base.Ability.VoiceEvent); } } protected override void OnUpdate() { if (_exitTimer.TickAndCheckDone()) { DoExit(); } } protected override void OnExit() { if (base.Ability.StandStill) { base.StandStill = false; } if (!base.Ability.StandStill) { _navAgent.isStopped = _navAgent.isOnNavMesh && base.Agent.IsStopped(); } if (!base.Ability.ApplyRootMotion) { _animator.applyRootMotion = base.Agent.CanApplyRootMotion(); } } } public sealed class EMPAbility : AbilityBase { public uint ChargeUpSoundId { get; set; } public uint ActivateSoundId { get; set; } public EnemyAnimType ChargeUpAnimation { get; set; } = EnemyAnimType.AbilityUse; public EnemyAnimType ActivateAnimation { get; set; } = EnemyAnimType.AbilityUseOut; public float ChargeUpDuration { get; set; } = 3f; public float EffectDuration { get; set; } = 30f; public float ActivateDuration { get; set; } = 5f; public float EffectRange { get; set; } = 20f; public bool InvincibleWhileCharging { get; set; } = true; public Color BuildupColor { get; set; } = new Color(0.525f, 0.956f, 0.886f, 1f) * 2f; public Color ScreamColor { get; set; } = new Color(0.525f, 0.956f, 0.886f, 1f) * 20f; } public sealed class EMPBehaviour : AbilityBehaviour { private enum EMPState { None, BuildUp, AbilityUsed, Done } private EMPState _state; private Timer _stateTimer; private INavigation _navAgent; public override bool RunUpdateOnlyWhileExecuting => true; public override bool AllowEABAbilityWhileExecuting => false; public override bool IsHostOnlyBehaviour => false; protected override void OnSetup() { _navAgent = ((AgentAI)base.Agent.AI).m_navMeshAgent; } protected override void OnEnter() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) base.StandStill = true; _state = EMPState.BuildUp; _stateTimer.Reset(base.Ability.ChargeUpDuration); if (base.Ability.ChargeUpSoundId != 0) { base.Agent.Sound.Post(base.Ability.ChargeUpSoundId, true); } if (base.Ability.InvincibleWhileCharging) { base.Agent.Damage.IsImortal = true; } base.Agent.Appearance.InterpolateGlow(base.Ability.BuildupColor, base.Ability.ChargeUpDuration); EnemyAnimUtil.DoAnimationLocal(base.Agent, base.Ability.ChargeUpAnimation, 0.15f, pauseAI: true); } protected override void OnUpdate() { //IL_005a: 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) switch (_state) { case EMPState.BuildUp: if (_stateTimer.TickAndCheckDone()) { base.Agent.Sound.Post(base.Ability.ActivateSoundId, true); base.Agent.Appearance.InterpolateGlow(base.Ability.ScreamColor, 0.5f); EnemyAnimUtil.DoAnimationLocal(base.Agent, base.Ability.ActivateAnimation, 0.15f, pauseAI: true); EMPManager.Activate(base.Agent.Position, base.Ability.EffectRange, base.Ability.EffectDuration); _state = EMPState.AbilityUsed; _stateTimer.Reset(base.Ability.ActivateDuration); } break; case EMPState.AbilityUsed: if (_stateTimer.TickAndCheckDone()) { _state = EMPState.Done; _stateTimer.Reset(0f); } break; case EMPState.Done: DoExit(); break; } } protected override void OnExit() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 base.StandStill = false; if (base.Ability.InvincibleWhileCharging && (int)base.Agent.Locomotion.CurrentStateEnum != 13) { base.Agent.Damage.IsImortal = false; } base.Agent.Appearance.InterpolateGlow(Color.black, 0.5f); _state = EMPState.None; _stateTimer.Reset(0f); } protected override void OnDead() { DoExit(); } } public sealed class ExplosionAbility : AbilityBase, IExplosionSetting { public ValueBase Damage { get; set; } = ValueBase.Zero; public Color LightColor { get; set; } = new Color(1f, 0.2f, 0f, 1f); public bool KillInflictor { get; set; } = true; public bool UseRagdollPosition { get; set; } = true; public bool UseExplosionCounter { get; set; } public int AllowedExplosionCount { get; set; } = 1; public float EnemyDamageMulti { get; set; } = 1f; public float MinRange { get; set; } = 2f; public float MaxRange { get; set; } = 5f; public ValueBase EnemyMinRange { get; set; } = ValueBase.Unchanged; public ValueBase EnemyMaxRange { get; set; } = ValueBase.Unchanged; public float NoiseMinRange { get; set; } = 5f; public float NoiseMaxRange { get; set; } = 10f; public NM_NoiseType NoiseType { get; set; } = (NM_NoiseType)1; public KnockbackSetting Knockback { get; set; } = new KnockbackSetting(); public BleedSetting Bleed { get; set; } = new BleedSetting(); public DrainStaminaSetting DrainStamina { get; set; } = new DrainStaminaSetting(); public InfectionSetting Infection { get; set; } = new InfectionSetting(); } public sealed class ExplosionBehaviour : AbilityBehaviour { public override bool RunUpdateOnlyWhileExecuting => true; public override bool AllowEABAbilityWhileExecuting => true; public override bool IsHostOnlyBehaviour => true; protected override void OnEnterUseClientPos() { DoExplosion(useClientPos: true); } protected override void OnEnter() { DoExplosion(useClientPos: false); } private void DoExplosion(bool useClientPos) { if (((Il2CppObjectBase)base.Agent).WasCollected) { DoExit(); return; } if (base.Ability.UseExplosionCounter) { ExplosionCounter explosionCounter = base.Agent.RegisterOrGetProperty(); if (explosionCounter.Count >= base.Ability.AllowedExplosionCount) { DoExit(); return; } explosionCounter.Count++; } base.Ability.DoExplode((Agent)(object)base.Agent, base.Ability.UseRagdollPosition, useClientPos); base.Ability.TryKillInflictor((Agent)(object)base.Agent); DoExit(); } } public sealed class ExplosionCounter { public int Count; } public sealed class FogSphereAbility : AbilityBase { public const string EAB_FOG_PREFAB = "Assets/AssetPrefabs/Characters/Enemies/Abilities/EAB_FogSphere.prefab"; public GameObject FogSpherePrefab; public uint SoundEventID { get; set; } public Color ColorMin { get; set; } = Color.white; public Color ColorMax { get; set; } = Color.clear; public float IntensityMin { get; set; } = 1f; public float IntensityMax { get; set; } = 5f; public float RangeMin { get; set; } = 1f; public float RangeMax { get; set; } = 3f; public float DensityMin { get; set; } = 1f; public float DensityMax { get; set; } = 5f; public float DensityAmountMin { get; set; } public float DensityAmountMax { get; set; } = 5f; public float Duration { get; set; } = 30f; public EffectVolumeSetting EffectVolume { get; set; } = new EffectVolumeSetting(); public override void OnAbilityLoaded() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) EAB_FogSphere component = ((Il2CppObjectBase)AssetShardManager.GetLoadedAsset("Assets/AssetPrefabs/Characters/Enemies/Abilities/EAB_FogSphere.prefab", false)).Cast().GetComponent(); FogSpherePrefab = ((Il2CppObjectBase)Object.Instantiate(component.m_fogSpherePrefab)).Cast(); FogSphereHandler component2 = FogSpherePrefab.GetComponent(); component2.m_colorMin = ColorMin; component2.m_colorMax = ColorMax; component2.m_intensityMin = IntensityMin; component2.m_intensityMax = IntensityMax; component2.m_rangeMin = RangeMin; component2.m_rangeMax = RangeMax; component2.m_densityMin = DensityMin; component2.m_densityMax = DensityMax; component2.m_densityAmountMin = DensityAmountMin; component2.m_densityAmountMax = DensityAmountMax; component2.m_totalLength = Duration; Object.DontDestroyOnLoad((Object)(object)FogSpherePrefab); } public override void OnAbilityUnloaded() { Object.Destroy((Object)(object)FogSpherePrefab); } } public sealed class FogSphereBehaviour : AbilityBehaviour { private readonly List _fogSphereHandlers = new List(); public override bool RunUpdateOnlyWhileExecuting => false; public override bool AllowEABAbilityWhileExecuting => true; public override bool IsHostOnlyBehaviour => false; protected override void OnEnter() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (base.Ability.SoundEventID != 0) { base.Agent.Sound.Post(base.Ability.SoundEventID, true); } GameObject val = Object.Instantiate(base.Ability.FogSpherePrefab, base.Agent.Position, Quaternion.identity); FogSphereHandler component = val.GetComponent(); if (component.Play()) { _fogSphereHandlers.Add(component); if (base.Ability.EffectVolume.Enabled) { EffectFogSphereHandler effectFogSphereHandler = ((Component)component).gameObject.AddComponent(); effectFogSphereHandler.Handler = component; effectFogSphereHandler.EVSphere = base.Ability.EffectVolume.CreateSphere(((Component)component).transform.position, 0f, 0f); EffectVolumeManager.RegisterVolume((EffectVolume)(object)effectFogSphereHandler.EVSphere); } } else { Object.DestroyImmediate((Object)(object)val); } DoExit(); } protected override void OnUpdate() { int num = _fogSphereHandlers.Count - 1; if (num <= -1) { return; } for (int num2 = num; num2 > -1; num2--) { FogSphereHandler val = _fogSphereHandlers[num2]; if ((Object)(object)val == (Object)null) { _fogSphereHandlers.RemoveAt(num2); } else if (!((Behaviour)val).enabled) { _fogSphereHandlers.RemoveAt(num2); Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } } } } public sealed class SpawnEnemyAbility : AbilityBase { public bool StopAgent { get; set; } public float Delay { get; set; } public uint EnemyID { get; set; } public AgentMode AgentMode { get; set; } = (AgentMode)1; public int TotalCount { get; set; } public int CountPerSpawn { get; set; } public float DelayPerSpawn { get; set; } public bool DoGlobalFallback { get; set; } public override void OnAbilityLoaded() { if (TotalCount < 0) { LogError("TotalCount was below zero! : setting to default value"); TotalCount = 0; } if (CountPerSpawn < 1) { LogError("CountPerSpawn was below one! : setting to default value"); CountPerSpawn = 1; } } } public sealed class SpawnEnemyBehaviour : AbilityBehaviour { [CompilerGenerated] private sealed class d__14 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SpawnEnemyBehaviour <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; SpawnEnemyBehaviour spawnEnemyBehaviour = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; goto IL_0042; case 1: <>1__state = -1; goto IL_0042; case 2: { <>1__state = -1; goto IL_0078; } IL_0042: if (!spawnEnemyBehaviour._stateTimer.TickAndCheckDone()) { <>2__current = null; <>1__state = 1; return true; } spawnEnemyBehaviour._stateTimer.Reset(0f); goto IL_00cd; IL_0078: if (!spawnEnemyBehaviour._stateTimer.TickAndCheckDone()) { <>2__current = null; <>1__state = 2; return true; } if (SNet.IsMaster) { spawnEnemyBehaviour.SpawnEnemy(spawnEnemyBehaviour.Ability.CountPerSpawn); } else { spawnEnemyBehaviour._remainingSpawn -= spawnEnemyBehaviour.Ability.CountPerSpawn; } spawnEnemyBehaviour._stateTimer.Reset(spawnEnemyBehaviour.Ability.DelayPerSpawn); goto IL_00cd; IL_00cd: if (spawnEnemyBehaviour._remainingSpawn <= 0) { spawnEnemyBehaviour.DoExit(); spawnEnemyBehaviour._updateLoop = null; return false; } goto IL_0078; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private int _remainingSpawn; private AIG_CourseNode _fallbackNode; private Vector3 _fallbackPos; private Quaternion _fallbackRot; private IEnumerator? _updateLoop; private Timer _stateTimer; public override bool RunUpdateOnlyWhileExecuting => true; public override bool AllowEABAbilityWhileExecuting => false; public override bool IsHostOnlyBehaviour => false; protected override void OnEnter() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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) _remainingSpawn = base.Ability.TotalCount; if (_remainingSpawn <= 0) { DoExit(); return; } base.StandStill = base.Ability.StopAgent; _fallbackNode = ((Agent)base.Agent).CourseNode; _fallbackPos = base.Agent.Position; _fallbackRot = ((Agent)base.Agent).Rotation; if (base.Ability.DoGlobalFallback) { CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DoSpawnRoutine()), (Action)null); } else { _updateLoop = DoSpawnRoutine(); } _stateTimer.Reset(base.Ability.Delay); } protected override void OnUpdate() { _updateLoop?.MoveNext(); } [IteratorStateMachine(typeof(d__14))] private IEnumerator DoSpawnRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__14(0) { <>4__this = this }; } private void SpawnEnemy(int count) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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) //IL_009a: 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) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < count; i++) { if (_remainingSpawn <= 0) { break; } AIG_CourseNode val = (AIG_CourseNode)((!base.Ability.DoGlobalFallback || (Object)(object)base.Agent != (Object)null) ? ((object)((Agent)base.Agent).CourseNode) : ((object)_fallbackNode)); Vector3 val2 = ((!base.Ability.DoGlobalFallback || (Object)(object)base.Agent != (Object)null) ? base.Agent.Position : _fallbackPos); Quaternion val3 = ((!base.Ability.DoGlobalFallback || (Object)(object)base.Agent != (Object)null) ? ((Agent)base.Agent).Rotation : _fallbackRot); EnemyAllocator.Current.SpawnEnemy(base.Ability.EnemyID, val, base.Ability.AgentMode, val2, val3, (EnemyGroup)null, -1); _remainingSpawn--; } } protected override void OnExit() { if (base.Ability.StopAgent && (!base.Ability.DoGlobalFallback || (Object)(object)base.Agent != (Object)null)) { base.StandStill = false; } } } public sealed class SpawnProjectileAbility : AbilityBase, ISpawnProjectileSetting { public ProjectileType ProjectileType { get; set; } public bool BackwardDirection { get; set; } public int Count { get; set; } = 1; public int BurstCount { get; set; } = 1; public float Delay { get; set; } = 0.1f; public float BurstDelay { get; set; } = 0.05f; public float ShotSpreadXMin { get; set; } public float ShotSpreadXMax { get; set; } public float ShotSpreadYMin { get; set; } public float ShotSpreadYMax { get; set; } public uint SoundID { get; set; } public bool FindTargetIfInvalid { get; set; } } public sealed class SpawnProjectileBehaviour : AbilityBehaviour { public override bool RunUpdateOnlyWhileExecuting => true; public override bool AllowEABAbilityWhileExecuting => true; public override bool IsHostOnlyBehaviour => false; protected override void OnEnter() { //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) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if (base.Ability.SoundID != 0) { base.Agent.Sound.Post(base.Ability.SoundID, true); } if (!SNet.IsMaster) { DoExit(); return; } Agent target = null; if (((AgentAI)base.Agent.AI).IsTargetValid) { target = ((AgentAI)base.Agent.AI).Target.m_agent; } else if (base.Ability.FindTargetIfInvalid) { float num = float.MaxValue; Enumerator enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator(); while (enumerator.MoveNext()) { PlayerAgent current = enumerator.Current; if (((Agent)current).Alive) { Vector3 val = ((Agent)base.Agent).EyePosition - ((Agent)current).EyePosition; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (num >= sqrMagnitude && !Physics.Linecast(((Agent)base.Agent).EyePosition, ((Agent)current).EyePosition, LayerManager.MASK_WORLD)) { num = sqrMagnitude; target = (Agent)(object)current; } } } } base.Ability.DoSpawn(base.Agent, target, base.Agent.ModelRef.m_shooterFireAlign, keepTrack: true); DoExit(); } } public sealed class SpawnWaveAbility : AbilityBase { public uint WaveSettingID { get; set; } public uint WavePopulationID { get; set; } public SurvivalWaveSpawnType SpawnType { get; set; } public float SpawnDelay { get; set; } public bool PlayDistantRoar { get; set; } = true; } public sealed class SpawnWaveBehaviour : AbilityBehaviour { public override bool RunUpdateOnlyWhileExecuting => true; public override bool AllowEABAbilityWhileExecuting => true; public override bool IsHostOnlyBehaviour => true; protected override void OnEnter() { //IL_002e: 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: Unknown result type (might be due to invalid IL or missing references) ushort num = default(ushort); Mastermind.Current.TriggerSurvivalWave(((Agent)base.Agent).CourseNode, base.Ability.WaveSettingID, base.Ability.WavePopulationID, ref num, base.Ability.SpawnType, base.Ability.SpawnDelay, 2f, base.Ability.PlayDistantRoar, false, default(Vector3), ""); DoExit(); } } } namespace EEC.EnemyCustomizations.Detections { public sealed class FeelerCustom : EnemyCustomBase { public ValueBase TendrilCount { get; set; } = ValueBase.Unchanged; public float TendrilAngleOffset { get; set; } public ValueBase TendrilStepAngle { get; set; } = ValueBase.Unchanged; public ValueBase TendrilMinYSpread { get; set; } = ValueBase.Unchanged; public ValueBase TendrilMaxYSpread { get; set; } = ValueBase.Unchanged; public ValueBase TendrilOutTimer { get; set; } = ValueBase.Unchanged; public ValueBase Distance { get; set; } = ValueBase.Unchanged; public ValueBase StepDistance { get; set; } = ValueBase.Unchanged; public ValueBase RetractTime { get; set; } = ValueBase.Unchanged; public ValueBase RetractTimeDetected { get; set; } = ValueBase.Unchanged; public Color NormalColor { get; set; } = Color.black; public Color DetectColor { get; set; } = Color.red; public override string GetProcessName() { return "Feeler"; } public override void OnConfigLoaded() { ScoutAntennaSpawnEvent.DetectionSpawn += OnDetectionSpawn; ScoutAntennaSpawnEvent.AntennaSpawn += OnAntennaSpawn; } public override void OnConfigUnloaded() { ScoutAntennaSpawnEvent.DetectionSpawn -= OnDetectionSpawn; ScoutAntennaSpawnEvent.AntennaSpawn -= OnAntennaSpawn; } private void OnDetectionSpawn(EnemyAgent agent, ScoutAntennaDetection detection) { if (IsTarget(agent)) { detection.m_tendrilCount = TendrilCount.GetAbsValue(detection.m_tendrilCount); detection.m_dirAngOffset = TendrilAngleOffset; detection.m_dirAngStep = TendrilStepAngle.GetAbsValue(detection.m_dirAngStep); detection.m_dirAngSpread_Min = TendrilMinYSpread.GetAbsValue(detection.m_dirAngSpread_Min); detection.m_dirAngSpread_Max = TendrilMaxYSpread.GetAbsValue(detection.m_dirAngSpread_Max); detection.m_timerWaitOut = TendrilOutTimer.GetAbsValue(detection.m_timerWaitOut); } } private void OnAntennaSpawn(EnemyAgent agent, ScoutAntennaDetection _, ScoutAntenna ant) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (IsTarget(agent)) { ant.m_colorDefault = NormalColor; ant.m_colorDetection = DetectColor; ant.m_moveInTime = RetractTime.GetAbsValue(ant.m_moveInTime); ant.m_moveInTimeDetected = RetractTimeDetected.GetAbsValue(ant.m_moveInTimeDetected); ant.m_maxDistance = Distance.GetAbsValue(ant.m_maxDistance); ant.m_stepDistance = StepDistance.GetAbsValue(ant.m_stepDistance); MeshFilter component = ((Component)ant).GetComponent(); Bounds bounds = component.mesh.bounds; ((Bounds)(ref bounds)).Expand(5000f); component.mesh.bounds = bounds; } } } public sealed class ScoutAnimCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public enum AnimationRandomType { PerEnemy, PerDetection } internal static readonly ScoutAnimSync _animSync; public AnimationRandomType RandomType { get; set; } = AnimationRandomType.PerDetection; public EnemyAnimType BendAnimation { get; set; } = EnemyAnimType.AbilityUseOut; public EnemyAnimType StandAnimation { get; set; } = EnemyAnimType.AbilityUse; public float ChanceToBend { get; set; } = 1f; public bool OverridePullingAnimation { get; set; } public EnemyAnimType PullingAnimation { get; set; } = EnemyAnimType.AbilityUseOut; static ScoutAnimCustom() { _animSync = new ScoutAnimSync(); _animSync.Setup(); } public override string GetProcessName() { return "ScoutAnim"; } public void OnSpawned(EnemyAgent agent) { ScoutAnimOverrideProperty scoutAnimOverrideProperty = agent.RegisterOrGetProperty(); scoutAnimOverrideProperty.Agent = agent; switch (RandomType) { case AnimationRandomType.PerEnemy: scoutAnimOverrideProperty.ChanceToBend = (Rand.CanDoBy(ChanceToBend) ? 1f : 0f); break; case AnimationRandomType.PerDetection: scoutAnimOverrideProperty.ChanceToBend = ChanceToBend; break; } scoutAnimOverrideProperty.BendAnimation = BendAnimation; scoutAnimOverrideProperty.StandAnimation = StandAnimation; scoutAnimOverrideProperty.OverridePullingAnimation = OverridePullingAnimation; scoutAnimOverrideProperty.PullingAnimation = PullingAnimation; } } public sealed class ScoutAnimSync : SyncedEvent { public struct Packet { public ushort enemyID; public ScoutAnimType nextAnim; } public override string GUID => "SAM"; public void DoRandom(EnemyAgent agent) { if (SNet.IsMaster && agent.TryGetProperty(out var property)) { ScoutAnimType nextAnim = ((property.ChanceToBend >= 1f) ? ScoutAnimType.Bending : ((!(property.ChanceToBend <= 0f)) ? (Rand.CanDoBy(property.ChanceToBend) ? ScoutAnimType.Bending : ScoutAnimType.Standing) : ScoutAnimType.Standing)); Packet packet = default(Packet); packet.enemyID = ((Agent)agent).GlobalID; packet.nextAnim = nextAnim; Packet packetData = packet; Send(packetData); } } protected override void Receive(Packet packet) { if (EnemyProperty.TryGet(packet.enemyID, out var property) && !((Il2CppObjectBase)property.Agent).WasCollected) { if (property.EnterWasCalled) { property.DoAnim(packet.nextAnim); property.AnimDetermined = false; property.EnterWasCalled = false; } else { property.NextAnim = packet.nextAnim; property.AnimDetermined = true; } } } } internal sealed class ScoutAnimOverrideProperty { public EnemyAgent Agent; public float ChanceToBend; public bool AnimDetermined; public bool EnterWasCalled; public ScoutAnimType NextAnim; public EnemyAnimType BendAnimation = EnemyAnimType.AbilityUseOut; public EnemyAnimType StandAnimation = EnemyAnimType.AbilityUse; public bool OverridePullingAnimation; public EnemyAnimType PullingAnimation = EnemyAnimType.AbilityUseOut; public void DoAnim(ScoutAnimType anim) { switch (anim) { case ScoutAnimType.Standing: EnemyAnimUtil.DoAnimationLocal(Agent, StandAnimation, 0.15f, pauseAI: false); break; case ScoutAnimType.Bending: EnemyAnimUtil.DoAnimationLocal(Agent, BendAnimation, 0.15f, pauseAI: false); break; } } public void DoPullingAnim() { EnemyAnimUtil.DoAnimationLocal(Agent, PullingAnimation, 0.15f, pauseAI: false); } } public enum ScoutAnimType : byte { Unknown, Bending, Standing } public sealed class ScreamingCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public DetectedBehaviourType DetectedBehaviour { get; set; } public bool ImmortalDuringScream { get; set; } = true; public override string GetProcessName() { return "Screaming"; } public void OnSpawned(EnemyAgent agent) { } } public enum DetectedBehaviourType { DoPropagateScream, DoScoutScream } } namespace EEC.EnemyCustomizations.Detections.Inject { [HarmonyPatch(typeof(ES_ScoutDetection), "CommonEnter")] internal static class Inject_ES_ScoutDetection { [HarmonyWrapSafe] internal static void Postfix(ES_ScoutDetection __instance) { if (((ES_Base)__instance).m_enemyAgent.TryGetProperty(out var property)) { if (SNet.IsMaster) { ScoutAnimCustom._animSync.DoRandom(__instance.m_owner); } if (property.AnimDetermined) { property.DoAnim(property.NextAnim); property.AnimDetermined = false; } property.EnterWasCalled = true; } } } [HarmonyPatch(typeof(ScoutAntennaDetection), "PlayAbilityOutAnimation")] internal static class Inject_ScoutAntennaDetection { [HarmonyWrapSafe] internal static void Postfix(ScoutAntennaDetection __instance) { if (__instance.m_owner.TryGetProperty(out var property) && property.OverridePullingAnimation) { property.DoPullingAnim(); } } } } namespace EEC.EnemyCustomizations.Abilities { public abstract class AttackCustomBase : EnemyCustomBase where T : class, new() { [JsonIgnore] public abstract bool DisableProjectileDamageEvent { get; } public T MeleeData { get; set; } = new T(); public T TentacleData { get; set; } = new T(); public T ProjectileData { get; set; } = new T(); public override void OnConfigLoaded() { LocalPlayerDamageEvents.MeleeDamage += OnMelee; LocalPlayerDamageEvents.TentacleDamage += OnTentacle; if (!DisableProjectileDamageEvent) { LocalPlayerDamageEvents.ProjectileDamage += OnProjectile; } } public override void OnConfigUnloaded() { LocalPlayerDamageEvents.MeleeDamage -= OnMelee; LocalPlayerDamageEvents.TentacleDamage -= OnTentacle; if (!DisableProjectileDamageEvent) { LocalPlayerDamageEvents.ProjectileDamage -= OnProjectile; } } private void OnMelee(PlayerAgent player, Agent inflictor, float damage) { Do(player, inflictor, MeleeData); } private void OnTentacle(PlayerAgent player, Agent inflictor, float damage) { Do(player, inflictor, TentacleData); } private void OnProjectile(PlayerAgent player, Agent inflictor, ProjectileBase projectile, float damage) { DoProjectile(player, inflictor, projectile, ProjectileData); } private void Do(PlayerAgent player, Agent inflictor, T setting) { if (inflictor.TryCastToEnemyAgent(out EnemyAgent enemyAgent) && IsTarget(enemyAgent)) { OnApplyEffect(setting, player, enemyAgent); } } private void DoProjectile(PlayerAgent player, Agent inflictor, ProjectileBase projectile, T setting) { if (inflictor.TryCastToEnemyAgent(out EnemyAgent enemyAgent) && IsTarget(enemyAgent)) { OnApplyProjectileEffect(setting, player, enemyAgent, projectile); } } protected abstract void OnApplyEffect(T setting, PlayerAgent player, EnemyAgent inflicator); protected virtual void OnApplyProjectileEffect(T setting, PlayerAgent player, EnemyAgent inflictor, ProjectileBase projectile) { } } public sealed class BleedAttackCustom : AttackCustomBase { public override bool DisableProjectileDamageEvent => false; public override string GetProcessName() { return "BleedAttack"; } public override void OnConfigLoaded() { base.OnConfigLoaded(); if (ConfigManager.Global.CanDownStopBleeding) { LocalPlayerAliveEvents.Down += OnDown; } if (ConfigManager.Global.CanMediStopBleeding) { ResourcePackEvents.ReceiveMedi += RecieveMedi; } } public override void OnConfigUnloaded() { base.OnConfigLoaded(); if (ConfigManager.Global.CanDownStopBleeding) { LocalPlayerAliveEvents.Down -= OnDown; } if (ConfigManager.Global.CanMediStopBleeding) { ResourcePackEvents.ReceiveMedi -= RecieveMedi; } } protected override void OnApplyEffect(BleedSetting setting, PlayerAgent player, EnemyAgent inflictor) { setting.DoBleed(player); } protected override void OnApplyProjectileEffect(BleedSetting setting, PlayerAgent player, EnemyAgent inflictor, ProjectileBase projectile) { OnApplyEffect(setting, player, inflictor); } private static void OnDown(PlayerAgent player) { BleedSetting.StopBleed(player); } private static void RecieveMedi(iResourcePackReceiver receiver, float _) { PlayerAgent val = ((Il2CppObjectBase)receiver).TryCast(); if ((Object)(object)val != (Object)null) { BleedSetting.StopBleed(val); } } } public sealed class DrainStaminaAttackCustom : AttackCustomBase { public override bool DisableProjectileDamageEvent => false; public override string GetProcessName() { return "DrainStamina"; } protected override void OnApplyEffect(DrainStaminaSetting setting, PlayerAgent player, EnemyAgent inflictor) { setting.DoDrain(player); } protected override void OnApplyProjectileEffect(DrainStaminaSetting setting, PlayerAgent player, EnemyAgent inflictor, ProjectileBase projectile) { OnApplyEffect(setting, player, inflictor); } } public sealed class ExplosiveAttackCustom : AttackCustomBase { public override bool DisableProjectileDamageEvent => true; public bool ProjectileExplodesOnWorld { get; set; } public bool ProjectileExplodesOnPlayer { get; set; } public bool ProjectileExplodesOnLifeTimeDone { get; set; } public override string GetProcessName() { return "ExplosiveAttack"; } public override void OnConfigLoaded() { base.OnConfigLoaded(); if (ProjectileExplodesOnWorld) { ProjectileEvents.CollidedWorld += ProjectileEvents_CollidedWorld; } if (ProjectileExplodesOnPlayer) { ProjectileEvents.CollidedPlayer += ProjectileEvents_CollidedPlayer; } if (ProjectileExplodesOnLifeTimeDone) { ProjectileEvents.LifeTimeDone += ProjectileEvents_LifeTimeDone; } } public override void OnConfigUnloaded() { base.OnConfigUnloaded(); if (ProjectileExplodesOnWorld) { ProjectileEvents.CollidedWorld -= ProjectileEvents_CollidedWorld; } if (ProjectileExplodesOnPlayer) { ProjectileEvents.CollidedPlayer -= ProjectileEvents_CollidedPlayer; } if (ProjectileExplodesOnLifeTimeDone) { ProjectileEvents.LifeTimeDone -= ProjectileEvents_LifeTimeDone; } } private void ProjectileEvents_CollidedWorld(ProjectileBase projectile, GameObject _) { TriggerProjectileExplosion(projectile); } private void ProjectileEvents_CollidedPlayer(ProjectileBase projectile, PlayerAgent _) { TriggerProjectileExplosion(projectile); } private void ProjectileEvents_LifeTimeDone(ProjectileTargeting projectile) { TriggerProjectileExplosion(((Il2CppObjectBase)projectile).Cast()); } private void TriggerProjectileExplosion(ProjectileBase projectile) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) uint id; if (!IsOwnerDestroyed(projectile, out EnemyAgent agent)) { if (IsTarget(agent)) { base.ProjectileData.DoLocalExplode(((Component)projectile).transform.position); base.ProjectileData.TryKillInflictor((Agent)(object)agent); } } else if (projectile.TryGetOwnerEnemyDataID(out id) && IsTarget(id)) { base.ProjectileData.DoLocalExplode(((Component)projectile).transform.position); } } protected override void OnApplyEffect(ExplosionSetting setting, PlayerAgent player, EnemyAgent inflictor) { setting.DoExplode((Agent)(object)player); setting.TryKillInflictor((Agent)(object)inflictor); } private static bool IsOwnerDestroyed(ProjectileBase projectile, out EnemyAgent agent) { if (!projectile.TryGetOwner(out agent)) { return true; } if ((Object)(object)agent == (Object)null) { return true; } if (((Il2CppObjectBase)agent).WasCollected) { return true; } return false; } } public sealed class InfectionAttackCustom : AttackCustomBase { public sealed class AttackData : IInfectionSetting { public bool Enabled { get; set; } = true; public ValueBase Infection { get; set; } = ValueBase.Zero; public uint SoundEventID { get; set; } public bool UseEffect { get; set; } public float ScreenLiquidRange { get; set; } } public override bool DisableProjectileDamageEvent => false; public override string GetProcessName() { return "InfectionAttack"; } protected override void OnApplyEffect(AttackData data, PlayerAgent player, EnemyAgent inflicator) { if (data.Infection.GetAbsValue(PlayerData.MaxInfection) != 0f) { InfectionManager.DoInfection(player, data); } } protected override void OnApplyProjectileEffect(AttackData setting, PlayerAgent player, EnemyAgent inflictor, ProjectileBase projectile) { OnApplyEffect(setting, player, inflictor); } } public sealed class KnockbackAttackCustom : AttackCustomBase { public override bool DisableProjectileDamageEvent => false; public override string GetProcessName() { return "KnockbackAttack"; } protected override void OnApplyEffect(KnockbackSetting setting, PlayerAgent player, EnemyAgent inflictor) { setting.DoKnockback((Agent)(object)inflictor, player); } protected override void OnApplyProjectileEffect(KnockbackSetting setting, PlayerAgent player, EnemyAgent inflictor, ProjectileBase projectile) { OnApplyEffect(setting, player, inflictor); } } public sealed class BirthingCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public uint EnemyGroupToSpawn { get; set; } public ValueBase ChildrenCost { get; set; } = ValueBase.Unchanged; public ValueBase ChildrenPerBirth { get; set; } = ValueBase.Unchanged; public ValueBase ChildrenPerBirthMin { get; set; } = ValueBase.Unchanged; public ValueBase ChildrenMax { get; set; } = ValueBase.Unchanged; public ValueBase MinDelayUntilNextBirth { get; set; } = ValueBase.Unchanged; public ValueBase MaxDelayUntilNextBirth { get; set; } = ValueBase.Unchanged; public override string GetProcessName() { return "Birthing"; } public void OnSpawned(EnemyAgent agent) { EAB_Birthing componentInChildren = ((Component)agent).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.m_groupDataBlock = GameDataBlockBase.GetBlock(EnemyGroupToSpawn); componentInChildren.m_childrenCost = ChildrenCost.GetAbsValue(componentInChildren.m_childrenCost); componentInChildren.m_childrenPerBirth = ChildrenPerBirth.GetAbsValue(componentInChildren.m_childrenPerBirth); componentInChildren.m_childrenAllowedSpawn = ChildrenPerBirth.GetAbsValue(componentInChildren.m_childrenAllowedSpawn); componentInChildren.m_childrenPerBirthMin = ChildrenPerBirthMin.GetAbsValue(componentInChildren.m_childrenPerBirthMin); componentInChildren.m_childrenMax = ChildrenMax.GetAbsValue(componentInChildren.m_childrenMax); componentInChildren.m_minDelayUntilNextBirth = MinDelayUntilNextBirth.GetAbsValue(componentInChildren.m_minDelayUntilNextBirth); componentInChildren.m_maxDelayUntilNextBirth = MaxDelayUntilNextBirth.GetAbsValue(componentInChildren.m_maxDelayUntilNextBirth); } } } public sealed class DoorBreakerCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { internal float _globalTimer; public bool UseGlobalTimer { get; set; } public float Damage { get; set; } = 1f; public float MinDelay { get; set; } = 0.5f; public float MaxDelay { get; set; } = 0.75f; public override string GetProcessName() { return "DoorBreaker"; } public override void OnConfigLoaded() { EB_InCombat_MoveToNextNode_DestroyDoor.s_globalRetryTimer = float.MaxValue; Inject_EB_DestroyDoor.ShouldOverride = true; LevelEvents.LevelCleanup += LevelCleanup; SNetEvents.PrepareRecall += RecallDone; } public override void OnConfigUnloaded() { EB_InCombat_MoveToNextNode_DestroyDoor.s_globalRetryTimer = 0f; Inject_EB_DestroyDoor.ShouldOverride = false; LevelEvents.LevelCleanup -= LevelCleanup; SNetEvents.RecallComplete -= RecallDone; } private void LevelCleanup() { _globalTimer = 0f; Inject_EB_DestroyDoor.GlobalTimer = 0f; } private void RecallDone(eBufferType _) { foreach (DoorBreakerProperty property in EnemyProperty.Properties) { property.Timer = 0f; } _globalTimer = 0f; Inject_EB_DestroyDoor.GlobalTimer = 0f; } public void OnSpawned(EnemyAgent agent) { DoorBreakerProperty doorBreakerProperty = agent.RegisterOrGetProperty(); doorBreakerProperty.Config = this; doorBreakerProperty.Damage = Damage; doorBreakerProperty.UseGlobalTimer = UseGlobalTimer; doorBreakerProperty.MinDelay = MinDelay; doorBreakerProperty.MaxDelay = MaxDelay; } } internal sealed class DoorBreakerProperty { public DoorBreakerCustom Config; public bool UseGlobalTimer; public float Damage = 1f; public float MinDelay = 0.5f; public float MaxDelay = 0.75f; public float Timer; } public sealed class FogSphereCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent, IEnemyPrefabBuiltEvent { public CurveWrapper ColorCurve { get; set; } = CurveWrapper.Empty; public Color ColorMin { get; set; } = Color.white; public Color ColorMax { get; set; } = Color.clear; public CurveWrapper IntensityCurve { get; set; } = CurveWrapper.Empty; public float IntensityMin { get; set; } = 1f; public float IntensityMax { get; set; } = 5f; public CurveWrapper RangeCurve { get; set; } = CurveWrapper.Empty; public float RangeMin { get; set; } = 1f; public float RangeMax { get; set; } = 3f; public CurveWrapper DensityCurve { get; set; } = CurveWrapper.Empty; public float DensityMin { get; set; } = 1f; public float DensityMax { get; set; } = 5f; public CurveWrapper DensityAmountCurve { get; set; } = CurveWrapper.Empty; public float DensityAmountMin { get; set; } public float DensityAmountMax { get; set; } = 5f; public float Duration { get; set; } = 30f; public EffectVolumeSetting EffectVolume { get; set; } = new EffectVolumeSetting(); public override string GetProcessName() { return "FogSphere"; } public void OnPrefabBuilt(EnemyAgent agent, EnemyDataBlock enemyData) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) EAB_FogSphere componentInChildren = ((Component)agent).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return; } GameObject val = componentInChildren.m_fogSpherePrefab.Instantiate(((Component)agent).gameObject.transform, "newFogPrefab"); if (val.TryGetComp(out var component)) { component.m_colorMin = ColorMin; component.m_colorMax = ColorMax; component.m_intensityMin = IntensityMin; component.m_intensityMax = IntensityMax; component.m_rangeMin = RangeMin; component.m_rangeMax = RangeMax; component.m_densityMin = DensityMin; component.m_densityMax = DensityMax; component.m_densityAmountMin = DensityAmountMin; component.m_densityAmountMax = DensityAmountMax; component.m_totalLength = Duration; if (ColorCurve.TryBuildCurve(out AnimationCurve curve)) { component.m_colorCurve = curve; } if (IntensityCurve.TryBuildCurve(out curve)) { component.m_intensityCurve = curve; } if (RangeCurve.TryBuildCurve(out curve)) { component.m_rangeCurve = curve; } if (DensityCurve.TryBuildCurve(out curve)) { component.m_densityCurve = curve; } if (DensityAmountCurve.TryBuildCurve(out curve)) { component.m_densityAmountCurve = curve; } componentInChildren.m_fogSpherePrefab = val; } } public void OnSpawned(EnemyAgent agent) { if (EffectVolume.Enabled) { SphereEffectProperty sphereEffectProperty = agent.RegisterOrGetProperty(); sphereEffectProperty.HandlerCount = 0; sphereEffectProperty.Setting = EffectVolume; } } } internal sealed class SphereEffectProperty { public int HandlerCount; public EffectVolumeSetting Setting; } public sealed class HealthRegenCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public sealed class HealthRegenData { public float RegenInterval { get; set; } = 1f; public float DelayUntilRegenStart { get; set; } = 5f; public bool CanDamageInterruptRegen { get; set; } = true; public ValueBase RegenAmount { get; set; } = ValueBase.Zero; public ValueBase RegenCap { get; set; } = ValueBase.Zero; } public HealthRegenData[] RegenDatas { get; set; } = Array.Empty(); public override string GetProcessName() { return "HealthRegen"; } public void OnSpawned(EnemyAgent agent) { if ((Object)(object)agent.Damage != (Object)null) { HealthRegenData[] regenDatas = RegenDatas; foreach (HealthRegenData regenData in regenDatas) { HealthRegenHandler healthRegenHandler = ((Component)agent).gameObject.AddComponent(); healthRegenHandler.DamageBase = agent.Damage; healthRegenHandler.RegenData = regenData; } } } } public sealed class PouncerCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent { public ValueBase DashCooldownMin { get; set; } = ValueBase.Unchanged; public ValueBase DashCooldownMax { get; set; } = ValueBase.Unchanged; public ValueBase DashMaxTime { get; set; } = ValueBase.Unchanged; public ValueBase ChargeDuration { get; set; } = ValueBase.Unchanged; public ValueBase ConsumeDuration { get; set; } = ValueBase.Unchanged; public ValueBase DashEndPhaseDistance { get; set; } = ValueBase.Unchanged; public ValueBase DashEndAnimationLength { get; set; } = ValueBase.Unchanged; public ValueBase ChargeStaggerDamageThreshold { get; set; } = ValueBase.Unchanged; public ValueBase DashStaggerDamageThreshold { get; set; } = ValueBase.Unchanged; public ValueBase StaggerDuration { get; set; } = ValueBase.Unchanged; public ValueBase FaceToTargetDuringProwlingDistance { get; set; } = ValueBase.Unchanged; public BoolBase StaggerLeadsToAfterHeld { get; set; } = BoolBase.Unchanged; public BoolBase EnableOffMeshLinkDash { get; set; } = BoolBase.Unchanged; public BoolBase LOSRequiredForDash { get; set; } = BoolBase.Unchanged; public BoolBase DashStaggerUsesHeavyHitreaction { get; set; } = BoolBase.Unchanged; public BoolBase Enable1PConsumeVFX { get; set; } = BoolBase.Unchanged; public BoolBase Enable3PConsumeVFX { get; set; } = BoolBase.Unchanged; public MovementModificationData DashMovementModifier { get; set; } = new MovementModificationData(); public HeldStateData HeldStateData { get; set; } = new HeldStateData(); public DamageShapeData DamageShapeData { get; set; } = new DamageShapeData(); public PouncerSoundData PouncerSoundData { get; set; } = new PouncerSoundData(); public HeldPathingData CombatStatePathingData { get; set; } = new HeldPathingData(); public override string GetProcessName() { return "Pouncer"; } public void OnSpawned(EnemyAgent agent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) PouncerBehaviour component = ((Component)agent).GetComponent(); PouncerDataContainer val = Object.Instantiate(component.Data); Vector2 dashCooldown = new Vector2 { x = DashCooldownMin.GetAbsValue(val.m_DashCooldown.x), y = DashCooldownMax.GetAbsValue(val.m_DashCooldown.y) }; val.m_DashCooldown = dashCooldown; val.DashMaxTime = DashMaxTime.GetAbsValue(val.DashMaxTime); val.ChargeDuration = ChargeDuration.GetAbsValue(val.ChargeDuration); val.ConsumeDuration = ConsumeDuration.GetAbsValue(val.ConsumeDuration); val.DashEndPhaseDistance = DashEndPhaseDistance.GetAbsValue(val.DashEndPhaseDistance); val.DashEndAnimationLength = DashEndAnimationLength.GetAbsValue(val.DashEndAnimationLength); val.ChargeStaggerDamageThreshold = ChargeStaggerDamageThreshold.GetAbsValue(val.ChargeStaggerDamageThreshold); val.DashStaggerDamageThreshold = DashStaggerDamageThreshold.GetAbsValue(val.DashStaggerDamageThreshold); val.DashStaggerDamageThreshold = DashStaggerDamageThreshold.GetAbsValue(val.DashStaggerDamageThreshold); val.StaggerDuration = StaggerDuration.GetAbsValue(val.StaggerDuration); val.FaceToTargetDuringProwlingDistance = FaceToTargetDuringProwlingDistance.GetAbsValue(val.FaceToTargetDuringProwlingDistance); val.StaggerLeadsToAfterHeld = StaggerLeadsToAfterHeld.GetValue(val.StaggerLeadsToAfterHeld); val.EnableOffMeshLinkDash = EnableOffMeshLinkDash.GetValue(val.EnableOffMeshLinkDash); val.LOSRequiredForDash = LOSRequiredForDash.GetValue(val.LOSRequiredForDash); val.DashStaggerUsesHeavyHitreaction = DashStaggerUsesHeavyHitreaction.GetValue(val.DashStaggerUsesHeavyHitreaction); val.Enable1PConsumeVFX = Enable1PConsumeVFX.GetValue(val.Enable1PConsumeVFX); val.Enable3PConsumeVFX = Enable3PConsumeVFX.GetValue(val.Enable3PConsumeVFX); val.DashMovementModifier = DashMovementModifier.ToData(val.DashMovementModifier); val.HeldStateData = HeldStateData.ToData(val.HeldStateData); val.DamageShapeData = DamageShapeData.ToData(val.DamageShapeData); val.PouncerSoundData = PouncerSoundData.ToData(); val.CombatStatePathingData = CombatStatePathingData.ToData(val.CombatStatePathingData); component.m_data = val; } } public sealed class MovementModificationData { public ValueBase SpeedModifier { get; set; } = ValueBase.Unchanged; public ValueBase AccelerationModifier { get; set; } = ValueBase.Unchanged; public MovementModificationData ToData(MovementModificationData originalData) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) MovementModificationData result = default(MovementModificationData); result.SpeedModifier = SpeedModifier.GetAbsValue(originalData.SpeedModifier); result.AccelerationModifier = AccelerationModifier.GetAbsValue(originalData.AccelerationModifier); return result; } } public sealed class HeldStateData { public ValueBase HeldStartAnimationDuration { get; set; } = ValueBase.Unchanged; public ValueBase MaxHeldDuration { get; set; } = ValueBase.Unchanged; public ValueBase DamageToPlayerPerSecond { get; set; } = ValueBase.Unchanged; public ValueBase DamageOnStartHolding { get; set; } = ValueBase.Unchanged; public ValueBase AfterHeldRunAwayDuration { get; set; } = ValueBase.Unchanged; public ValueBase SpitOutStateDuration { get; set; } = ValueBase.Unchanged; public BoolBase ValidatePlayerDimension { get; set; } = BoolBase.Unchanged; public HeldPathingData PathingData { get; set; } = new HeldPathingData(); public HeldStateData ToData(HeldStateData orig) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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) HeldStateData result = default(HeldStateData); result.HeldStartAnimationDuration = HeldStartAnimationDuration.GetAbsValue(orig.HeldStartAnimationDuration); result.MaxHeldDuration = MaxHeldDuration.GetAbsValue(orig.MaxHeldDuration); result.DamageToPlayerPerSecond = DamageToPlayerPerSecond.GetAbsValue(orig.DamageToPlayerPerSecond); result.DamageOnStartHolding = DamageOnStartHolding.GetAbsValue(orig.DamageOnStartHolding); result.AfterHeldRunAwayDuration = AfterHeldRunAwayDuration.GetAbsValue(orig.AfterHeldRunAwayDuration); result.SpitOutStateDuration = SpitOutStateDuration.GetAbsValue(orig.SpitOutStateDuration); result.ValidatePlayerDimension = ValidatePlayerDimension.GetValue(orig.ValidatePlayerDimension); result.PathingData = PathingData.ToData(orig.PathingData); return result; } } public sealed class DamageShapeData { public ValueBase Radius { get; set; } = ValueBase.Unchanged; public ValueBase Angle { get; set; } = ValueBase.Unchanged; public DamageShapeData ToData(DamageShapeData orig) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) DamageShapeData result = default(DamageShapeData); result.Radius = Radius.GetAbsValue(orig.Radius); result.Angle = Angle.GetAbsValue(orig.Angle); return result; } } public sealed class PouncerSoundData { public uint AttackCharge { get; set; } = 2040824805u; public uint AttackHit { get; set; } = 1034385728u; public uint AttackMiss { get; set; } = 1149851817u; public uint DashStart { get; set; } = 3726964003u; public uint HeldIdle { get; set; } = 376939216u; public uint HeldSpitOut { get; set; } = 2870456237u; public uint IdleGrowl { get; set; } = 3799706438u; public uint TentacleLoop { get; set; } = 3217748688u; public PouncerSoundData ToData() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) PouncerSoundData result = default(PouncerSoundData); result.AttackCharge = AttackCharge; result.AttackHit = AttackHit; result.AttackMiss = AttackMiss; result.DashStart = DashStart; result.HeldIdle = HeldIdle; result.HeldSpitOut = HeldSpitOut; result.IdleGrowl = IdleGrowl; result.TentacleLoop = TentacleLoop; return result; } } public sealed class HeldPathingData { public ValueBase DstChangeRate { get; set; } = ValueBase.Unchanged; public ValueBase TryToKeepDistance { get; set; } = ValueBase.Unchanged; public BoolBase RecursiveReachableNodeSearch { get; set; } = BoolBase.Unchanged; public MovementModificationData MovementModifier { get; set; } = new MovementModificationData(); public HeldPathingData ToData(HeldPathingData orig) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) HeldPathingData result = default(HeldPathingData); result.DstChangeRate = DstChangeRate.GetAbsValue(orig.DstChangeRate); result.TryToKeepDistance = TryToKeepDistance.GetAbsValue(orig.TryToKeepDistance); result.RecursiveReachableNodeSearch = RecursiveReachableNodeSearch.GetValue(orig.RecursiveReachableNodeSearch); result.MovementModifier = MovementModifier.ToData(orig.MovementModifier); return result; } } public sealed class ScoutScreamingCustom : EnemyCustomBase, IEnemySpawnedEvent, IEnemyEvent, IEnemyGlowEvent { public static readonly Color DefaultChargeupColor = ES_ScoutScream.s_screamChargeupColor; public static readonly Color DefaultScreamColor = ES_ScoutScream.s_screamPopColor; public Color ChargeupColor { get; set; } = new Color(0f, 1f, 0.8f, 1f) * 2f; public Color ScreamColor { get; set; } = new Color(0f, 1f, 0.8f, 1f) * 20f; public Color FogColor { get; set; } = new Color(0f, 1f, 0.8f, 1f) * 20f; public float FogIntensity { get; set; } = 1f; public EffectVolumeSetting EffectVolume { get; set; } = new EffectVolumeSetting(); public override string GetProcessName() { return "ScoutScreaming"; } public void OnSpawned(EnemyAgent agent) { //IL_001f: 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_004f: Unknown result type (might be due to invalid IL or missing references) ScoutFogSphereHandler scoutFogSphereHandler = ((Component)agent).gameObject.AddComponent(); scoutFogSphereHandler.ScoutScream = agent.Locomotion.ScoutScream; scoutFogSphereHandler.FogColor = FogColor; scoutFogSphereHandler.FogIntensity = FogIntensity; if (EffectVolume.Enabled) { scoutFogSphereHandler.EVSphere = EffectVolume.CreateSphere(((Component)agent).transform.position, 0f, 0f); EffectVolumeManager.RegisterVolume((EffectVolume)(object)scoutFogSphereHandler.EVSphere); } } public bool OnGlow(EnemyAgent agent, ref GlowInfo glowInfo) { //IL_0001: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (glowInfo.Color == DefaultChargeupColor) { glowInfo = glowInfo.ChangeColor(ChargeupColor); return true; } if (glowInfo.Color == DefaultScreamColor) { glowInfo = glowInfo.ChangeColor(ScreamColor); return true; } return false; } } } namespace EEC.EnemyCustomizations.Abilities.Inject { [HarmonyPatch(typeof(EAB_FogSphere), "DoTrigger")] internal static class Inject_EAB_FogSphere { [HarmonyWrapSafe] internal static void Prefix(EAB_FogSphere __instance) { if (((EnemyAbility)__instance).m_owner.TryGetProperty(out var property)) { property.HandlerCount = __instance.m_activeFogSpheres.Count; } } [HarmonyWrapSafe] internal static void Postfix(EAB_FogSphere __instance) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAbility)__instance).m_owner.TryGetProperty(out var property) && property.HandlerCount != __instance.m_activeFogSpheres.Count) { List activeFogSpheres = __instance.m_activeFogSpheres; FogSphereHandler val = activeFogSpheres[activeFogSpheres.Count - 1]; if (!((Object)(object)((Component)val).gameObject.GetComponent() != (Object)null)) { EffectFogSphereHandler effectFogSphereHandler = ((Component)val).gameObject.AddComponent(); effectFogSphereHandler.Handler = val; effectFogSphereHandler.EVSphere = property.Setting.CreateSphere(((Component)val).transform.position, 0f, 0f); EffectVolumeManager.RegisterVolume((EffectVolume)(object)effectFogSphereHandler.EVSphere); } } } } [HarmonyPatch(typeof(EB_InCombat_MoveToNextNode_DestroyDoor), "UpdateBehaviour")] internal static class Inject_EB_DestroyDoor { public static bool ShouldOverride; public static float GlobalTimer; public const float MinTime = 0.5f; public const float MaxTime = 1f; public const float Range = 0.5f; public static float DefaultRandomDelay => Rand.NextFloat() * 0.5f + 0.5f; [HarmonyWrapSafe] internal static void Postfix(EB_InCombat_MoveToNextNode_DestroyDoor __instance) { if (!ShouldOverride) { return; } if (((EB_StateBase)__instance).m_ai.m_enemyAgent.TryGetProperty(out var property)) { if (property.UseGlobalTimer && property.Config._globalTimer < Clock.ExpeditionProgressionTime) { if (TryDamageDoor(__instance, property.Damage)) { property.Config._globalTimer = Clock.ExpeditionProgressionTime + Rand.Range(property.MinDelay, property.MaxDelay); } } else if (!property.UseGlobalTimer && property.Timer < Clock.ExpeditionProgressionTime && TryDamageDoor(__instance, property.Damage)) { property.Timer = Clock.ExpeditionProgressionTime + Rand.Range(property.MinDelay, property.MaxDelay); } } else if (!(GlobalTimer >= Clock.ExpeditionProgressionTime) && TryDamageDoor(__instance, 1f)) { GlobalTimer = Clock.ExpeditionProgressionTime + DefaultRandomDelay; } } private static bool TryDamageDoor(EB_InCombat_MoveToNextNode_DestroyDoor context, float damage) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) Agent agent = ((AgentAI)((EB_StateBase)context).m_ai).Agent; ((AgentAI)((EB_StateBase)context).m_ai).Agent.TargetLookDir = ((EB_StateBase)context).m_ai.m_courseNavigation.m_onPortalPosition - agent.Position; Vector3 targetLookDir = ((AgentAI)((EB_StateBase)context).m_ai).Agent.TargetLookDir; ((Vector3)(ref targetLookDir)).Normalize(); targetLookDir = agent.TargetLookDir; if (((Vector3)(ref targetLookDir)).sqrMagnitude >= 6.25f) { return false; } LG_WeakDoor val = ((Il2CppObjectBase)((EB_StateBase)context).m_ai.m_courseNavigation.m_navPortal.m_door).TryCast(); if ((Object)(object)val == (Object)null) { return false; } val.m_sync.AttemptDoorInteraction((eDoorInteractionType)7, damage, 0f, agent.Position, (Agent)null); return true; } } } namespace EEC.EnemyCustomizations.Abilities.Handlers { [InjectToIl2Cpp] internal sealed class HealthRegenHandler : MonoBehaviour { public Dam_EnemyDamageBase DamageBase; public HealthRegenCustom.HealthRegenData RegenData; private Timer _regenInitialTimer; private Timer _regenIntervalTimer; private bool _isRegening; private bool _isInitialTimerDone; private bool _alwaysRegen; private bool _isRegenMode; private float _regenCapAbsValue; private float _regenAmountAbsValue; private void Start() { _isRegening = false; _alwaysRegen = !RegenData.CanDamageInterruptRegen; if (!_alwaysRegen) { EnemyDamageEvents.Damage += OnTakeDamage; DamageBase.Owner.AddOnDeadOnce(delegate { EnemyDamageEvents.Damage -= OnTakeDamage; }); } _regenCapAbsValue = RegenData.RegenCap.GetAbsValue(((Dam_SyncedDamageBase)DamageBase).HealthMax); _regenAmountAbsValue = RegenData.RegenAmount.GetAbsValue(((Dam_SyncedDamageBase)DamageBase).HealthMax); if (_regenAmountAbsValue >= 0f) { _isRegenMode = true; } if (_alwaysRegen || !_isRegenMode) { StartRegen(); } } private void FixedUpdate() { if (!SNet.IsMaster || !_isRegening) { return; } if (!_isInitialTimerDone && _regenInitialTimer.TickAndCheckDone()) { _isInitialTimerDone = true; } else if (_isInitialTimerDone && _regenIntervalTimer.TickAndCheckDone()) { if (_isRegenMode) { DoRegen(); } else { DoDecay(); } _regenIntervalTimer.Reset(RegenData.RegenInterval); } } [HideFromIl2Cpp] private void StartRegen() { _regenInitialTimer.Reset(RegenData.DelayUntilRegenStart); _isRegening = true; _isInitialTimerDone = false; } [HideFromIl2Cpp] private void DoRegen() { if (((Dam_SyncedDamageBase)DamageBase).Health >= _regenCapAbsValue) { if (!_alwaysRegen) { _isRegening = false; } return; } float num = ((Dam_SyncedDamageBase)DamageBase).Health + _regenAmountAbsValue; if (num >= _regenCapAbsValue) { num = _regenCapAbsValue; if (!_alwaysRegen) { _isRegening = false; } } ((Dam_SyncedDamageBase)DamageBase).SendSetHealth(num); } [HideFromIl2Cpp] private void DoDecay() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (((Dam_SyncedDamageBase)DamageBase).Health <= _regenCapAbsValue) { if (!_alwaysRegen) { _isRegening = false; } return; } float num = ((Dam_SyncedDamageBase)DamageBase).Health + _regenAmountAbsValue; if (num <= _regenCapAbsValue) { num = _regenCapAbsValue; if (!_alwaysRegen) { _isRegening = false; } } ((Dam_SyncedDamageBase)DamageBase).SendSetHealth(num); if (num <= 0f) { DamageBase.MeleeDamage(((Dam_SyncedDamageBase)DamageBase).HealthMax, (Agent)null, ((Component)this).transform.position, Vector3.up, 0, 1f, 1f, 1f, 1f, false, (DamageNoiseLevel)0, 0u); } } [HideFromIl2Cpp] private void OnTakeDamage(EnemyAgent enemy, Agent inflictor, float damage) { if (((Agent)enemy).GlobalID == ((Agent)DamageBase.Owner).GlobalID) { StartRegen(); } } private void OnDestroy() { DamageBase = null; RegenData = null; } } [InjectToIl2Cpp] internal sealed class ScoutFogSphereHandler : MonoBehaviour { public Color FogColor; public float FogIntensity; public ES_ScoutScream ScoutScream; public EV_Sphere EVSphere; private Timer _updateTimer = new Timer(0.1f); private bool _isColorSet; private void Update() { //IL_0022: 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_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) if (ScoutScream.m_fogSphereAdd == null) { return; } if (!_isColorSet) { ScoutScream.m_fogSphereAdd.SetRadiance(FogColor, FogIntensity); _isColorSet = true; } if (EVSphere != null && _updateTimer.TickAndCheckDone()) { if (ScoutScream.m_fogSphereAdd.IsAllocated) { FogSphere sphere = ScoutScream.m_fogSphereAdd.m_sphere; float num = Mathf.Sqrt(1f / sphere.m_data.InvRangeSqr); EVSphere.minRadius = num * 0.8f; EVSphere.maxRadius = num; EVSphere.position = ScoutScream.m_fogSphereAdd.m_sphere.m_data.Position; _updateTimer.Reset(); } else { EVSphere.minRadius = 0f; EVSphere.maxRadius = 0f; } } } private void OnDestroy() { if (EVSphere != null) { EffectVolumeManager.UnregisterVolume((EffectVolume)(object)EVSphere); } ScoutScream = null; EVSphere = null; } } } namespace EEC.CustomSettings.CustomTentacles { public sealed class CustomTentacle { public string DebugName { get; set; } = string.Empty; public int ID { get; set; } = 15; public GPUCurvyType BodyPrefab { get; set; } = (GPUCurvyType)1; public GPUCurvyType BodyMaterial { get; set; } = (GPUCurvyType)1; public GPUCurvyType HeadPrefab { get; set; } = (GPUCurvyType)1; public GPUCurvyType HeadMaterial { get; set; } = (GPUCurvyType)1; public GPUCurvyType Shape { get; set; } = (GPUCurvyType)1; public int MaxCount { get; set; } = 50; } public static class CustomTentacleManager { private static readonly Dictionary _tentacleSetups = new Dictionary(); public static void GenerateTentacle(CustomTentacle tentInfo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) //IL_0064: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if (IsDefaultType(tentInfo.BodyPrefab) && IsDefaultType(tentInfo.BodyMaterial) && IsDefaultType(tentInfo.HeadPrefab) && IsDefaultType(tentInfo.HeadMaterial) && IsDefaultType(tentInfo.Shape) && !_tentacleSetups.ContainsKey(tentInfo.ID)) { GameObject val = new GameObject(); Object.DontDestroyOnLoad((Object)val); GPUC_Setup val2 = val.AddComponent(); val2.m_bodyPrefab = GetSetup(tentInfo.BodyPrefab).m_bodyPrefab; val2.m_bodyTileMaterial = GetSetup(tentInfo.BodyMaterial).m_bodyTileMaterial; val2.m_headPrefab = GetSetup(tentInfo.HeadPrefab).m_headPrefab; val2.m_headMaterial = GetSetup(tentInfo.HeadMaterial).m_headMaterial; GPUC_Setup setup = GetSetup(tentInfo.BodyPrefab); Logger.Warning($"limit: {setup.m_globalLimit}, gbuffer: {setup.m_renderToGBuffer}, segMax: {setup.m_segmentsMax}"); val2.m_globalLimit = 50; val2.m_renderToGBuffer = true; val2.m_shape = GetSetup(tentInfo.Shape).m_shape; val2.Setup(); _tentacleSetups.Add(tentInfo.ID, val2); Logger.Debug($"Added Tentacle!: {tentInfo.ID} ({tentInfo.DebugName})"); } } public static bool IsDefaultType(GPUCurvyType type) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return Enum.IsDefined(typeof(GPUCurvyType), type); } public static GPUC_Setup GetSetup(GPUCurvyType type) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected I4, but got Unknown return ((Il2CppArrayBase)(object)GPUCurvyManager.Current.m_setups)[(int)type]; } public static GPUC_Setup GetTentacle(int id) { if (_tentacleSetups.TryGetValue(id, out GPUC_Setup value)) { return value; } return null; } } } namespace EEC.CustomSettings.CustomTentacles.Inject { [HarmonyPatch(typeof(GPUCurvyManager))] internal static class Inject_GPUCurvyManager { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("Setup")] internal static void Post_Setup() { CustomTentacle[] tentacleDefinitions = ConfigManager.TentacleCustom.TentacleDefinitions; for (int i = 0; i < tentacleDefinitions.Length; i++) { CustomTentacleManager.GenerateTentacle(tentacleDefinitions[i]); } } [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("TryAllocateGPUCurvy")] internal static bool Pre_Allocate(GPUCurvyType type, ref GPUCurvy gpuCurvy) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Expected I4, but got Unknown int num = (int)type; if (Enum.IsDefined(typeof(GPUCurvyType), num)) { return true; } if (CustomTentacleManager.GetTentacle(num).TryCanAllocate(ref gpuCurvy)) { Logger.Error($"ALLOC {num}"); return false; } Logger.Error($"CANT FIND TENTACLE SETTING WITH ID: {num}"); return true; } } } namespace EEC.CustomSettings.CustomScoutWaves { [CallConstructorOnLoad] public static class CustomScoutWaveManager { private static readonly List _scoutSettings; private static readonly List _activeScoutSettings; private static readonly Dictionary _targetSettingDict; private static readonly Dictionary _waveSettingDict; private static string _previousExpKey; private static ExpeditionData _previousExpData; private static uint _defaultWaveSettingID; private static uint _defaultWavePopulationID; private static eRundownTier _currentExpeditionTier; private static int _currentExpeditionIndex; private static bool _isDefaultSettingBlocked; static CustomScoutWaveManager() { _scoutSettings = new List(); _activeScoutSettings = new List(); _targetSettingDict = new Dictionary(); _waveSettingDict = new Dictionary(); _previousExpKey = string.Empty; _previousExpData = null; _isDefaultSettingBlocked = false; LevelEvents.BuildStart += OnLevelStateUpdate; LevelEvents.LevelCleanup += OnLevelStateUpdate; } private static void OnLevelStateUpdate() { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) string activeExpeditionUniqueKey = RundownManager.ActiveExpeditionUniqueKey; if (string.IsNullOrEmpty(activeExpeditionUniqueKey)) { Logger.Log("KEY WAS EMPTY"); } else if (!activeExpeditionUniqueKey.InvariantEquals(_previousExpKey)) { _previousExpKey = activeExpeditionUniqueKey; string[] array = activeExpeditionUniqueKey.Split("_"); eRundownTier result; int result2; if (array.Length != 4) { Logger.Warning($"Key split length was not 4?: Length: {array.Length} Raw: {activeExpeditionUniqueKey}"); } else if (!Enum.TryParse(array[2], out result)) { Logger.Warning("Tier is not valid?: " + array[2]); } else if (!int.TryParse(array[3], out result2)) { Logger.Warning("Index was not a number?: " + array[3]); } else { ExpeditionUpdate(result, result2, RundownManager.ActiveExpedition); } } } public static void ExpeditionUpdate(eRundownTier tier, int expIndex, ExpeditionInTierData inTierData) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) _isDefaultSettingBlocked = false; if (_previousExpData != null) { _previousExpData.ScoutWaveSettings = _defaultWaveSettingID; _previousExpData.ScoutWavePopulation = _defaultWavePopulationID; } _previousExpData = inTierData.Expedition; _defaultWaveSettingID = _previousExpData.ScoutWaveSettings; _defaultWavePopulationID = _previousExpData.ScoutWavePopulation; _currentExpeditionTier = tier; _currentExpeditionIndex = expIndex; _activeScoutSettings.Clear(); foreach (ExpeditionScoutSetting scoutSetting in _scoutSettings) { if (!scoutSetting.IsMatch(_currentExpeditionTier, _currentExpeditionIndex)) { continue; } ScoutWaveSet[] scoutSettings = scoutSetting.ScoutSettings; foreach (ScoutWaveSet obj in scoutSettings) { ScoutTargetSetting targetSetting = GetTargetSetting(obj.TargetSetting); ScoutWaveSetting waveSetting = GetWaveSetting(obj.WaveSetting); if (targetSetting != null && waveSetting != null) { ScoutSettingCache scoutSettingCache = default(ScoutSettingCache); scoutSettingCache.TargetSetting = targetSetting; scoutSettingCache.WaveSetting = waveSetting; ScoutSettingCache item = scoutSettingCache; _activeScoutSettings.Add(item); } } } if (_activeScoutSettings.Count > 0) { _previousExpData.ScoutWaveSettings = 0u; _previousExpData.ScoutWavePopulation = 0u; _isDefaultSettingBlocked = true; } } public static void AddScoutSetting(params ExpeditionScoutSetting[] scoutSettings) { for (int i = 0; i < scoutSettings.Length; i++) { AddScoutSetting(scoutSettings[i]); } } public static void AddScoutSetting(ExpeditionScoutSetting scoutSetting) { _scoutSettings.Add(scoutSetting); } public static void AddWaveSetting(params ScoutWaveSetting[] waveSettings) { for (int i = 0; i < waveSettings.Length; i++) { AddWaveSetting(waveSettings[i]); } } public static void AddWaveSetting(ScoutWaveSetting waveSetting) { string key = waveSetting.Name.ToLowerInvariant(); if (!_waveSettingDict.ContainsKey(key)) { _waveSettingDict.Add(key, waveSetting); } } public static ScoutWaveSetting GetWaveSetting(string name) { string key = name.ToLowerInvariant(); if (_waveSettingDict.ContainsKey(key)) { return _waveSettingDict[key]; } return null; } public static void AddTargetSetting(params ScoutTargetSetting[] targetSettings) { for (int i = 0; i < targetSettings.Length; i++) { AddTargetSetting(targetSettings[i]); } } public static void AddTargetSetting(ScoutTargetSetting targetSetting) { string key = targetSetting.Name.ToLowerInvariant(); if (!_targetSettingDict.ContainsKey(key)) { _targetSettingDict.Add(key, targetSetting); } } public static ScoutTargetSetting GetTargetSetting(string name) { string key = name.ToLowerInvariant(); if (_targetSettingDict.ContainsKey(key)) { return _targetSettingDict[key]; } return null; } public static void ClearAll() { _scoutSettings.Clear(); _waveSettingDict.Clear(); _targetSettingDict.Clear(); } public static void TriggerScoutWave(EnemyAgent scoutAgent) { if (!_isDefaultSettingBlocked) { return; } bool flag = false; List stopOnDeathWaves = new List(); foreach (ScoutSettingCache activeScoutSetting in _activeScoutSettings) { ScoutTargetSetting targetSetting = activeScoutSetting.TargetSetting; ScoutWaveSetting waveSetting = activeScoutSetting.WaveSetting; if (!targetSetting.Target.IsMatch(scoutAgent.EnemyDataID) || waveSetting.Waves.GetLength(0) <= 0) { continue; } int length = waveSetting.Waves.GetLength(0); if (length > 1) { float[] array = new float[length]; if (waveSetting.WeightsOverride.Length != 0) { for (int i = 0; i < waveSetting.WeightsOverride.Length; i++) { array[i] = Math.Min(0f, waveSetting.WeightsOverride[i]); } } int num = PickWeightedRandom(array); TriggerWaves(waveSetting.Waves[num], ((Agent)scoutAgent).CourseNode, ref stopOnDeathWaves); flag = true; break; } if (length == 1) { TriggerWaves(waveSetting.Waves[0], ((Agent)scoutAgent).CourseNode, ref stopOnDeathWaves); flag = true; break; } Logger.Warning("WaveSetting count was zero: Wave has ignored"); } if (flag) { if (stopOnDeathWaves.Count <= 0) { return; } scoutAgent.AddOnDeadOnce(delegate { MastermindEvent val = default(MastermindEvent); foreach (ushort item in stopOnDeathWaves) { if (Mastermind.Current.TryGetEvent(item, ref val)) { val.StopEvent(); } } }); } else { TriggerDefaultWave(((Agent)scoutAgent).CourseNode); } } private static int PickWeightedRandom(float[] weights) { if (weights.Length == 0) { throw new ArgumentException("weights length is zero!"); } if (weights.Length == 1) { return 0; } float[] array = new float[weights.Length]; weights.CopyTo(array, 0); float num = array.Sum(); if (num <= 0f) { return Rand.IndexOf(weights); } float num2 = 0f; for (int i = 0; i < array.Length; i++) { if (array[i] <= 0f) { array[i] = -1f; } else { num2 = (array[i] = num2 + array[i]); } } float num3 = Rand.NextFloat() * num; for (int j = 0; j < array.Length; j++) { if (array[j] >= num3) { return j; } } throw new IndexOutOfRangeException("index was not picked?!"); } private static void TriggerWaves(WaveSetting[] waves, AIG_CourseNode sourceNode, ref List stopOnDeathList) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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) LG_Zone val3 = default(LG_Zone); ushort item = default(ushort); foreach (WaveSetting waveSetting in waves) { SurvivalWaveSpawnType val = (SurvivalWaveSpawnType)(waveSetting.SpawnSetting.SpawnType switch { WaveSpawnType.ClosestAlive => 0, WaveSpawnType.ClosestNoBetweenPlayers => 4, WaveSpawnType.InNode => 2, WaveSpawnType.InNodeZone => 1, _ => 0, }); AIG_CourseNode val2 = sourceNode; switch (waveSetting.SpawnSetting.NodeType) { case SpawnNodeType.FromArea: if (Builder.CurrentFloor.TryGetZoneByLocalIndex(val2.m_dimension.DimensionIndex, waveSetting.SpawnSetting.Layer, waveSetting.SpawnSetting.LocalIndex, ref val3)) { val2 = ((waveSetting.SpawnSetting.AreaIndex >= val3.m_areas.Count) ? val3.m_areas[0].m_courseNode : val3.m_areas[waveSetting.SpawnSetting.AreaIndex].m_courseNode); } break; case SpawnNodeType.FromElevatorArea: val2 = Builder.GetElevatorArea().m_courseNode; break; } Mastermind.Current.TriggerSurvivalWave(val2, waveSetting.WaveSettingID, waveSetting.WavePopulationID, ref item, val, waveSetting.Delay, 2f, true, false, default(Vector3), ""); if (waveSetting.StopWaveOnDeath) { stopOnDeathList.Add(item); } } } private static void TriggerDefaultWave(AIG_CourseNode sourceNode) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Logger.Debug("Can't found good setting for scout, Spawning Default"); ushort num = default(ushort); Mastermind.Current.TriggerSurvivalWave(sourceNode, _defaultWaveSettingID, _defaultWavePopulationID, ref num, (SurvivalWaveSpawnType)0, 0f, 2f, true, false, default(Vector3), ""); } } public struct ScoutSettingCache { public ScoutTargetSetting TargetSetting; public ScoutWaveSetting WaveSetting; } public sealed class ExpeditionScoutSetting { public string[] Targets { get; set; } = Array.Empty(); public ScoutWaveSet[] ScoutSettings { get; set; } = Array.Empty(); public bool IsMatch(eRundownTier tier, int index) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected I4, but got Unknown string strToCompare = (tier - 1) switch { 0 => "A", 1 => "B", 2 => "C", 3 => "D", 4 => "E", _ => "?", }; string[] targets = Targets; foreach (string text in targets) { if (text.InvariantEquals("*")) { return true; } string text2 = text.Trim().ToUpper(); if (text2.Length < 2) { continue; } string text3 = text2.Substring(0, 1); string text4 = text2; string text5 = text4.Substring(1, text4.Length - 1); int result = -1; switch (text3) { case "A": case "B": case "C": case "D": case "E": text3 = text2.Substring(0, 1); break; case "*": text3 = string.Empty; break; default: continue; } if (string.IsNullOrEmpty(text3) || text3.InvariantEquals(strToCompare, ignoreCase: true)) { if (text5.InvariantEquals("*")) { return true; } if (int.TryParse(text5, out result) && result == index + 1) { return true; } } } return false; } } public sealed class ScoutWaveSet { public string TargetSetting { get; set; } = string.Empty; public string WaveSetting { get; set; } = string.Empty; } public sealed class ScoutTargetSetting { public string Name { get; set; } = string.Empty; public TargetSetting Target { get; set; } = new TargetSetting(); } public sealed class ScoutWaveSetting { public string Name { get; set; } = string.Empty; public WaveSetting[][] Waves { get; set; } = Array.Empty(); public float[] WeightsOverride { get; set; } = Array.Empty(); } public sealed class WaveSetting { public SpawnNodeSetting SpawnSetting = new SpawnNodeSetting { SpawnType = WaveSpawnType.ClosestAlive, NodeType = SpawnNodeType.Scout }; public uint WaveSettingID { get; set; } public uint WavePopulationID { get; set; } public float Delay { get; set; } public bool StopWaveOnDeath { get; set; } } public sealed class SpawnNodeSetting { public WaveSpawnType SpawnType { get; set; } public SpawnNodeType NodeType { get; set; } public LG_LayerType Layer { get; set; } public eLocalZoneIndex LocalIndex { get; set; } public int AreaIndex { get; set; } } public enum WaveSpawnType { ClosestAlive, ClosestNoBetweenPlayers, InNode, InNodeZone } public enum SpawnNodeType { Scout, FromArea, FromElevatorArea } } namespace EEC.CustomSettings.CustomScoutWaves.Inject { [HarmonyPatch(typeof(ES_ScoutScream), "CommonUpdate")] internal static class Inject_ES_ScoutScream { [HarmonyWrapSafe] internal static void Postfix(ES_ScoutScream __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)__instance.m_state == 4 && __instance.m_stateDoneTimer >= 0f) { __instance.m_stateDoneTimer = -1f; if (SNet.IsMaster) { CustomScoutWaveManager.TriggerScoutWave(((ES_Base)__instance).m_enemyAgent); } } } } } namespace EEC.CustomSettings.CustomProjectiles { public sealed class CustomProjectile { public string DebugName { get; set; } = string.Empty; public byte ID { get; set; } = 10; public ProjectileType BaseProjectile { get; set; } public ValueBase Speed { get; set; } = ValueBase.Unchanged; public MultiplierShiftSetting SpeedChange { get; set; } = new MultiplierShiftSetting(); public ValueBase CheckEvasiveDistance { get; set; } = ValueBase.Unchanged; public ValueBase InitialHomingDuration { get; set; } = ValueBase.Unchanged; public ValueBase InitialHomingStrength { get; set; } = ValueBase.Unchanged; public ValueBase HomingDelay { get; set; } = ValueBase.Unchanged; public ValueBase HomingStrength { get; set; } = ValueBase.Unchanged; public MultiplierShiftSetting HomingStrengthChange { get; set; } = new MultiplierShiftSetting(); public ValueBase LifeTime { get; set; } = ValueBase.Unchanged; public Color TrailColor { get; set; } = Color.yellow; public ValueBase TrailTime { get; set; } = ValueBase.Unchanged; public ValueBase TrailWidth { get; set; } = ValueBase.Unchanged; public Color GlowColor { get; set; } = Color.yellow; public ValueBase GlowRange { get; set; } = ValueBase.Unchanged; public uint CollisionSoundID { get; set; } public ValueBase Damage { get; set; } = ValueBase.Unchanged; public ValueBase Infection { get; set; } = ValueBase.Unchanged; [JsonPropertyName("SpawnProjectileOnCollideWorld")] public SpawnProjectileSetting SpawnProjColWorld { get; set; } = new SpawnProjectileSetting(); [JsonPropertyName("SpawnProjectileOnCollidePlayer")] public SpawnProjectileSetting SpawnProjColPlayer { get; set; } = new SpawnProjectileSetting(); [JsonPropertyName("SpawnProjectileOnLifeTimeDone")] public SpawnProjectileSetting SpawnProjLifeDone { get; set; } = new SpawnProjectileSetting(); public ExplosionSetting Explosion { get; set; } = new ExplosionSetting(); public KnockbackSetting Knockback { get; set; } = new KnockbackSetting(); public BleedSetting Bleed { get; set; } = new BleedSetting(); public DrainStaminaSetting DrainStamina { get; set; } = new DrainStaminaSetting(); public bool HitEnemies { get; set; } public void DoCollisionEffect(ProjectileBase proj, Vector3 projectilePosition, PlayerAgent player = null) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) ExplosionSetting explosion = Explosion; if (explosion != null && explosion.Enabled) { Explosion.DoLocalExplode(projectilePosition); } if (!((Object)(object)player == (Object)null) && ((Agent)player).IsLocallyOwned) { KnockbackSetting knockback = Knockback; if (knockback != null && knockback.Enabled) { Knockback.DoKnockbackIgnoreDistance(projectilePosition, player); } BleedSetting bleed = Bleed; if (bleed != null && bleed.Enabled) { Bleed.DoBleed(player); } DrainStaminaSetting drainStamina = DrainStamina; if (drainStamina != null && drainStamina.Enabled) { DrainStamina.DoDrain(player); } float absValue = Infection.GetAbsValue(PlayerData.MaxInfection, proj.m_maxInfection); if (absValue < 0f) { DoDisinfectEffect(absValue, player); } } } public void DoDestroyEffect(ProjectileBase projectile, ProjectileDestroyedReason reason) { if (projectile.TryGetOwner(out EnemyAgent agent)) { switch (reason) { case ProjectileDestroyedReason.CollideWorld: SpawnProjColWorld?.DoSpawn(agent, projectile.m_targetAgent, ((Component)projectile).transform, keepTrack: false); break; case ProjectileDestroyedReason.CollidePlayer: SpawnProjColPlayer?.DoSpawn(agent, projectile.m_targetAgent, ((Component)projectile).transform, keepTrack: false); break; case ProjectileDestroyedReason.LifeTimeDone: SpawnProjLifeDone?.DoSpawn(agent, projectile.m_targetAgent, ((Component)projectile).transform, keepTrack: false); break; } } } private static void DoDisinfectEffect(float infect, PlayerAgent player) { //IL_0015: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) player.Sound.Post(EVENTS.DISINFECTION_SPRAY_ON_VISOR, true); ScreenLiquidManager.Apply((ScreenLiquidSettingName)10, ((Agent)player).Position, new Vector3(0.5f, 0.5f)); player.Damage.ModifyInfection(new pInfection { amount = infect, effect = (pInfectionEffect)0, mode = (pInfectionMode)1 }, true, true); } } public enum ProjectileDestroyedReason { CollideWorld, CollidePlayer, LifeTimeDone } [CallConstructorOnLoad] public static class CustomProjectileManager { public class ProjectileData { public GameObject Prefab; public CustomProjectile Settings; public void RegisterInstance(GameObject gameObject) { //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) if (!gameObject.TryGetComp(out var projectile)) { return; } int instanceID = ((Object)gameObject).GetInstanceID(); _instanceProjLookup[instanceID] = this; UnityEventHandler unityEventHandler = null; if ((Settings?.SpeedChange?.Enabled).GetValueOrDefault()) { MultiplierShiftSetting speedChange = Settings.SpeedChange; float inv2 = 1f / speedChange.Duration; float progress2 = 0f; float originalSpeed = projectile.Speed; bool enabled2 = true; unityEventHandler = (UnityEventHandler)Delegate.Combine(unityEventHandler, (UnityEventHandler)delegate { if (enabled2) { if (speedChange.StopAfterDuration && progress2 >= speedChange.Duration) { projectile.Speed = originalSpeed * speedChange.StopMulti; enabled2 = false; } else { float num3 = speedChange.EvaluateMultiplier(progress2 * inv2); projectile.Speed = originalSpeed * num3; progress2 += Time.deltaTime; } } }); } if ((Settings?.HomingStrengthChange?.Enabled).GetValueOrDefault()) { MultiplierShiftSetting homingChange = Settings.HomingStrengthChange; float inv = 1f / homingChange.Duration; float progress = 0f; float originalHoming = projectile.TargetStrength; bool enabled = true; unityEventHandler = (UnityEventHandler)Delegate.Combine(unityEventHandler, (UnityEventHandler)delegate { if (enabled) { if (homingChange.StopAfterDuration && progress >= homingChange.Duration) { projectile.Speed = originalHoming * homingChange.StopMulti; enabled = false; } else { float num2 = homingChange.EvaluateMultiplier(progress * inv); projectile.TargetStrength = originalHoming * num2; progress += Time.deltaTime; } } }); } CustomProjectile settings = Settings; if (settings != null && settings.HitEnemies) { Vector3 moveVector = default(Vector3); Ray moveRay = default(Ray); unityEventHandler = (UnityEventHandler)Delegate.Combine(unityEventHandler, (UnityEventHandler)delegate { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00d3: 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) moveVector = ((ProjectileBase)projectile).m_myPos - ((ProjectileBase)projectile).m_lastPos; Vector3 s_tempMove = ProjectileBase.s_tempMove; float num = Mathf.Max(0.5f, ((Vector3)(ref s_tempMove)).magnitude); ((Ray)(ref moveRay)).origin = ((ProjectileBase)projectile).m_lastPos; ((Vector3)(ref moveVector)).Normalize(); ((Ray)(ref moveRay)).direction = moveVector; RaycastHit val = default(RaycastHit); if (Physics.Raycast(moveRay, ref val, num, LayerManager.MASK_ENEMY_DAMAGABLE) && (!projectile.TryGetOwner(out EnemyAgent agent) || !(((Il2CppObjectBase)((Component)((RaycastHit)(ref val)).collider).GetComponent().GetBaseAgent()).Pointer == ((Il2CppObjectBase)agent).Pointer))) { ((ProjectileBase)projectile).Collision(moveRay, val); } }); } MonoBehaviourEventHandler.AttatchToObject(gameObject, unityEventHandler, null, null, delegate { RemoveInstanceLookup(instanceID); }); } } private static readonly Dictionary _projDataLookup; private static readonly Dictionary _instanceProjLookup; public static bool AssetLoaded { get; internal set; } static CustomProjectileManager() { AssetLoaded = false; _projDataLookup = new Dictionary(200); _instanceProjLookup = new Dictionary(200); LevelEvents.LevelCleanup += delegate { _instanceProjLookup.Clear(); }; ProjectileEvents.CollidedWorld += delegate(ProjectileBase proj, GameObject obj) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) ProjectileData instanceData2 = GetInstanceData(((Object)((Component)proj).gameObject).GetInstanceID()); if (instanceData2 != null && instanceData2.Settings != null) { CustomProjectile settings2 = instanceData2.Settings; settings2.DoCollisionEffect(proj, ((Component)proj).transform.position); settings2.DoDestroyEffect(proj, ProjectileDestroyedReason.CollideWorld); } }; ProjectileEvents.CollidedPlayer += delegate(ProjectileBase proj, PlayerAgent agent) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) ProjectileData instanceData = GetInstanceData(((Object)((Component)proj).gameObject).GetInstanceID()); if (instanceData != null && instanceData.Settings != null) { CustomProjectile settings = instanceData.Settings; settings.DoCollisionEffect(proj, ((Component)proj).transform.position, agent); settings.DoDestroyEffect(proj, ProjectileDestroyedReason.CollidePlayer); } }; ProjectileEvents.LifeTimeDone += delegate(ProjectileTargeting proj) { GetInstanceData(((Object)((Component)proj).gameObject).GetInstanceID())?.Settings?.DoDestroyEffect((ProjectileBase)(object)proj, ProjectileDestroyedReason.LifeTimeDone); }; } public static void GenerateProjectile(CustomProjectile projInfo) { //IL_00c0: 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_0116: Expected I4, but got Unknown //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) Logger.Verbose("Trying to Add Projectile... " + projInfo.DebugName); if (!AssetLoaded) { Logger.Error("Cannot Create CustomProjectile before asset fully loaded!"); return; } if (Enum.IsDefined(typeof(ProjectileType), projInfo.ID)) { Logger.Error($"ProjectileID Conflict with Official ID!, ProjID: {projInfo.ID}"); return; } if (_projDataLookup.ContainsKey(projInfo.ID)) { Logger.Error($"ProjectileID Conflict!, ProjID: {projInfo.ID}"); return; } if (!Enum.IsDefined(typeof(ProjectileType), projInfo.BaseProjectile)) { Logger.Error($"BaseProjectile should be one of the from official!, ProjID: {projInfo.ID}"); return; } GameObject val = Object.Instantiate(((Il2CppArrayBase)(object)ProjectileManager.Current.m_projectilePrefabs)[(int)projInfo.BaseProjectile]); Object.DontDestroyOnLoad((Object)(object)val); if (val.TryGetComp(out var component)) { component.m_maxDamage = projInfo.Damage.GetAbsValue(PlayerData.MaxHealth, component.m_maxDamage); component.m_maxInfection = projInfo.Infection.GetAbsValue(PlayerData.MaxInfection, component.m_maxInfection); ProjectileTargeting val2 = ((Il2CppObjectBase)component).TryCast(); if ((Object)(object)val2 != (Object)null) { val2.Speed = projInfo.Speed.GetAbsValue(val2.Speed); val2.m_checkEvasiveDis = projInfo.CheckEvasiveDistance.GetAbsValue(val2.m_checkEvasiveDis); val2.TargetStrength = projInfo.HomingStrength.GetAbsValue(val2.TargetStrength); val2.m_targetingDelay = projInfo.HomingDelay.GetAbsValue(val2.m_targetingDelay); val2.m_initialTargetStrength = projInfo.InitialHomingStrength.GetAbsValue(val2.m_initialTargetStrength); val2.m_initialTargetingDuration = projInfo.InitialHomingDuration.GetAbsValue(val2.m_initialTargetingDuration); val2.LightColor = projInfo.GlowColor; val2.LightRange = projInfo.GlowRange.GetAbsValue(val2.LightRange); } else { Logger.Warning($"ProjectileBase is not a ProjectileTargeting, Ignore few settings, ProjID: {projInfo.ID}, Name: {projInfo.DebugName}"); } } else { Logger.Error($"Projectile Base Prefab Doesn't have ProjectileBase, Are you sure?, ProjID: {projInfo.ID}, Name: {projInfo.DebugName}"); } TrailRenderer componentInChildren = val.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.startColor = projInfo.TrailColor; componentInChildren.endColor = Color.clear; componentInChildren.time = projInfo.TrailTime.GetAbsValue(componentInChildren.time); componentInChildren.widthMultiplier = projInfo.TrailWidth.GetAbsValue(componentInChildren.widthMultiplier); } val.SetActive(false); ((Object)val).name = "GeneratedProjectilePrefab_" + projInfo.ID; _projDataLookup.Add(projInfo.ID, new ProjectileData { Prefab = val, Settings = projInfo }); Logger.Debug($"Added Projectile!: {projInfo.ID} ({projInfo.DebugName})"); } public static void DestroyAllProjectile() { foreach (ProjectileData value in _projDataLookup.Values) { Object.Destroy((Object)(object)value.Prefab); } Logger.Debug("Custom Projectile has Cleaned up!"); _projDataLookup.Clear(); } public static ProjectileData GetProjectileData(byte id) { if (_projDataLookup.TryGetValue(id, out ProjectileData value)) { return value; } return null; } public static ProjectileData GetInstanceData(int id) { if (_instanceProjLookup.TryGetValue(id, out ProjectileData value)) { return value; } return null; } public static void RemoveInstanceLookup(int id) { _instanceProjLookup.Remove(id); } } } namespace EEC.CustomSettings.CustomProjectiles.Inject { [HarmonyPatch(typeof(ProjectileBase), "Collision")] internal static class Inject_ProjectileBase_Collision { [HarmonyWrapSafe] internal static void Postfix(ProjectileBase __instance) { //IL_0096: 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) CustomProjectileManager.ProjectileData instanceData = CustomProjectileManager.GetInstanceData(((Object)((Component)__instance).gameObject).GetInstanceID()); if (instanceData == null) { return; } uint collisionSoundID = instanceData.Settings.CollisionSoundID; if (collisionSoundID == 0) { if (__instance.m_maxInfection > 0f) { List dynamicPlayers = CellSound.Current.m_dynamicPlayers; dynamicPlayers[dynamicPlayers.Count - 1].Recycle(); dynamicPlayers.RemoveAt(dynamicPlayers.Count - 1); } } else if (__instance.m_maxInfection > 0f) { List dynamicPlayers2 = CellSound.Current.m_dynamicPlayers; CellSoundPlayer obj = dynamicPlayers2[dynamicPlayers2.Count - 1]; obj.Stop(); obj.Post(collisionSoundID, __instance.m_myPos); } else { CellSound.Post(collisionSoundID, __instance.m_myPos); } } } [HarmonyPatch(typeof(ProjectileManager))] internal static class Inject_ProjectileManager { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("LoadAssets")] internal static void Post_LoadAsset() { CustomProjectileManager.AssetLoaded = true; CustomProjectile[] projectileDefinitions = ConfigManager.ProjectileCustom.ProjectileDefinitions; for (int i = 0; i < projectileDefinitions.Length; i++) { CustomProjectileManager.GenerateProjectile(projectileDefinitions[i]); } } [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("SpawnProjectileType")] internal static bool Pre_SpawnProjectile(ref GameObject __result, ref ProjectileType type, Vector3 pos, Quaternion rot) { //IL_005b: 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) if (Enum.IsDefined(typeof(ProjectileType), (byte)type)) { return true; } CustomProjectileManager.ProjectileData projectileData = CustomProjectileManager.GetProjectileData((byte)type); if (projectileData == null) { Logger.Error($"CANT FIND PROJECTILE DATA WITH ID: {type}"); type = (ProjectileType)0; return true; } GameObject val = Object.Instantiate(projectileData.Prefab, pos, rot, ProjectileManager.Current.m_root.transform); val.SetActive(true); projectileData.RegisterInstance(val); __result = val; return false; } } [HarmonyPatch(typeof(ProjectileTargeting), "OnFire")] internal static class Inject_ProjectileTargeting_OnFire { [HarmonyWrapSafe] internal static void Postfix(ProjectileTargeting __instance) { CustomProjectileManager.ProjectileData instanceData = CustomProjectileManager.GetInstanceData(((Object)((Component)__instance).gameObject).GetInstanceID()); if (instanceData != null) { float time = Clock.Time; float baseValue = __instance.m_endLifeTime - time; __instance.m_endLifeTime = instanceData.Settings.LifeTime.GetAbsValue(baseValue) + time; } } } } namespace EEC.CustomAbilities.Knockback { [CallConstructorOnLoad] public static class KnockbackManager { internal static KnockbackSync Sync { get; private set; } static KnockbackManager() { Sync = new KnockbackSync(); Sync.Setup(); } public static void DoKnockback(PlayerAgent agent, KnockbackData data) { Sync.SendToPlayer(data, agent); } } public struct KnockbackData { public Vector3 inflictorPos; public float velocity; public float velocityZ; public bool doMultDistance; public bool doMultDistanceZ; } internal sealed class KnockbackSync : SyncedPlayerEvent { public override string GUID => "KNB"; public override bool SendToTargetOnly => true; public override bool AllowBots => false; protected override void Receive(KnockbackData packet, SNet_Player receivedPlayer) { if (TryGetPlayerAgent(receivedPlayer, out PlayerAgent agent)) { DoKnockback(packet, agent); } } private static void DoKnockback(KnockbackData data, PlayerAgent player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Agent)player).Position - data.inflictorPos; float magnitude = ((Vector3)(ref val)).magnitude; Vector3 val2 = val / magnitude * data.velocity; Vector3 val3 = Vector3.up * data.velocityZ; if (data.doMultDistance) { val2 *= magnitude; } if (data.doMultDistanceZ) { val3 *= magnitude; } player.Locomotion.AddExternalPushForce(val2); if (data.velocityZ != 0f && ((Agent)player).Alive) { player.Locomotion.ChangeState((PLOC_State)3, true); player.Locomotion.VerticalVelocity = val2 + val3; } } } } namespace EEC.CustomAbilities.Infection { [CallConstructorOnLoad] public static class InfectionManager { internal static InfectionSync Sync { get; private set; } static InfectionManager() { Sync = new InfectionSync(); Sync.Setup(); } public static void DoInfection(PlayerAgent agent, IInfectionSetting setting) { DoInfection(agent, setting.ToPacket()); } public static void DoInfection(PlayerAgent agent, InfectionData data) { if (data.infection != 0f) { Sync.SendToPlayer(data, agent); } } } public struct InfectionData { public float infection; public uint soundEventID; public bool useEffect; public float screenLiquidRange; } internal sealed class InfectionSync : SyncedPlayerEvent { public override string GUID => "INF"; public override bool SendToTargetOnly => true; public override bool AllowBots => false; protected override void Receive(InfectionData packet, SNet_Player receivedPlayer) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (!TryGetPlayerAgent(receivedPlayer, out PlayerAgent agent)) { return; } if (Logger.VerboseLogAllowed) { Logger.Verbose($"Infection [{agent.PlayerSlotIndex} {packet.infection}]"); } if (packet.soundEventID != 0) { agent.Sound.Post(packet.soundEventID, true); } if (packet.useEffect) { ScreenLiquidSettingName val = (ScreenLiquidSettingName)4; if (packet.infection < 0f) { val = (ScreenLiquidSettingName)10; } ScreenLiquidManager.TryApply(val, ((Agent)agent).Position, packet.screenLiquidRange, true); } agent.Damage.ModifyInfection(new pInfection { amount = packet.infection, effect = (pInfectionEffect)0, mode = (pInfectionMode)1 }, true, true); } } } namespace EEC.CustomAbilities.FogHealth { [CallConstructorOnLoad] public static class FogHealthManager { internal static FogHealthSync Sync { get; private set; } static FogHealthManager() { Sync = new FogHealthSync(); Sync.Setup(); } public static void DoHealthChange(PlayerAgent agent, float amount) { if (amount > 0f) { ((Dam_SyncedDamageBase)agent.Damage).AddHealth(amount, (Agent)null); return; } Sync.SendToPlayer(new FogHealthData { damage = 0f - amount }, agent); } } public struct FogHealthData { public float damage; } internal sealed class FogHealthSync : SyncedPlayerEvent { private const float FLASH_CONVERSION = 6f; public override string GUID => "FGH"; public override bool SendToTargetOnly => false; public override bool AllowBots => false; protected override void Receive(FogHealthData packet, SNet_Player receivedPlayer) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) if (TryGetPlayerAgent(receivedPlayer, out PlayerAgent agent)) { if (Logger.VerboseLogAllowed) { Logger.Verbose($"FogHealth [{agent.PlayerSlotIndex} {packet.damage}]"); } float damage = packet.damage; Dam_PlayerDamageBase damage2 = agent.Damage; if (receivedPlayer.IsLocal) { agent.FPSCamera.AddHitReact(damage / ((Dam_SyncedDamageBase)damage2).HealthMax * 6f, Vector3.up, 0f, true, true); } damage2.OnIncomingDamage(damage, damage, (Agent)null); } } } } namespace EEC.CustomAbilities.Explosion { public static class ExplosionEffectPooling { private static readonly Queue _pool = new Queue(); public static void Initialize() { for (int i = 0; i < 30; i++) { _pool.Enqueue(CreatePoolObject()); } } private static ExplosionEffectHandler CreatePoolObject() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(); Object.DontDestroyOnLoad((Object)val); ExplosionEffectHandler result = val.AddComponent(); val.AddComponent(); val.SetActive(false); return result; } public static void TryDoEffect(ExplosionEffectData data) { if (_pool.TryDequeue(out ExplosionEffectHandler handler)) { handler.EffectDoneOnce = delegate { ((Component)handler).gameObject.SetActive(false); _pool.Enqueue(handler); }; ((Component)handler).gameObject.SetActive(true); handler.DoEffect(data); } } } public struct ExplosionEffectData { public Vector3 position; public Color flashColor; public float intensity; public float range; public float duration; } [CallConstructorOnLoad] public static class ExplosionManager { public static readonly Color FlashColor; private static bool _usingLightFlash; private static int _hostMask; private static int _hostOnlyMask; internal static ExplosionSync Sync { get; private set; } internal static ExplosionAgentSync AgentSync { get; private set; } static ExplosionManager() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) FlashColor = new Color(1f, 0.2f, 0f, 1f); Sync = new ExplosionSync(); AgentSync = new ExplosionAgentSync(); _usingLightFlash = true; _hostMask = 0; _hostOnlyMask = 0; Sync.Setup(); AgentSync.Setup(); AssetEvents.AllAssetLoaded += AssetEvents_AllAssetLoaded; } private static void AssetEvents_AllAssetLoaded() { ExplosionEffectPooling.Initialize(); _usingLightFlash = Configuration.ShowExplosionEffect; _hostOnlyMask = LayerManager.MASK_EXPLOSION_TARGETS; _hostMask = LayerManager.MASK_EXPLOSION_TARGETS & ~LayerMask.GetMask(new string[1] { "PlayerSynced" }); } public static void DoExplosion(ExplosionPosData data) { Sync.Send(data); } public static void DoExplosion(ExplosionAgentData data) { AgentSync.Send(data); } public static void DoLocalExplosion(ExplosionPosData data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Internal_TriggerExplosion(data.position, data.data); } internal static void Internal_TriggerExplosion(Vector3 position, ExplosionData data) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) CellSound.Post(EVENTS.STICKYMINEEXPLODE, position); if (_usingLightFlash) { LightFlash(position, data.maxRange, data.lightColor); } if (SNet.IsMaster) { TriggerHostExplosion(position, data, _hostMask); } else { TriggerClientExplosion(position, data); } } internal static void Internal_TriggerHostOnlyExplosion(Vector3 position, ExplosionData data) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) CellSound.Post(EVENTS.STICKYMINEEXPLODE, position); if (_usingLightFlash) { LightFlash(position, data.maxRange, data.lightColor); } if (SNet.IsMaster) { TriggerHostExplosion(position, data, _hostOnlyMask); } } private static void TriggerClientExplosion(Vector3 position, ExplosionData data) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); if ((Object)(object)localPlayerAgent == (Object)null) { return; } Vector3 eyePosition = ((Agent)localPlayerAgent).EyePosition; float num = Vector3.Distance(position, eyePosition); if (!Physics.Linecast(position, eyePosition, LayerManager.MASK_EXPLOSION_BLOCKERS)) { float num2 = CalcRangeMod(num, data.minRange, data.maxRange); float num3 = data.damage * num2; if (num3 != 0f) { Logger.Verbose($"Explosive damage: {num3} out of max: {data.damage}, Dist: {num}, min: {data.minRange}, max: {data.maxRange}"); DoExplosionHit(num3, num2, data, ((Il2CppObjectBase)localPlayerAgent.Damage).Cast(), position, (Agent?)(object)localPlayerAgent); } } } private static void TriggerHostExplosion(Vector3 position, ExplosionData data, int mask) { //IL_0000: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) Il2CppReferenceArray val = Physics.OverlapSphere(position, Math.Max(data.maxRange, data.enemyMaxRange), mask); if (((Il2CppArrayBase)(object)val).Count < 1) { return; } DamageUtil.IncrementSearchID(); uint searchID = DamageUtil.SearchID; RaycastHit val3 = default(RaycastHit); foreach (Collider item in (Il2CppArrayBase)(object)val) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null || !((Component)item).gameObject.TryGetComp(out var component)) { continue; } component = component.GetBaseDamagable(); if (component == null) { continue; } Agent baseAgent = component.GetBaseAgent(); Vector3 val2 = ((!((Object)(object)baseAgent != (Object)null)) ? ((Component)item).transform.position : baseAgent.EyePosition); if (component.TempSearchID == searchID) { continue; } component.TempSearchID = searchID; float num = Vector3.Distance(position, val2); if (!Physics.Linecast(position, val2, ref val3, LayerManager.MASK_EXPLOSION_BLOCKERS) || (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val3)).collider).gameObject == (Object)null) && ((Object)((Component)((RaycastHit)(ref val3)).collider).gameObject).GetInstanceID() == ((Object)((Component)item).gameObject).GetInstanceID())) { float num2; float num3; if (((baseAgent == null) ? 2 : ((int)baseAgent.Type)) == 1) { num2 = CalcRangeMod(num, data.enemyMinRange, data.enemyMaxRange); num3 = data.damage * data.enemyMulti * num2; } else { num2 = CalcRangeMod(num, data.minRange, data.maxRange); num3 = data.damage * num2; } if (num3 != 0f) { Logger.Verbose($"Explosive damage: {num3} out of max: {data.damage}, Dist: {num}, min: {data.minRange}, max: {data.maxRange}"); DoExplosionHit(num3, num2, data, component, position, baseAgent); } } } } private static void DoExplosionHit(float damage, float rangeMod, ExplosionData data, IDamageable damageable, Vector3 position, Agent? agent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (damage < 0f) { ExplosionHeal(damageable, 0f - damage); } else { damageable.ExplosionDamage(damage, position, Vector3.up * 1000f, 0u); } if (((agent == null) ? 2 : ((int)agent.Type)) == 0) { PlayerAgent agent2 = ((Il2CppObjectBase)agent).Cast(); if (data.bleeding.enabled) { BleedingData packet = data.bleeding.packet; packet.damage *= rangeMod; BleedManager.DoBleed(agent2, packet); } if (data.drainStamina.enabled) { DrainStaminaData packet2 = data.drainStamina.packet; packet2.amount *= rangeMod; packet2.amountInCombat *= rangeMod; DrainStaminaManager.DoDrain(agent2, packet2); } if (data.knockback.enabled) { KnockbackData packet3 = data.knockback.packet; packet3.velocity *= rangeMod; packet3.velocityZ *= rangeMod; KnockbackManager.DoKnockback(agent2, packet3); } if (data.infection.enabled) { InfectionData packet4 = data.infection.packet; packet4.infection *= rangeMod; InfectionManager.DoInfection(agent2, packet4); } } } private static void ExplosionHeal(IDamageable damageable, float heal) { Dam_SyncedDamageBase obj = ((Il2CppObjectBase)damageable).Cast(); obj.SendSetHealth(obj.Health + heal); } private static float CalcRangeMod(float distance, float minRange, float maxRange) { float result = 0f; if (distance <= minRange) { result = 1f; } else if (distance <= maxRange) { result = 1f - (distance - minRange) / (maxRange - minRange); } return result; } public static void LightFlash(Vector3 pos, float range, Color lightColor) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) ExplosionEffectData data = default(ExplosionEffectData); data.position = pos; data.flashColor = lightColor; data.intensity = 5f; data.range = range; data.duration = 0.05f; ExplosionEffectPooling.TryDoEffect(data); if (PlayerManager.HasLocalPlayerAgent()) { Vector3 val = ((Agent)PlayerManager.GetLocalPlayerAgent()).Position - pos; float magnitude = ((Vector3)(ref val)).magnitude; float num = 6f * Mathf.Max(0f, Mathf.InverseLerp(range, 0f, magnitude)); if (num > 0.01f) { PlayerManager.GetLocalPlayerAgent().FPSCamera.Shake(1.5f, num, 0.09f); } } } } public struct ExplosionPosData { public Vector3 position; public ExplosionData data; } public struct ExplosionAgentData { public pAgent agent; public bool useRagdoll; public ExplosionData data; } public struct ExplosionData { public float damage; public float enemyMulti; public float minRange; public float maxRange; public float enemyMinRange; public float enemyMaxRange; public Color lightColor; public ExpBleedingData bleeding; public ExpDrainStaminaData drainStamina; public ExpKnockbackData knockback; public ExpInfectionData infection; } public struct ExpBleedingData { public bool enabled; public BleedingData packet; } public struct ExpDrainStaminaData { public bool enabled; public DrainStaminaData packet; } public struct ExpKnockbackData { public bool enabled; public KnockbackData packet; } public struct ExpInfectionData { public bool enabled; public InfectionData packet; } internal sealed class ExplosionSync : SyncedEvent { public override string GUID => "EXP"; protected override void Receive(ExplosionPosData packet) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) ExplosionData data = packet.data; Logger.Verbose($"Explosion Received: [{packet.position}] {data.damage} {data.enemyMulti} {data.minRange} {data.maxRange}"); ExplosionManager.Internal_TriggerHostOnlyExplosion(packet.position, data); } } internal sealed class ExplosionAgentSync : SyncedEvent { public override string GUID => "EXPA"; protected override void Receive(ExplosionAgentData packet) { //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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) Agent val = default(Agent); if (((pAgent)(ref packet.agent)).TryGet(ref val)) { Vector3 position = val.EyePosition; if (packet.useRagdoll) { val.GetRagdollPosition(ref position); } ExplosionData data = packet.data; data.knockback.packet.inflictorPos = position; ExplosionManager.Internal_TriggerExplosion(position, data); } } } } namespace EEC.CustomAbilities.Explosion.Handlers { [InjectToIl2Cpp] internal sealed class ExplosionEffectHandler : MonoBehaviour { public Action EffectDoneOnce; private EffectLight _light; private Timer _timer; private bool _effectOnGoing; internal void DoEffect(ExplosionEffectData data) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.position = data.position; if ((Object)(object)_light == (Object)null) { _light = ((Component)this).gameObject.GetComponent(); ((LightBase)_light).Setup(); } ((LightBase)_light).UpdateVisibility(true); ((LightBase)_light).Color = data.flashColor; ((LightBase)_light).Range = data.range; ((LightBase)_light).Intensity = data.intensity; _timer.Reset(data.duration); _effectOnGoing = true; } private void FixedUpdate() { if (_effectOnGoing && _timer.TickAndCheckDone()) { OnDone(); } } private void OnDone() { if ((Object)(object)_light != (Object)null) { ((LightBase)_light).UpdateVisibility(false); } EffectDoneOnce?.Invoke(); EffectDoneOnce = null; _light = null; _effectOnGoing = false; } } } namespace EEC.CustomAbilities.EMP { [InjectToIl2Cpp] public sealed class EMPController : MonoBehaviour { private IEMPHandler _handler; private bool _hasHandler; private float _duration; private bool _setup; [HideFromIl2Cpp] private bool IsEMPActive => _duration > Clock.Time; [HideFromIl2Cpp] public Vector3 Position => ((Component)this).transform.position; private void Awake() { EMPManager.AddTarget(this); } private void OnEnable() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) if ((int)GameStateManager.CurrentStateName == 10 && _setup) { _duration = Clock.Time + EMPManager.DurationFromPosition(((Component)this).transform.position); if (_duration > Clock.Time) { _handler.ForceState(EMPState.Off); } else { _handler.ForceState(EMPState.On); } } } private void Update() { if (_hasHandler) { _handler.Tick(IsEMPActive); } } [HideFromIl2Cpp] public void AddTime(float time) { _duration = Clock.Time + time; } [HideFromIl2Cpp] public void ClearTime() { _duration = Clock.Time - 1f; } [HideFromIl2Cpp] public void AssignHandler(IEMPHandler handler) { if (_handler != null) { Logger.Warning("Tried to assign a handler to a controller that already had one!"); return; } _handler = handler; _handler.Setup(((Component)this).gameObject, this); _hasHandler = true; _setup = true; } [HideFromIl2Cpp] public void ForceState(EMPState state) { if (_handler != null) { _handler.ForceState(state); } } private void OnDestroy() { EMPManager.RemoveTarget(this); _handler.OnDespawn(); _handler = null; } } public abstract class EMPHandlerBase : IEMPHandler { protected enum DeviceState { On, Off, Unknown } protected DeviceState _deviceState; protected EMPState _state; protected float _stateTimer; private static bool _isLocalPlayerDisabled; private float _delayTimer; private bool _destroyed; public static bool IsLocalPlayerDisabled { get { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 if (_isLocalPlayerDisabled) { return (int)GameStateManager.CurrentStateName == 10; } return false; } } protected virtual float FlickerDuration => 0.2f; protected virtual float MinDelay => 0f; protected virtual float MaxDelay => 1.5f; protected virtual bool IsDeviceOnPlayer => false; public abstract void Setup(GameObject gameObject, EMPController controller); public static void Cleanup() { _isLocalPlayerDisabled = false; } public void ForceState(EMPState state) { if (_state != state) { _state = state; Logger.Debug("Force State -> {0}", state); _delayTimer = Clock.Time - 1f; _stateTimer = Clock.Time - 1f; switch (state) { case EMPState.On: _deviceState = DeviceState.On; DeviceOn(); break; case EMPState.Off: _deviceState = DeviceState.Off; DeviceOff(); break; default: _deviceState = DeviceState.Unknown; break; } } } public void Tick(bool isEMPD) { if (_destroyed) { return; } if (isEMPD && _state == EMPState.On && _deviceState == DeviceState.On) { OnEMPStart(); float randomDelay = GetRandomDelay(MinDelay, MaxDelay); _state = EMPState.FlickerOff; _delayTimer = Clock.Time + randomDelay; _stateTimer = Clock.Time + FlickerDuration + randomDelay; } if (!isEMPD && _state == EMPState.Off) { float randomDelay2 = GetRandomDelay(0f, 1.5f); _state = EMPState.FlickerOn; _delayTimer = Clock.Time + randomDelay2; _stateTimer = Clock.Time + FlickerDuration + randomDelay2; } switch (_state) { case EMPState.On: if (_deviceState != 0) { DeviceOn(); _deviceState = DeviceState.On; if (IsDeviceOnPlayer) { _isLocalPlayerDisabled = false; } } break; case EMPState.FlickerOff: if (!(_delayTimer > Clock.Time)) { if (Clock.Time < _stateTimer) { FlickerDevice(); } else { _state = EMPState.Off; } } break; case EMPState.Off: if (_deviceState != DeviceState.Off) { DeviceOff(); _deviceState = DeviceState.Off; if (IsDeviceOnPlayer) { _isLocalPlayerDisabled = true; } } break; case EMPState.FlickerOn: if (!(_delayTimer > Clock.Time)) { if (Clock.Time < _stateTimer) { FlickerDevice(); } else { _state = EMPState.On; } } break; } } public void OnDespawn() { _destroyed = true; } protected abstract void FlickerDevice(); protected abstract void DeviceOn(); protected abstract void DeviceOff(); protected virtual void OnEMPStart() { } protected static float GetRandomDelay(float min, float max) { return Rand.Range(min, max); } protected static float GetRandom01() { return Rand.NextFloatInclusive(); } protected static int GetRandomRange(int min, int maxPlusOne) { return Rand.Range(min, maxPlusOne); } protected static bool FlickerUtil(int oneInX = 2) { return Rand.Index(oneInX) == 0; } } [CallConstructorOnLoad] public static class EMPManager { private struct ActiveEMPs { private readonly Vector3 _position; private readonly float _range; private readonly float _duration; public float RemainingTime => _duration - Clock.Time; public ActiveEMPs(Vector3 position, float range, float duration) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) this = default(ActiveEMPs); _position = position; _range = range; _duration = Clock.Time + duration; } public bool InRange(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(position, _position) < _range; } } private static readonly List _empTargets; private static readonly List _activeEMPs; static EMPManager() { _empTargets = new List(); _activeEMPs = new List(); LevelEvents.LevelCleanup += delegate { _empTargets.Clear(); EMPHandlerBase.Cleanup(); }; SNetEvents.PrepareRecall += delegate { foreach (EMPController empTarget in _empTargets) { empTarget.ClearTime(); empTarget.ForceState(EMPState.On); } EMPHandlerBase.Cleanup(); }; LevelEvents.BuildDone += delegate { Inject_PlayerBackpack.Setup(); }; } public static void AddTarget(EMPController target) { _empTargets.Add(target); } public static void RemoveTarget(EMPController target) { _empTargets.Remove(target); } public static void Activate(Vector3 position, float range, float duration) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!GameStateManager.IsInExpedition) { Logger.Error("Tried to activate an EMP when not in level, this shouldn't happen!"); return; } _activeEMPs.Add(new ActiveEMPs(position, range, duration)); foreach (EMPController empTarget in _empTargets) { if (Vector3.Distance(position, empTarget.Position) < range) { empTarget.AddTime(duration); } } } public static float DurationFromPosition(Vector3 position) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) _activeEMPs.RemoveAll((ActiveEMPs e) => Mathf.Round(e.RemainingTime) <= 0f); float num = 0f; foreach (ActiveEMPs activeEMP in _activeEMPs) { if (activeEMP.InRange(position)) { num += activeEMP.RemainingTime; } } return num; } } public enum EMPState { On, FlickerOff, Off, FlickerOn } public interface IEMPHandler { void Tick(bool enabled); void Setup(GameObject gameObject, EMPController controller); void ForceState(EMPState state); void OnDespawn(); } } namespace EEC.CustomAbilities.EMP.Inject { [HarmonyPatch(typeof(EnemyScanner))] internal static class Inject_EnemyScanner { [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("UpdateDetectedEnemies")] internal static bool Pre_UpdateDetectedEnemies() { return !EMPHandlerBase.IsLocalPlayerDisabled; } [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("UpdateTagProgress")] internal static bool Pre_UpdateTagProgress(EnemyScanner __instance) { if (EMPHandlerBase.IsLocalPlayerDisabled) { ((ItemEquippable)__instance).Sound.Post(EVENTS.BIOTRACKER_TOOL_LOOP_STOP, true); __instance.m_screen.SetStatusText("ERROR"); return false; } __instance.m_screen.SetStatusText("Ready to tag"); return true; } } [HarmonyPatch(typeof(LG_Light))] internal static class Inject_LG_Light { [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("Start")] internal static void Pre_Start(LG_Light __instance) { ((Component)__instance).gameObject.AddComponent().AssignHandler(new EMPLightHandler()); } } [HarmonyPatch(typeof(PlayerAgent))] internal static class Inject_PlayerAgent { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("Setup")] internal static void Post_Setup(PlayerAgent __instance) { if (((Agent)__instance).IsLocallyOwned) { ((Component)__instance).gameObject.AddComponent().AssignHandler(new EMPPlayerFlashLightHandler()); ((Component)__instance).gameObject.AddComponent().AssignHandler(new EMPPlayerHudHandler()); } } } internal class Inject_PlayerBackpack { public static void Setup() { Enumerator enumerator = PlayerBackpackManager.Current.m_backpacks.Values.GetEnumerator(); while (enumerator.MoveNext()) { PlayerBackpack current = enumerator.Current; AddHandlerForSlot(current, (InventorySlot)1, new EMPGunSightHandler()); AddHandlerForSlot(current, (InventorySlot)2, new EMPGunSightHandler()); AddToolHandler(current); } } private static void AddToolHandler(PlayerBackpack backpack) { BackpackItem val = default(BackpackItem); if (backpack.TryGetBackpackItem((InventorySlot)3, ref val)) { if ((Object)(object)((Component)val.Instance).gameObject.GetComponent() != (Object)null) { Logger.Debug("Item already has controller, skipping..."); } if ((Object)(object)((Component)val.Instance).GetComponent() != (Object)null) { ((Component)val.Instance).gameObject.AddComponent().AssignHandler(new EMPBioTrackerHandler()); } } else { Logger.Warning("Couldn't get item for slot {0}!", (object)(InventorySlot)3); } } private static void AddHandlerForSlot(PlayerBackpack backpack, InventorySlot slot, IEMPHandler handler) { //IL_0001: 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) BackpackItem val = default(BackpackItem); if (backpack.TryGetBackpackItem(slot, ref val)) { if ((Object)(object)((Component)val.Instance).gameObject.GetComponent() != (Object)null) { Logger.Debug("Item already has controller, skipping..."); } ((Component)val.Instance).gameObject.AddComponent().AssignHandler(handler); } else { Logger.Warning("Couldn't get item for slot {0}!", slot); } } } [HarmonyPatch(typeof(PlayerGuiLayer))] internal static class Inject_PlayerGuiLayer { [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("UpdateGUIElementsVisibility")] internal static bool Pre_UpdateGUIElementsVisibility() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 if (EMPHandlerBase.IsLocalPlayerDisabled) { EMPPlayerHudHandler.Instance.ForceState(EMPState.Off); return false; } if ((int)GameStateManager.CurrentStateName == 10) { EMPPlayerHudHandler.Instance.ForceState(EMPState.On); } return true; } } [HarmonyPatch(typeof(PlayerSync))] internal static class Inject_PlayerSync { [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("WantsToSetFlashlightEnabled")] internal static bool Pre_WantsToSetFlashlightEnabled(PlayerSync __instance, bool enable) { if (EMPHandlerBase.IsLocalPlayerDisabled) { return false; } if (enable == __instance.m_agent.Inventory.FlashlightEnabled) { __instance.WantsToSetFlashlightEnabled(!__instance.m_agent.Inventory.FlashlightEnabled, false); return false; } return true; } } [HarmonyPatch(typeof(SentryGunFirstPerson))] internal static class Inject_SentryGunFirstPerson { [HarmonyPrefix] [HarmonyWrapSafe] [HarmonyPatch("CheckCanPlace")] internal static bool Pre_CheckCanPlace(ref bool __result) { if (EMPHandlerBase.IsLocalPlayerDisabled) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(SentryGunInstance))] internal static class Inject_SentryGunInstance { [HarmonyPostfix] [HarmonyWrapSafe] [HarmonyPatch("Setup")] internal static void Post_Setup(SentryGunInstance __instance) { ((Component)__instance).gameObject.AddComponent().AssignHandler(new EMPSentryHandler()); } } } namespace EEC.CustomAbilities.EMP.Handlers { public class EMPBioTrackerHandler : EMPHandlerBase { private EnemyScanner _scanner; public override void Setup(GameObject gameObject, EMPController controller) { if (!gameObject.TryGetComp(out _scanner)) { Logger.Error("Couldn't get bio-tracker component!"); } } protected override void DeviceOff() { ((ItemEquippable)_scanner).Sound.Post(EVENTS.BIOTRACKER_TOOL_LOOP_STOP, true); _scanner.m_graphics.m_display.enabled = false; } protected override void DeviceOn() { _scanner.m_graphics.m_display.enabled = true; } protected override void FlickerDevice() { ((Behaviour)_scanner).enabled = EMPHandlerBase.FlickerUtil(); } } public class EMPGunSightHandler : EMPHandlerBase { public GameObject[] _sightPictures; public override void Setup(GameObject gameObject, EMPController controller) { Il2CppArrayBase componentsInChildren = gameObject.GetComponentsInChildren(true); if (componentsInChildren != null) { _sightPictures = (from x in (IEnumerable)componentsInChildren where (Object)(object)x.sharedMaterial != (Object)null && (Object)(object)x.sharedMaterial.shader != (Object)null where ((Object)x.sharedMaterial.shader).name.InvariantContains("HolographicSight") select ((Component)x).gameObject).ToArray(); } if (_sightPictures == null || _sightPictures.Length < 1) { Logger.Warning("Unable to find sight on {0}!", ((Object)gameObject).name); } } protected override void DeviceOff() { ForEachSights(delegate(GameObject x) { x.SetActive(false); }); } protected override void DeviceOn() { ForEachSights(delegate(GameObject x) { x.SetActive(true); }); } protected override void FlickerDevice() { ForEachSights(delegate(GameObject x) { x.SetActive(EMPHandlerBase.FlickerUtil()); }); } private void ForEachSights(Action action) { if (_sightPictures == null) { return; } GameObject[] sightPictures = _sightPictures; foreach (GameObject val in sightPictures) { if (!((Object)(object)val == (Object)null)) { action?.Invoke(val); } } } } public class EMPLightHandler : EMPHandlerBase { private LG_Light _light; private float _originalIntensity; private Color _originalColor; public override void Setup(GameObject gameObject, EMPController controller) { if (!gameObject.TryGetComp(out _light)) { Logger.Warning("No Light!"); } else { _state = EMPState.On; } } protected override void FlickerDevice() { if ((Object)(object)_light != (Object)null) { _light.ChangeIntensity(EMPHandlerBase.GetRandom01() * _originalIntensity); } } protected override void DeviceOn() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_light != (Object)null) { _light.ChangeIntensity(_originalIntensity); _light.ChangeColor(_originalColor); } } protected override void DeviceOff() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_light != (Object)null) { _light.ChangeIntensity(0f); _light.ChangeColor(Color.black); } } protected override void OnEMPStart() { //IL_0026: 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) if ((Object)(object)_light != (Object)null) { _originalIntensity = _light.GetIntensity(); _originalColor = _light.m_color; } } } public class EMPPlayerFlashLightHandler : EMPHandlerBase { private PlayerInventoryBase _inventory; private float _originalIntensity; private bool _originalFlashlightState; protected override bool IsDeviceOnPlayer => true; private bool FlashlightEnabled => _inventory.FlashlightEnabled; public override void Setup(GameObject gameObject, EMPController controller) { _inventory = gameObject.GetComponent().Inventory; if ((Object)(object)_inventory == (Object)null) { Logger.Warning("Player inventory was null!"); return; } _state = EMPState.On; InventoryEvents.ItemWielded += InventoryEvents_ItemWielded; } private void InventoryEvents_ItemWielded(GearPartFlashlight flashlight) { FlashlightSettingsDataBlock block = GameDataBlockBase.GetBlock(flashlight.m_settingsID); _originalIntensity = block.intensity; } protected override void DeviceOff() { _originalFlashlightState = FlashlightEnabled; if (_originalFlashlightState) { _inventory.Owner.Sync.WantsToSetFlashlightEnabled(false, false); } } protected override void DeviceOn() { if (_originalFlashlightState != FlashlightEnabled) { _inventory.Owner.Sync.WantsToSetFlashlightEnabled(_originalFlashlightState, false); } _inventory.m_flashlight.intensity = _originalIntensity; } protected override void FlickerDevice() { if (FlashlightEnabled) { _inventory.m_flashlight.intensity = EMPHandlerBase.GetRandom01() * _originalIntensity; } } } public class EMPPlayerHudHandler : EMPHandlerBase { private readonly List _targets = new List(); private static EMPPlayerHudHandler _instance; public static EMPPlayerHudHandler Instance => _instance; public override void Setup(GameObject gameObject, EMPController controller) { if (_instance == null) { _targets.Add((RectTransformComp)(object)GuiManager.PlayerLayer.m_compass); _targets.Add((RectTransformComp)(object)GuiManager.PlayerLayer.m_wardenObjective); _targets.Add((RectTransformComp)(object)GuiManager.PlayerLayer.Inventory); _targets.Add((RectTransformComp)(object)GuiManager.PlayerLayer.m_playerStatus); _instance = this; } } protected override void DeviceOff() { foreach (RectTransformComp target in _targets) { ((Component)target).gameObject.SetActive(false); } ((GuiLayer)GuiManager.NavMarkerLayer).SetVisible(false); Logger.Debug("Player HUD off"); } protected override void DeviceOn() { foreach (RectTransformComp target in _targets) { ((Component)target).gameObject.SetActive(true); } ((GuiLayer)GuiManager.NavMarkerLayer).SetVisible(true); Logger.Debug("Player HUD on"); } protected override void FlickerDevice() { foreach (RectTransformComp target in _targets) { target.SetVisible(EMPHandlerBase.FlickerUtil()); } ((GuiLayer)GuiManager.NavMarkerLayer).SetVisible(EMPHandlerBase.FlickerUtil()); } } public class EMPSentryHandler : EMPHandlerBase { private static Color _offColor = new Color { r = 0f, g = 0f, b = 0f, a = 0f }; private SentryGunInstance _sentry; private SentryGunInstance_ScannerVisuals_Plane _visuals; public override void Setup(GameObject gameObject, EMPController controller) { _sentry = gameObject.GetComponent(); _visuals = gameObject.GetComponent(); if ((Object)(object)_sentry == (Object)null || (Object)(object)_visuals == (Object)null) { Logger.Error("Missing components on Sentry! Has Sentry?: {0}, Has Visuals?: {1}", (Object)(object)_sentry == (Object)null, (Object)(object)_visuals == (Object)null); } } protected override void DeviceOff() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) _visuals.m_scannerPlane.SetColor(_offColor); _visuals.UpdateLightProps(_offColor, false); _sentry.m_isSetup = false; _sentry.m_isScanning = false; _sentry.m_isFiring = false; ((ItemEquippable)_sentry).Sound.Post(EVENTS.SENTRYGUN_STOP_ALL_LOOPS, true); } protected override void DeviceOn() { _sentry.m_isSetup = true; _sentry.m_visuals.SetVisualStatus((eSentryGunStatus)0, true); _sentry.m_isScanning = false; _sentry.m_startScanTimer = Clock.Time + _sentry.m_initialScanDelay; ((ItemEquippable)_sentry).Sound.Post(EVENTS.SENTRYGUN_LOW_AMMO_WARNING, true); } protected override void FlickerDevice() { int randomRange = EMPHandlerBase.GetRandomRange(0, 3); _sentry.StopFiring(); switch (randomRange) { case 0: _visuals.SetVisualStatus((eSentryGunStatus)4, true); break; case 1: _visuals.SetVisualStatus((eSentryGunStatus)1, true); break; case 2: _visuals.SetVisualStatus((eSentryGunStatus)2, true); break; } } } } namespace EEC.CustomAbilities.DrainStamina { [CallConstructorOnLoad] public static class DrainStaminaManager { internal static DrainStaminaSync Sync { get; private set; } static DrainStaminaManager() { Sync = new DrainStaminaSync(); Sync.Setup(); } public static void DoDrain(PlayerAgent agent, DrainStaminaData data) { Sync.SendToPlayer(data, agent); } } public struct DrainStaminaData { public float amount; public float amountInCombat; public bool resetRecover; public bool resetRecoverInCombat; } internal sealed class DrainStaminaSync : SyncedPlayerEvent { public override string GUID => "DRS"; public override bool SendToTargetOnly => true; public override bool AllowBots => false; protected override void Receive(DrainStaminaData packet, SNet_Player receivedPlayer) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (TryGetPlayerAgent(receivedPlayer, out PlayerAgent agent)) { if (Logger.VerboseLogAllowed) { Logger.Verbose($"DrainStamina [{agent.PlayerSlotIndex} {packet.amount} {packet.amountInCombat}]"); } ActionCost val = default(ActionCost); val.baseStaminaCostOutOfCombat = packet.amount; val.baseStaminaCostInCombat = packet.amountInCombat; val.resetRestingTimerOutOfCombat = packet.resetRecover; val.resetRestingTimerInCombat = packet.resetRecoverInCombat; ActionCost val2 = val; if (val2.baseStaminaCostInCombat < 0f && val2.baseStaminaCostOutOfCombat < 0f) { AddStamina(agent, val2); } else { agent.Stamina.UseStamina(val2, 1f); } } } private static void AddStamina(PlayerAgent agent, ActionCost cost) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) int num; float num2; bool flag; if (agent.PlayerData.StaminaUsageAffectedByDrama) { num = (((int)DramaManager.CurrentStateEnum != 6) ? 1 : 0); if (num != 0) { num2 = 0f - cost.baseStaminaCostOutOfCombat; flag = cost.resetRestingTimerOutOfCombat; goto IL_003e; } } else { num = 0; } num2 = 0f - cost.baseStaminaCostInCombat; flag = cost.resetRestingTimerInCombat; goto IL_003e; IL_003e: PlayerStamina stamina = agent.Stamina; float num3 = Math.Min(stamina.Stamina + num2, 1f); if (num != 0 && num3 < agent.PlayerData.StaminaMaximumCapWhenInCombat) { num3 = agent.PlayerData.StaminaMaximumCapWhenInCombat; } stamina.Stamina = Math.Max(stamina.Stamina, num3); if (flag) { stamina.m_lastExertion = Clock.Time; } } } } namespace EEC.CustomAbilities.Bleed { [CallConstructorOnLoad] public static class BleedManager { internal static BleedSync Sync { get; private set; } static BleedManager() { Sync = new BleedSync(); Sync.Setup(); } public static void DoBleed(PlayerAgent agent, BleedingData data) { if (!ConfigManager.Global.CanDownStopBleeding || data.duration < 0f || ((Agent)agent).Alive) { Sync.SendToPlayer(data, agent); } } public static void StopBleed(PlayerAgent agent) { DoBleed(agent, new BleedingData { interval = 0f, duration = -1f, damage = 0f }); } } public struct BleedingData { public float interval; public float duration; public float damage; public float chanceToBleed; public bool doStack; public ScreenLiquidSettingName liquid; public uint textSpecialOverride; } internal sealed class BleedSync : SyncedPlayerEvent { public override string GUID => "BLD"; public override bool SendToTargetOnly => true; public override bool AllowBots => false; protected override void Receive(BleedingData packet, SNet_Player receivedPlayer) { if (!TryGetPlayerAgent(receivedPlayer, out PlayerAgent agent)) { return; } if (Logger.VerboseLogAllowed) { Logger.Verbose($"Bleed Received: [{agent.PlayerSlotIndex}] {packet.damage} {packet.interval} {packet.duration}"); } if (packet.duration >= 0f && (!ConfigManager.Global.CanDownStopBleeding || ((Agent)agent).Alive)) { if (Rand.CanDoBy(packet.chanceToBleed)) { GetHandler(agent).DoBleed(packet); } } else { GetHandler(agent).StopBleed(); } } private static BleedHandler GetHandler(PlayerAgent agent) { BleedHandler bleedHandler = ((Component)agent).gameObject.AddOrGetComponent(); bleedHandler.Agent = agent; return bleedHandler; } } } namespace EEC.CustomAbilities.Bleed.Inject { [HarmonyPatch(typeof(PUI_LocalPlayerStatus), "UpdateHealth")] internal static class Inject_PUI_LocalPlayerStatus { public static bool IsBleeding = false; private static bool _hasOverrideText = false; private static string _overrideText = string.Empty; public static uint SpecialOverrideTextID { set { if (value == 0) { _hasOverrideText = false; _overrideText = string.Empty; return; } string text = Text.Get(value); if (!string.IsNullOrEmpty(text)) { _hasOverrideText = true; _overrideText = text; } else { _hasOverrideText = false; _overrideText = string.Empty; } } } internal static void Postfix(PUI_LocalPlayerStatus __instance) { if (IsBleeding) { if (_hasOverrideText) { ((TMP_Text)__instance.m_healthText).text = string.Format(_overrideText, ((TMP_Text)__instance.m_healthText).text); } else { ((TMP_Text)__instance.m_healthText).text = ((TMP_Text)__instance.m_healthText).text + "\nBLEEDING"; } } } } } namespace EEC.CustomAbilities.Bleed.Handlers { [InjectToIl2Cpp] internal sealed class BleedHandler : MonoBehaviour { [CompilerGenerated] private sealed class d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BleedHandler <>4__this; public BleedingData bleedData; private bool 5__2; private WaitForSeconds 5__3; private float 5__4; private ScreenLiquidSettingName 5__5; private bool 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; BleedHandler bleedHandler = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; bleedHandler._globalBleedRunning = true; 5__2 = false; if (bleedHandler._specialOverrideText == 0) { bleedHandler._specialOverrideText = bleedData.textSpecialOverride; Inject_PUI_LocalPlayerStatus.SpecialOverrideTextID = bleedData.textSpecialOverride; 5__2 = true; } 5__3 = WaitFor.Seconds[bleedData.interval]; 5__4 = 0f; 5__5 = bleedData.liquid; 5__6 = Enum.IsDefined(typeof(ScreenLiquidSettingName), 5__5); break; case 1: <>1__state = -1; break; } if (5__4 < bleedData.duration) { if (5__6) { ScreenLiquidManager.DirectApply(5__5, new Vector2(Rand.Range(0.3f, 0.7f), Rand.Range(0.3f, 0.7f)), Vector2.down); } if (((Agent)bleedHandler.Agent).Alive) { if (bleedData.damage >= 0f) { ((Dam_SyncedDamageBase)bleedHandler.Agent.Damage).FireDamage(bleedData.damage, (Agent)(object)bleedHandler.Agent); } else { ((Dam_SyncedDamageBase)bleedHandler.Agent.Damage).AddHealth(bleedData.damage, (Agent)(object)bleedHandler.Agent); } } 5__4 += bleedData.interval; <>2__current = 5__3; <>1__state = 1; return true; } bleedHandler._globalBleedRunning = false; bleedHandler._globalBleedRoutine = null; if (5__2) { bleedHandler._specialOverrideText = 0u; Inject_PUI_LocalPlayerStatus.SpecialOverrideTextID = 0u; } Inject_PUI_LocalPlayerStatus.IsBleeding = bleedHandler._globalBleedRunning || bleedHandler._bleedRoutineCounter > 0; GuiManager.PlayerLayer.UpdateHealth(((Dam_SyncedDamageBase)bleedHandler.Agent.Damage).GetHealthRel(), bleedHandler.Agent.MeleeBuffTimer > Clock.Time); 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(); } } [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BleedHandler <>4__this; public BleedingData bleedData; private bool 5__2; private WaitForSeconds 5__3; private float 5__4; private ScreenLiquidSettingName 5__5; private bool 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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) int num = <>1__state; BleedHandler bleedHandler = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; bleedHandler._bleedRoutineCounter++; 5__2 = false; if (bleedHandler._specialOverrideText == 0) { bleedHandler._specialOverrideText = bleedData.textSpecialOverride; Inject_PUI_LocalPlayerStatus.SpecialOverrideTextID = bleedData.textSpecialOverride; 5__2 = true; } 5__3 = WaitFor.Seconds[bleedData.interval]; 5__4 = 0f; 5__5 = bleedData.liquid; 5__6 = Enum.IsDefined(typeof(ScreenLiquidSettingName), 5__5); break; case 1: <>1__state = -1; break; } if (5__4 < bleedData.duration) { if (5__6) { ScreenLiquidManager.DirectApply(5__5, new Vector2(Rand.Range(0.3f, 0.7f), Rand.Range(0.3f, 0.7f)), Vector2.down); } if (((Agent)bleedHandler.Agent).Alive) { if (bleedData.damage >= 0f) { ((Dam_SyncedDamageBase)bleedHandler.Agent.Damage).FireDamage(bleedData.damage, (Agent)(object)bleedHandler.Agent); } else { ((Dam_SyncedDamageBase)bleedHandler.Agent.Damage).AddHealth(0f - bleedData.damage, (Agent)(object)bleedHandler.Agent); } } 5__4 += bleedData.interval; <>2__current = 5__3; <>1__state = 1; return true; } bleedHandler._bleedRoutineCounter--; if (5__2) { bleedHandler._specialOverrideText = 0u; Inject_PUI_LocalPlayerStatus.SpecialOverrideTextID = 0u; } Inject_PUI_LocalPlayerStatus.IsBleeding = bleedHandler._globalBleedRunning || bleedHandler._bleedRoutineCounter > 0; GuiManager.PlayerLayer.UpdateHealth(((Dam_SyncedDamageBase)bleedHandler.Agent.Damage).GetHealthRel(), bleedHandler.Agent.MeleeBuffTimer > Clock.Time); 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 PlayerAgent Agent; private bool _globalBleedRunning; private Coroutine _globalBleedRoutine; private int _bleedRoutineCounter; private uint _specialOverrideText; [HideFromIl2Cpp] public void DoBleed(BleedingData bleedData) { if (!((Agent)Agent).Alive) { return; } Inject_PUI_LocalPlayerStatus.IsBleeding = true; if (bleedData.doStack) { ((MonoBehaviour)(object)this).StartCoroutine(DoStackableBleed(bleedData)); return; } if (_globalBleedRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_globalBleedRoutine); } _globalBleedRoutine = ((MonoBehaviour)(object)this).StartCoroutine(DoGlobalBleed(bleedData)); } [IteratorStateMachine(typeof(d__6))] [HideFromIl2Cpp] private IEnumerator DoGlobalBleed(BleedingData bleedData) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0) { <>4__this = this, bleedData = bleedData }; } [IteratorStateMachine(typeof(d__7))] [HideFromIl2Cpp] private IEnumerator DoStackableBleed(BleedingData bleedData) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { <>4__this = this, bleedData = bleedData }; } [HideFromIl2Cpp] public void StopBleed() { ((MonoBehaviour)this).StopAllCoroutines(); _bleedRoutineCounter = 0; _globalBleedRunning = false; _globalBleedRoutine = null; Inject_PUI_LocalPlayerStatus.IsBleeding = false; Inject_PUI_LocalPlayerStatus.SpecialOverrideTextID = 0u; GuiManager.PlayerLayer.UpdateHealth(((Dam_SyncedDamageBase)Agent.Damage).GetHealthRel(), Agent.MeleeBuffTimer > Clock.Time); } private void OnDestroy() { StopBleed(); Agent = null; } } } namespace EEC.Configs { public sealed class CategoryConfig : Config { private readonly Dictionary _categoryCache = new Dictionary(); public string[] Categories { get; set; } = Array.Empty(); public IdWithCategories[] CategoryPair { get; set; } = Array.Empty(); public CategoryWithIds[] IdPair { get; set; } = Array.Empty(); public override string FileName => "Category"; public override void Loaded() { string[] categories = Categories; foreach (string text in categories) { if (_categoryCache.ContainsKey(text.ToLowerInvariant())) { Logger.Error("Overlapping Category Found, Category Name: " + text); continue; } _categoryCache.Add(text.ToLowerInvariant(), new CategoryDefinition { Name = text }); Logger.Debug("Category Defined! '" + text + "'"); } IdWithCategories[] categoryPair = CategoryPair; foreach (IdWithCategories idWithCategories in categoryPair) { categories = idWithCategories.Categories; foreach (string text2 in categories) { if (!_categoryCache.TryGetValue(text2.ToLowerInvariant(), out CategoryDefinition value)) { Logger.Error("Unable to find Category: " + text2); } else { value.AddEnemyID(idWithCategories.PersistentID); } } Logger.Verbose($"Assign Categories to ID: '{idWithCategories.PersistentID}', Categories: [{string.Join(", ", idWithCategories.Categories)}]"); } CategoryWithIds[] idPair = IdPair; foreach (CategoryWithIds categoryWithIds in idPair) { if (!_categoryCache.TryGetValue(categoryWithIds.Category.ToLowerInvariant(), out CategoryDefinition value2)) { Logger.Error("Unable to find Category: " + categoryWithIds.Category); continue; } value2.AddEnemyIDRange(categoryWithIds.PersistentIDs); Logger.Verbose($"Assign Id to Category: '{categoryWithIds.Category}', ids: [{string.Join(", ", categoryWithIds.PersistentIDs)}]"); } foreach (CategoryDefinition value3 in _categoryCache.Values) { value3.CacheID(); Logger.Debug($"Category Initialized! '{value3.Name}', ids: [{string.Join(", ", value3.PersistentIDs)}]"); } } public bool Any(string[] categories, uint enemyID) { foreach (string text in categories) { if (!_categoryCache.TryGetValue(text.ToLowerInvariant(), out CategoryDefinition value)) { Logger.Warning("Unable to find Category with name: " + text); } else if (value.PersistentIDs.Contains(enemyID)) { return true; } } return false; } public bool All(string[] categories, uint enemyID) { bool result = true; foreach (string text in categories) { if (!_categoryCache.TryGetValue(text.ToLowerInvariant(), out CategoryDefinition value)) { Logger.Warning("Unable to find Category with name: " + text); result = false; break; } if (!value.PersistentIDs.Contains(enemyID)) { result = false; break; } } return result; } } public class IdWithCategories { public uint PersistentID { get; set; } public string[] Categories { get; set; } = Array.Empty(); } public class CategoryWithIds { public string Category { get; set; } = string.Empty; public uint[] PersistentIDs { get; set; } = Array.Empty(); } public class CategoryDefinition { public readonly List _PersistentIDs = new List(); public string Name { get; set; } public uint[] PersistentIDs { get; private set; } = Array.Empty(); public void AddEnemyIDRange(uint[] ids) { Array.ForEach(ids, delegate(uint id) { AddEnemyID(id); }); } public void AddEnemyID(uint id) { if (!_PersistentIDs.Contains(id)) { _PersistentIDs.Add(id); } } public void CacheID() { PersistentIDs = _PersistentIDs.ToArray(); } } public abstract class Config { [JsonIgnore] public abstract string FileName { get; } public virtual Config CreateBlankConfig() { Config config = Activator.CreateInstance(GetType()) as Config; SetDefaultArrayPropertyValue(config, GetType()); return config; } private void SetDefaultArrayPropertyValue(object obj, Type type) { PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo propertyInfo in properties) { if (!propertyInfo.CanWrite) { continue; } Type propertyType = propertyInfo.PropertyType; if (!propertyType.IsArray) { if (!propertyType.IsValueType) { SetDefaultArrayPropertyValue(propertyInfo.GetValue(obj), propertyType); } } else if (propertyType.HasElementType) { Type elementType = propertyType.GetElementType(); try { Array array = Array.CreateInstance(elementType, 1); object obj2 = Activator.CreateInstance(elementType); array.SetValue(obj2, 0); propertyInfo.SetValue(obj, array); SetDefaultArrayPropertyValue(obj2, elementType); } catch (Exception) { } } } } public virtual void Loaded() { } public virtual void Unloaded() { } } public sealed class GlobalConfig : Config { [JsonPropertyName("Flyer.StuckCheck.Enabled")] public bool UsingFlyerStuckCheck { get; set; } [JsonPropertyName("Flyer.StuckCheck.RetryCount")] public int FlyerStuck_Retry { get; set; } = 5; [JsonPropertyName("Flyer.StuckCheck.RetryInterval")] public float FlyerStuck_Interval { get; set; } = 1.5f; [JsonPropertyName("Material.CacheAll")] public bool CacheAllMaterials { get; set; } [JsonPropertyName("Bleeding.UseMediToStop")] public bool CanMediStopBleeding { get; set; } [JsonPropertyName("Bleeding.StopOnDown")] public bool CanDownStopBleeding { get; set; } [JsonPropertyName("WaveRoarFix.AutoAddUnused")] public bool AddUnusedVanillaRoars { get; set; } public override string FileName => "Global"; } public sealed class ScoutWaveConfig : Config { public ExpeditionScoutSetting[] Expeditions { get; set; } = Array.Empty(); public ScoutTargetSetting[] TargetSettings { get; set; } = Array.Empty(); public ScoutWaveSetting[] WaveSettings { get; set; } = Array.Empty(); public override string FileName => "ScoutWave"; public override void Loaded() { CustomScoutWaveManager.AddScoutSetting(Expeditions); CustomScoutWaveManager.AddTargetSetting(TargetSettings); CustomScoutWaveManager.AddWaveSetting(WaveSettings); } public override void Unloaded() { CustomScoutWaveManager.ClearAll(); } } } namespace EEC.Configs.Customizations { public sealed class AbilityCustomConfig : CustomizationConfig { public BirthingCustom[] BirthingCustom { get; set; } = Array.Empty(); public FogSphereCustom[] FogSphereCustom { get; set; } = Array.Empty(); public HealthRegenCustom[] HealthRegenCustom { get; set; } = Array.Empty(); public InfectionAttackCustom[] InfectionAttackCustom { get; set; } = Array.Empty(); public KnockbackAttackCustom[] KnockbackAttackCustom { get; set; } = Array.Empty(); public ExplosiveAttackCustom[] ExplosiveAttackCustom { get; set; } = Array.Empty(); public BleedAttackCustom[] BleedAttackCustom { get; set; } = Array.Empty(); public DrainStaminaAttackCustom[] DrainStaminaAttackCustom { get; set; } = Array.Empty(); public DoorBreakerCustom[] DoorBreakerCustom { get; set; } = Array.Empty(); public ScoutScreamingCustom[] ScoutScreamingCustom { get; set; } = Array.Empty(); public PouncerCustom[] PouncerCustom { get; set; } = Array.Empty(); public override string FileName => "Ability"; public override CustomizationConfigType Type => CustomizationConfigType.Ability; } public abstract class CustomizationConfig : Config { [JsonIgnore] public abstract CustomizationConfigType Type { get; } public virtual IEnumerable GetAllSettings() { IEnumerable> enumerable = (from x in GetType()?.GetProperties()?.Where((PropertyInfo x) => x.PropertyType != null && typeof(IEnumerable).IsAssignableFrom(x.PropertyType)) select (IEnumerable)x.GetValue(this)) ?? null; if (enumerable != null && enumerable.Any()) { List list = new List(); { foreach (IEnumerable item in enumerable) { list.AddRange(item); } return list; } } return Enumerable.Empty(); } } public enum CustomizationConfigType { Ability, Detection, EnemyAbility, Model, Projectile, Property, Tentacle } public sealed class DetectionCustomConfig : CustomizationConfig { public ScreamingCustom[] ScreamingCustom { get; set; } = Array.Empty(); public FeelerCustom[] FeelerCustom { get; set; } = Array.Empty(); public ScoutAnimCustom[] ScoutAnimCustom { get; set; } = Array.Empty(); public override string FileName => "Detection"; public override CustomizationConfigType Type => CustomizationConfigType.Detection; } public sealed class EnemyAbilityCustomConfig : CustomizationConfig { public BehaviourAbilityCustom[] BehaviourAbilityCustom { get; set; } = Array.Empty(); public LimbDestroyedAbilityCustom[] LimbDestroyedAbilityCustom { get; set; } = Array.Empty(); public DeathAbilityCustom[] DeathAbilityCustom { get; set; } = Array.Empty(); public EnemyAbilitiesSetting Abilities { get; set; } = new EnemyAbilitiesSetting(); public override string FileName => "EnemyAbility"; public override CustomizationConfigType Type => CustomizationConfigType.EnemyAbility; public override void Loaded() { Abilities.RegisterAll(); EnemyAbilityManager.Setup(); } public override void Unloaded() { EnemyAbilityManager.Clear(); } } public class EnemyAbilitiesSetting { public FogSphereAbility[] FogSphere { get; set; } = Array.Empty(); public ExplosionAbility[] Explosion { get; set; } = Array.Empty(); public SpawnEnemyAbility[] SpawnEnemy { get; set; } = Array.Empty(); public SpawnWaveAbility[] SpawnWave { get; set; } = Array.Empty(); public SpawnProjectileAbility[] SpawnProjectile { get; set; } = Array.Empty(); public DoAnimAbility[] DoAnim { get; set; } = Array.Empty(); public EMPAbility[] EMP { get; set; } = Array.Empty(); public CloakAbility[] Cloak { get; set; } = Array.Empty(); public ChainedAbility[] Chain { get; set; } = Array.Empty(); public void RegisterAll() { List list = new List(); list.AddRange(FogSphere); list.AddRange(Explosion); list.AddRange(SpawnEnemy); list.AddRange(SpawnWave); list.AddRange(SpawnProjectile); list.AddRange(DoAnim); list.AddRange(EMP); list.AddRange(Cloak); list.AddRange(Chain); foreach (IAbility item in list) { if (string.IsNullOrEmpty(item.Name)) { Logger.Warning("Ignoring EnemyAbility without any Name!"); } else { EnemyAbilityManager.AddAbility(item); } } } } public sealed class ModelCustomConfig : CustomizationConfig { public ShadowCustom[] ShadowCustom { get; set; } = Array.Empty(); public MaterialCustom[] MaterialCustom { get; set; } = Array.Empty(); public GlowCustom[] GlowCustom { get; set; } = Array.Empty(); public LimbCustom[] LimbCustom { get; set; } = Array.Empty(); public ModelRefCustom[] ModelRefCustom { get; set; } = Array.Empty(); public MarkerCustom[] MarkerCustom { get; set; } = Array.Empty(); public ScannerCustom[] ScannerCustom { get; set; } = Array.Empty(); public SilhouetteCustom[] SilhouetteCustom { get; set; } = Array.Empty(); public BoneCustom[] BoneCustom { get; set; } = Array.Empty(); public AnimHandleCustom[] AnimHandleCustom { get; set; } = Array.Empty(); public override string FileName => "Model"; public override CustomizationConfigType Type => CustomizationConfigType.Model; } public sealed class ProjectileCustomConfig : CustomizationConfig { public ShooterFireCustom[] ShooterFireCustom { get; set; } = Array.Empty(); public CustomProjectile[] ProjectileDefinitions { get; set; } = Array.Empty(); public override string FileName => "Projectile"; public override CustomizationConfigType Type => CustomizationConfigType.Projectile; public override void Loaded() { if (CustomProjectileManager.AssetLoaded) { CustomProjectile[] projectileDefinitions = ProjectileDefinitions; for (int i = 0; i < projectileDefinitions.Length; i++) { CustomProjectileManager.GenerateProjectile(projectileDefinitions[i]); } } } public override void Unloaded() { CustomProjectileManager.DestroyAllProjectile(); } } public sealed class PropertyCustomConfig : CustomizationConfig { public SpawnCostCustom[] SpawnCostCustom { get; set; } = Array.Empty(); public EventsCustom[] EventsCustom { get; set; } = Array.Empty(); public DistantRoarCustom[] DistantRoarCustom { get; set; } = Array.Empty(); public override string FileName => "Property"; public override CustomizationConfigType Type => CustomizationConfigType.Property; } [Obsolete("SpawnCost Config will be merged to Property in 2.x version!")] public sealed class SpawnCostCustomConfig : CustomizationConfig { public SpawnCostCustom[] SpawnCostCustom { get; set; } = Array.Empty(); public override string FileName => "SpawnCost"; public override CustomizationConfigType Type => CustomizationConfigType.Property; public override void Loaded() { Logger.Error("SpawnCost.json(c) will no longer avilable after 2.x.x version"); Logger.Error(" - Suggestion: Migrate to Property.json(c)"); } } public sealed class TentacleCustomConfig : CustomizationConfig { public StrikerTentacleCustom[] StrikerTentacleCustom { get; set; } = Array.Empty(); public CustomTentacle[] TentacleDefinitions { get; set; } = Array.Empty(); public override string FileName => "Tentacle"; public override CustomizationConfigType Type => CustomizationConfigType.Tentacle; } } namespace EEC.API { public static class CustomizationAPI { public static event Action SpawnCustomizationDone; internal static void OnSpawnCustomizationDone_Internal(EnemyAgent agent) { CustomizationAPI.SpawnCustomizationDone?.Invoke(agent); } public static bool HasCustomization(uint enemyID, string customizationTypeName) { return GetCustomizationsOf(enemyID, customizationTypeName).Any(); } public static bool TryGetCustomizations(uint enemyID, string customizationTypeName, out IEnumerable customs) { IEnumerable customizationsOf = GetCustomizationsOf(enemyID, customizationTypeName); if (customizationsOf.Any()) { customs = customizationsOf; return true; } customs = Enumerable.Empty(); return false; } public static bool TryGetCustomizationJsons(uint enemyID, string customizationTypeName, out IEnumerable jsons) { IEnumerable customizationsOf = GetCustomizationsOf(enemyID, customizationTypeName); if (customizationsOf.Any()) { List list = new List(); foreach (EnemyCustomBase item in customizationsOf) { list.Add(JsonSerializer.Serialize(item, item.GetType())); } jsons = list; return true; } jsons = Enumerable.Empty(); return false; } public static IEnumerable GetCustomizationsOf(uint enemyID, string customizationTypeName) { string customizationTypeName2 = customizationTypeName; IEnumerable customizationBuffer = ConfigManager.CustomizationBuffer; if (!customizationBuffer.Any()) { return Enumerable.Empty(); } IEnumerable enumerable = from x in customizationBuffer where x.GetType().Name.InvariantEquals(customizationTypeName2, ignoreCase: true) where x.Enabled && x.Target.IsMatch(enemyID) select x; if (enumerable != null) { return enumerable; } return Enumerable.Empty(); } } }