Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of EnemyInteractions v1.2.0
plugins/EnemyInteractions/EnemyInteractions.dll
Decompiled 11 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EmotesAPI; using EnemyInteractions.Components; using EnemyInteractions.DataStuffs; using EnemyInteractions.Utils; using GameNetcodeStuff; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LethalInternship.AI; using Microsoft.CodeAnalysis; using MonoMod.Cil; using MonoMod.RuntimeDetour; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("LethalInternship")] [assembly: AssemblyCompany("EnemyInteractions")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+414554b48907a9298387f6a51d69fa1f18cfa857")] [assembly: AssemblyProduct("EnemyInteractions")] [assembly: AssemblyTitle("EnemyInteractions")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EnemyInteractions { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.gemumoddo.enemyinteractions", "Enemy Interactions", "1.2.0")] public class EnemyInteractionsPlugin : BaseUnityPlugin { public const string ModGuid = "com.gemumoddo.enemyinteractions"; public const string ModName = "Enemy Interactions"; public const string ModVersion = "1.2.0"; public static EnemyInteractionsPlugin instance; internal static bool BadAssCompanyPresent; private void Awake() { instance = this; Logging.SetLogSource(((BaseUnityPlugin)this).Logger); EnemyKillHooks.InitHooks(); EnemyInteractionSettings.Setup(); BadAssCompanyPresent = Chainloader.PluginInfos.ContainsKey("com.weliveinasociety.badasscompany"); if (BadAssCompanyPresent && EnemyInteractionSettings.useBadAssCompany.Value) { EmoteOptions.onKillEmotes.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Default Dance", 30f)); EmoteOptions.onKillEmotes.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Take The L", 3f)); EmoteOptions.onKillEmotes.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Orange Justice", 3f)); EmoteOptions.onKillEmotes.Add(new EnemyEmote("com.weliveinasociety.badasscompany__California Gurls", 6.75f)); EmoteOptions.onKillEmotes.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Dabstand", 30f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Gangnam Style", 1f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Thicc", 2f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Butt", 30f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Club Penguin", 5f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__DevilSpawn", 6f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__I NEED A MEDIC BAG", 0.8f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Float", 1.2f)); EmoteOptions.intermittentEmoteList.Add(new EnemyEmote("com.weliveinasociety.badasscompany__Bird", 0.5f)); } } } internal class EnemyKillHooks { private static Hook? _enemyAiStartHook; private static Hook? _caveDwellerTransform; private static Hook? _killPlayerHook; private static Hook? _maskedAiStartHook; private static Hook? _enemyDeathHook; public static void InitHooks() { _maskedAiStartHook = HookUtils.NewHook<MaskedPlayerEnemy>("Start", typeof(EnemyKillHooks), "OnMaskedAiStart"); _enemyAiStartHook = HookUtils.NewHook<EnemyAI>("Start", typeof(EnemyKillHooks), "OnEnemyAiStart"); _killPlayerHook = HookUtils.NewHook<PlayerControllerB>("KillPlayer", typeof(EnemyKillHooks), "OnKillPlayer"); if (Chainloader.PluginInfos.ContainsKey("Szumi57.LethalInternship")) { InternCompat.SetupInternStartHook(); } _enemyDeathHook = HookUtils.NewHook<EnemyAI>("KillEnemy", typeof(EnemyKillHooks), "OnKillEnemy"); _caveDwellerTransform = HookUtils.NewHook<CaveDwellerAI>("StartTransformationAnim", typeof(EnemyKillHooks), "CaveDwellerStartTransformationAnim"); } private static void OnMaskedAiStart(Action<MaskedPlayerEnemy> orig, MaskedPlayerEnemy self) { orig(self); try { if (CustomEmotesAPI.localMapper.isServer) { ((Component)self).gameObject.AddComponent<RandomEmotesStarter>().Setup((EnemyAI)(object)self); } } catch (Exception) { } } private static void OnEnemyAiStart(Action<EnemyAI> orig, EnemyAI self) { orig(self); try { if (CustomEmotesAPI.localMapper.isServer) { ((Component)self).gameObject.AddComponent<RandomEmotesStarter>().Setup(self); } } catch (Exception) { } } private static void OnKillPlayer(Action<PlayerControllerB, Vector3, bool, CauseOfDeath, int, Vector3> orig, PlayerControllerB self, Vector3 bodyVelocity, bool spawnBody = true, CauseOfDeath causeOfDeath = 0, int deathAnimation = 0, Vector3 positionOffset = default(Vector3)) { //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0160: 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_00c1: Expected O, but got Unknown try { if (CustomEmotesAPI.localMapper.isServer && Random.Range(0f, 100f) < EnemyInteractionSettings.OnKillEmoteChance.Value) { List<GameObject> list = GetEnemies.ReturnAllEnemiesInRange(((Component)self).gameObject, 30f); foreach (GameObject item in list) { if (!BoneMapper.playersToMappers.ContainsKey(item)) { continue; } BoneMapper val = BoneMapper.playersToMappers[item]; if (!((Behaviour)val.emoteSkeletonAnimator).enabled) { val.preserveProps = true; EnemyEmote enemyEmote = EmoteOptions.onKillEmotes[Random.Range(0, EmoteOptions.onKillEmotes.Count)]; GameObject val2 = new GameObject(); EmoteStopper emoteStopper = val2.AddComponent<EmoteStopper>(); ((MonoBehaviour)emoteStopper).StartCoroutine(emoteStopper.StopEmoteAfterTime(val, enemyEmote.maxDuration)); val.props.Add(val2); if (CanEmoteChecker.CanEmote(val.enemyController.enemyType.enemyName)) { CustomEmotesAPI.PlayAnimation(enemyEmote.animationName, val, -2); } } } } } catch (Exception) { DebugClass.Log((object)"couldn't play on kill effects properly for EnemyInteractions"); } orig(self, bodyVelocity, spawnBody, causeOfDeath, deathAnimation, positionOffset); } private static void OnKillEnemy(Action<EnemyAI, bool> orig, EnemyAI self, bool destroy = false) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown orig(self, destroy); if (!destroy && EnemyInteractionsPlugin.BadAssCompanyPresent && EnemyInteractionSettings.emoteOnDeath.Value && BoneMapper.playersToMappers.ContainsKey(((Component)self).gameObject) && EnemyInteractionSettings.useBadAssCompany.Value) { BoneMapper val = BoneMapper.playersToMappers[((Component)self).gameObject]; val.preserveProps = true; EnemyEmote enemyEmote = new EnemyEmote("com.weliveinasociety.badasscompany__I NEED A MEDIC BAG", 5.5f); GameObject val2 = new GameObject(); EmoteStopper emoteStopper = val2.AddComponent<EmoteStopper>(); ((MonoBehaviour)emoteStopper).StartCoroutine(emoteStopper.StopEmoteAfterTime(val, enemyEmote.maxDuration)); val.props.Add(val2); if (CanEmoteChecker.CanEmote(val.enemyController.enemyType.enemyName)) { CustomEmotesAPI.PlayAnimation(enemyEmote.animationName, val, -2); } } } private static void CaveDwellerStartTransformationAnim(Action<CaveDwellerAI> orig, CaveDwellerAI self) { if (Object.op_Implicit((Object)(object)((Component)self).GetComponent<RandomEmotesStarter>())) { ((MonoBehaviour)CustomEmotesAPI.localMapper).StartCoroutine(SetupManEaterAdult(self)); } orig(self); } private static IEnumerator SetupManEaterAdult(CaveDwellerAI self) { yield return (object)new WaitForSeconds(2.5f); ((Component)self).gameObject.GetComponent<RandomEmotesStarter>().Setup((EnemyAI)(object)self); } } internal class InternCompat { private static Hook? StartHook; public static void SetupInternStartHook() { StartHook = HookUtils.NewHook<InternAI>("Start", typeof(InternCompat), "Start"); } private static void Start(Action<InternAI> orig, InternAI self) { orig(self); ((Component)self).gameObject.AddComponent<RandomEmotesStarter>().Setup((EnemyAI)(object)self); } } } namespace EnemyInteractions.Utils { internal class CanEmoteChecker { public static bool CanEmote(string enemyName) { if (1 == 0) { } bool result = enemyName switch { "Bunker Spider" => EnemyInteractionSettings.bunkerSpiderEmote.Value, "Hoarding bug" => EnemyInteractionSettings.hoardingBugEmote.Value, "Earth Leviathan" => EnemyInteractionSettings.earthLeviathanEmote.Value, "Crawler" => EnemyInteractionSettings.thumperEmote.Value, "Blob" => EnemyInteractionSettings.hygrodereEmote.Value, "Centipede" => EnemyInteractionSettings.snareFleaEmote.Value, "Nutcracker" => EnemyInteractionSettings.nutcrackerEmote.Value, "Baboon hawk" => EnemyInteractionSettings.baboonHawkEmote.Value, "Puffer" => EnemyInteractionSettings.sporeLizardEmote.Value, "Spring" => EnemyInteractionSettings.coilHeadEmote.Value, "Jester" => EnemyInteractionSettings.jesterEmote.Value, "Flowerman" => EnemyInteractionSettings.brackenEmote.Value, "Girl" => EnemyInteractionSettings.ghostGirlEmote.Value, "MouthDog" => EnemyInteractionSettings.eyelessDogEmote.Value, "ForestGiant" => EnemyInteractionSettings.forestKeeperEmote.Value, "Masked" => EnemyInteractionSettings.maskedEmote.Value, "Shy guy" => EnemyInteractionSettings.shyGuyEmote.Value, "SkibidiToilet" => EnemyInteractionSettings.skibidiToiletEmote.Value, "Demogorgon" => EnemyInteractionSettings.demoGorgonEmote.Value, "Peeper" => EnemyInteractionSettings.peeperEmote.Value, "RadMech" => EnemyInteractionSettings.radMechEmote.Value, "Butler" => EnemyInteractionSettings.butlerEmote.Value, "Tulip Snake" => EnemyInteractionSettings.tulipSnakeEmote.Value, "HarpGhost" => EnemyInteractionSettings.harpGhostEmote.Value, "EnforcerGhost" => EnemyInteractionSettings.enforcerGhostEmote.Value, "BagpipeGhost" => EnemyInteractionSettings.bagpipeGhostEmote.Value, "SlendermanEnemy" => EnemyInteractionSettings.slendermanEmote.Value, "RedWoodGiant" => EnemyInteractionSettings.redWoodGiantEmote.Value, "DriftWoodGiant" => EnemyInteractionSettings.driftWoodGiantEmote.Value, "Foxy" => EnemyInteractionSettings.foxyEmote.Value, "The Fiend" => EnemyInteractionSettings.theFiendEmote.Value, "Siren Head" => EnemyInteractionSettings.sirenHeadEmote.Value, "Football" => EnemyInteractionSettings.footballEmote.Value, "Sentinel" => EnemyInteractionSettings.sentinelEmote.Value, "Bush Wolf" => EnemyInteractionSettings.bushWolfEmote.Value, "Clay Surgeon" => EnemyInteractionSettings.claySurgeonEmote.Value, "InternNPC" => EnemyInteractionSettings.internEmote.Value, "Maneater" => EnemyInteractionSettings.caveDwellerEmote.Value, _ => false, }; if (1 == 0) { } return result; } } internal class GetEnemies { private static readonly object _lock = new object(); internal static List<GameObject> ReturnAllEnemiesInRange(GameObject self, float range) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) lock (_lock) { try { if (CustomEmotesAPI.localMapper.isServer) { Collider[] array = Physics.OverlapSphere(self.transform.position, range); List<GameObject> list = new List<GameObject>(); Collider[] array2 = array; foreach (Collider val in array2) { EnemyAI componentInParent = ((Component)val).GetComponentInParent<EnemyAI>(); if (componentInParent != null && !list.Contains(((Component)componentInParent).gameObject)) { list.Add(((Component)componentInParent).gameObject); } } return list; } } catch (Exception ex) { Logging.Error("Exception in ReturnAllEnemiesInRange: " + ex.Message); } return new List<GameObject>(); } } } internal static class HookUtils { private const BindingFlags DefaultFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public static Hook NewHook<TTarget, TDest>(string targetMethodName, string destMethodName, TDest instance) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown MethodInfo method = typeof(TTarget).GetMethod(targetMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method2 = typeof(TDest).GetMethod(destMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return new Hook((MethodBase)method, method2, (object)instance); } public static Hook NewHook<TTarget>(string targetMethodName, MethodInfo destMethod) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown MethodInfo method = typeof(TTarget).GetMethod(targetMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return new Hook((MethodBase)method, destMethod); } public static Hook NewHook<TTarget>(string targetMethodName, Type destType, string destMethodName) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown MethodInfo method = typeof(TTarget).GetMethod(targetMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method2 = destType.GetMethod(destMethodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); return new Hook((MethodBase)method, method2); } public static ILHook NewILHook<TTarget>(string targetMethodName, Manipulator manipulator) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown MethodInfo method = typeof(TTarget).GetMethod(targetMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return new ILHook((MethodBase)method, manipulator); } } internal static class Logging { private static ManualLogSource? _logSource; internal static void SetLogSource(ManualLogSource logSource) { _logSource = logSource; } public static void Error(object data) { Error(data.ToString()); } public static void Warn(object data) { Warn(data.ToString()); } public static void Info(object data) { Info(data.ToString()); } public static void Error(string msg) { if (_logSource == null) { Debug.LogError((object)("[Enemy Interactions] [Error] " + msg)); } else { _logSource.LogError((object)msg); } } public static void Warn(string msg) { if (_logSource == null) { Debug.LogWarning((object)("[Enemy Interactions] [Warning] " + msg)); } else { _logSource.LogWarning((object)msg); } } public static void Info(string msg) { if (_logSource == null) { Debug.Log((object)("[Enemy Interactions] [Info] " + msg)); } else { _logSource.LogInfo((object)msg); } } } } namespace EnemyInteractions.DataStuffs { public class EmoteOptions { public static List<EnemyEmote> onKillEmotes = new List<EnemyEmote>(); public static List<EnemyEmote> intermittentEmoteList = new List<EnemyEmote>(); } public struct EnemyEmote { public string animationName; public float maxDuration; public EnemyEmote(string animationName, float maxDuration) { this.animationName = animationName; this.maxDuration = maxDuration; } } public static class EnemyInteractionSettings { public static ConfigEntry<float> RandomEmoteFrequencyMinimum; public static ConfigEntry<float> RandomEmoteFrequencyMaximum; public static ConfigEntry<float> OnKillEmoteChance; public static ConfigEntry<bool> snareFleaEmote; public static ConfigEntry<bool> bunkerSpiderEmote; public static ConfigEntry<bool> hoardingBugEmote; public static ConfigEntry<bool> brackenEmote; public static ConfigEntry<bool> thumperEmote; public static ConfigEntry<bool> hygrodereEmote; public static ConfigEntry<bool> ghostGirlEmote; public static ConfigEntry<bool> sporeLizardEmote; public static ConfigEntry<bool> nutcrackerEmote; public static ConfigEntry<bool> coilHeadEmote; public static ConfigEntry<bool> jesterEmote; public static ConfigEntry<bool> maskedEmote; public static ConfigEntry<bool> eyelessDogEmote; public static ConfigEntry<bool> forestKeeperEmote; public static ConfigEntry<bool> earthLeviathanEmote; public static ConfigEntry<bool> baboonHawkEmote; public static ConfigEntry<bool> shyGuyEmote; public static ConfigEntry<bool> skibidiToiletEmote; public static ConfigEntry<bool> demoGorgonEmote; public static ConfigEntry<bool> peeperEmote; public static ConfigEntry<bool> radMechEmote; public static ConfigEntry<bool> butlerEmote; public static ConfigEntry<bool> tulipSnakeEmote; public static ConfigEntry<bool> harpGhostEmote; public static ConfigEntry<bool> enforcerGhostEmote; public static ConfigEntry<bool> bagpipeGhostEmote; public static ConfigEntry<bool> slendermanEmote; public static ConfigEntry<bool> redWoodGiantEmote; public static ConfigEntry<bool> driftWoodGiantEmote; public static ConfigEntry<bool> foxyEmote; public static ConfigEntry<bool> theFiendEmote; public static ConfigEntry<bool> sirenHeadEmote; public static ConfigEntry<bool> footballEmote; public static ConfigEntry<bool> sentinelEmote; public static ConfigEntry<bool> bushWolfEmote; public static ConfigEntry<bool> claySurgeonEmote; public static ConfigEntry<bool> caveDwellerEmote; public static ConfigEntry<bool> internEmote; public static ConfigEntry<bool> emoteOnDeath; public static ConfigEntry<bool> useBadAssCompany; internal static void Setup() { RandomEmoteFrequencyMinimum = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<float>("Settings", "Random Emote Frequency Minimum Time", 60f, "Enemies will emote at random between the minimum and maximum amount of time specified in seconds"); RandomEmoteFrequencyMaximum = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<float>("Settings", "Random Emote Frequency Maximum Time", 120f, "Enemies will emote at random between the minimum and maximum amount of time specified in seconds"); OnKillEmoteChance = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<float>("Settings", "On Kill Emote Chance", 100f, "% chance for enemies to emote upon a player dying near them"); snareFleaEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Snare Flea can emote", true, "Lets the specified enemy emote with enemy interactions"); bunkerSpiderEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Bunker Spider can emote", true, "Lets the specified enemy emote with enemy interactions"); hoardingBugEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Hoarding Bug can emote", true, "Lets the specified enemy emote with enemy interactions"); brackenEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Bracken can emote", true, "Lets the specified enemy emote with enemy interactions"); thumperEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Thumper can emote", true, "Lets the specified enemy emote with enemy interactions"); hygrodereEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Hygrodere can emote", true, "Lets the specified enemy emote with enemy interactions"); ghostGirlEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Ghost Girl can emote", true, "Lets the specified enemy emote with enemy interactions"); sporeLizardEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Spore Lizard can emote", true, "Lets the specified enemy emote with enemy interactions"); nutcrackerEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Nutcracker can emote", true, "Lets the specified enemy emote with enemy interactions"); coilHeadEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Coil-Head can emote", true, "Lets the specified enemy emote with enemy interactions"); jesterEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Jester can emote", true, "Lets the specified enemy emote with enemy interactions"); maskedEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Masked can emote", true, "Lets the specified enemy emote with enemy interactions"); eyelessDogEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Eyeless Dog can emote", true, "Lets the specified enemy emote with enemy interactions"); forestKeeperEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Forest Keeper can emote", true, "Lets the specified enemy emote with enemy interactions"); earthLeviathanEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Earth Leviathan can emote", true, "Lets the specified enemy emote (technically) with enemy interactions"); baboonHawkEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Baboon Hawk can emote", true, "Lets the specified enemy emote with enemy interactions"); shyGuyEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Shy Guy can emote", true, "Lets the specified enemy emote with enemy interactions"); skibidiToiletEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Skibidi Toilet can emote", true, "Lets the specified enemy emote with enemy interactions"); demoGorgonEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "DemoGorgon can emote", true, "Lets the specified enemy emote with enemy interactions"); peeperEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Peeper can emote", true, "Lets the specified enemy emote with enemy interactions"); radMechEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Old Bird can emote", true, "Lets the specified enemy emote with enemy interactions"); butlerEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Butler can emote", true, "Lets the specified enemy emote with enemy interactions"); tulipSnakeEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Tulip Snake can emote", true, "Lets the specified enemy emote with enemy interactions"); harpGhostEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Harp Ghost can emote", true, "Lets the specified enemy emote with enemy interactions"); enforcerGhostEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Enforcer Ghost can emote", true, "Lets the specified enemy emote with enemy interactions"); bagpipeGhostEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Bagpipe Ghost can emote", true, "Lets the specified enemy emote with enemy interactions"); slendermanEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Slenderman can emote", true, "Lets the specified enemy emote with enemy interactions"); redWoodGiantEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Redwood Giant can emote", true, "Lets the specified enemy emote with enemy interactions"); driftWoodGiantEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Driftwood Giant can emote", true, "Lets the specified enemy emote with enemy interactions"); foxyEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Foxy can emote", true, "Lets the specified enemy emote with enemy interactions"); theFiendEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "The Fiend can emote", true, "Lets the specified enemy emote with enemy interactions"); sirenHeadEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Siren Head can emote", true, "Lets the specified enemy emote with enemy interactions"); footballEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Football can emote", true, "Lets the specified enemy emote with enemy interactions"); sentinelEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Sentinel can emote", true, "Lets the specified enemy emote with enemy interactions"); bushWolfEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Kidnapper Fox can emote", true, "Lets the specified enemy emote with enemy interactions"); claySurgeonEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Barber can emote", true, "Lets the specified enemy emote with enemy interactions"); caveDwellerEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Maneater can emote", true, "Lets the specified enemy emote with enemy interactions"); internEmote = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Modded Enemies", "Interns can emote", true, "Lets the specified enemy emote with enemy interactions"); emoteOnDeath = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Enemies Need a Medic Bag", true, "...when they die (Requires BadAssEmotes for the emote)"); useBadAssCompany = ((BaseUnityPlugin)EnemyInteractionsPlugin.instance).Config.Bind<bool>("Misc", "Use BadAssCompany", true, "Use BadAssCompany?"); RandomEmoteFrequencyMinimum.SettingChanged += FrequencyChange; RandomEmoteFrequencyMaximum.SettingChanged += FrequencyChange; OnKillEmoteChance.SettingChanged += FrequencyChange; ClampChance(); if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { LethalConfig(); } } private static void FrequencyChange(object sender, EventArgs e) { ClampChance(); } private static void ClampChance() { RandomEmoteFrequencyMaximum.Value = Mathf.Clamp(RandomEmoteFrequencyMaximum.Value, 2f, 86400f); RandomEmoteFrequencyMinimum.Value = Mathf.Clamp(RandomEmoteFrequencyMinimum.Value, 1f, RandomEmoteFrequencyMaximum.Value); OnKillEmoteChance.Value = Mathf.Clamp(OnKillEmoteChance.Value, 0f, 100f); } private static void LethalConfig() { //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_0021: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //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) //IL_0056: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_007b: 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) //IL_008b: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown LethalConfigManager.SetModDescription("Enemies can emote too!"); ConfigEntry<float> randomEmoteFrequencyMinimum = RandomEmoteFrequencyMinimum; FloatSliderOptions val = new FloatSliderOptions(); ((BaseRangeOptions<float>)val).Min = 0f; ((BaseRangeOptions<float>)val).Max = 600f; ((BaseOptions)val).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(randomEmoteFrequencyMinimum, val)); ConfigEntry<float> randomEmoteFrequencyMaximum = RandomEmoteFrequencyMaximum; FloatSliderOptions val2 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val2).Min = 0f; ((BaseRangeOptions<float>)val2).Max = 600f; ((BaseOptions)val2).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(randomEmoteFrequencyMaximum, val2)); ConfigEntry<float> onKillEmoteChance = OnKillEmoteChance; FloatSliderOptions val3 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val3).Min = 0f; ((BaseRangeOptions<float>)val3).Max = 100f; ((BaseOptions)val3).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(onKillEmoteChance, val3)); } } } namespace EnemyInteractions.Components { internal class EmoteStopper : MonoBehaviour { private Coroutine _stopCoroutine; internal IEnumerator StopEmoteAfterTime(BoneMapper mapper, float time) { _stopCoroutine = ((MonoBehaviour)this).StartCoroutine(StopEmoteAfterTimeInternal(mapper, time)); yield return _stopCoroutine; } private IEnumerator StopEmoteAfterTimeInternal(BoneMapper mapper, float time) { yield return (object)new WaitForSeconds(time); if ((Object)(object)mapper == (Object)null || (Object)(object)((Component)mapper).gameObject == (Object)null) { Logging.Warn("Mapper or its GameObject is null in StopEmoteAfterTime. Skipping emote stop."); yield break; } if ((Object)(object)mapper.emoteSkeletonAnimator == (Object)null) { Logging.Warn("Mapper's emoteSkeletonAnimator is null in StopEmoteAfterTime. Skipping emote stop."); yield break; } CustomEmotesAPI.PlayAnimation("none", mapper, -2); if ((Object)(object)((Component)this).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void OnDestroy() { if (_stopCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_stopCoroutine); } } } internal class RandomEmotePlayer : MonoBehaviour { internal BoneMapper? personalMapper; internal EnemyAI? personalAI; internal bool skipNextRandomPlay = false; internal void SetupToRandomlyEmote(BoneMapper personalMapper, EnemyAI personalAI) { if (CustomEmotesAPI.localMapper.isServer) { this.personalMapper = personalMapper; this.personalAI = personalAI; ((MonoBehaviour)this).StartCoroutine(PlayEmotesRandomly()); } } internal IEnumerator PlaySpecificEmote(EnemyEmote emoteName, bool skip, BoneMapper mapper, RandomEmotePlayer emotePlayer, int recursionDepth = 0) { if (recursionDepth >= 10) { Logging.Info("Recursion depth limit reached in PlaySpecificEmote."); yield break; } if ((Object)(object)personalAI == (Object)null || (Object)(object)personalMapper == (Object)null) { Logging.Error("personalAI or personalMapper is null in PlaySpecificEmote."); yield break; } if ((Object)(object)mapper == (Object)null) { Logging.Error("mapper is null in PlaySpecificEmote."); yield break; } if ((Object)(object)mapper.enemyController == (Object)null) { Logging.Error("mapper.enemyController is null in PlaySpecificEmote."); yield break; } if ((Object)(object)mapper.enemyController.enemyType == (Object)null) { Logging.Error("mapper.enemyController.enemyType is null in PlaySpecificEmote."); yield break; } if (personalAI.isEnemyDead || ((Behaviour)mapper.emoteSkeletonAnimator).enabled || emotePlayer.skipNextRandomPlay) { Logging.Info("Skipping emote due to conditions: isEnemyDead, emoteSkeletonAnimator.enabled, or skipNextRandomPlay."); yield break; } emotePlayer.skipNextRandomPlay = skip; mapper.preserveProps = true; GameObject g = new GameObject(); EmoteStopper lmao = g.AddComponent<EmoteStopper>(); ((MonoBehaviour)lmao).StartCoroutine(lmao.StopEmoteAfterTime(mapper, emoteName.maxDuration)); mapper.props.Add(g); if (CanEmoteChecker.CanEmote(mapper.enemyController.enemyType.enemyName)) { Logging.Info("Playing emote: " + emoteName.animationName); CustomEmotesAPI.PlayAnimation(emoteName.animationName, mapper, -2); } else { Logging.Info("Cannot play emote for enemy: " + mapper.enemyController.enemyType.enemyName); } yield return (object)new WaitForSeconds(0.1f); List<GameObject> nearbyEnemies = GetEnemies.ReturnAllEnemiesInRange(((Component)personalAI).gameObject, 15f); foreach (GameObject item in nearbyEnemies) { if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)((Component)personalAI).gameObject || !BoneMapper.playersToMappers.ContainsKey(item)) { continue; } BoneMapper b = BoneMapper.playersToMappers[item]; EnemyAI enemyAI = item.GetComponent<EnemyAI>(); if (!((Object)(object)enemyAI == (Object)null) && !enemyAI.isEnemyDead && !((Behaviour)b.emoteSkeletonAnimator).enabled && Random.Range(0, 5) > 1) { RandomEmotePlayer randomPlayer = ((Component)b).GetComponent<RandomEmotePlayer>(); if ((Object)(object)randomPlayer != (Object)null) { Logging.Info("Triggering emote on nearby enemy: " + b.enemyController.enemyType.enemyName); ((MonoBehaviour)randomPlayer).StartCoroutine(PlaySpecificEmote(emoteName, skip: true, b, randomPlayer, recursionDepth + 1)); } } } } internal IEnumerator PlayEmotesRandomly() { while (!personalAI.isEnemyDead) { float seconds = Random.Range(EnemyInteractionSettings.RandomEmoteFrequencyMinimum.Value, EnemyInteractionSettings.RandomEmoteFrequencyMaximum.Value); yield return (object)new WaitForSeconds(seconds); if (!skipNextRandomPlay) { EnemyEmote emote = EmoteOptions.intermittentEmoteList[Random.Range(0, EmoteOptions.intermittentEmoteList.Count)]; Logging.Info("Playing random emote: " + emote.animationName); ((MonoBehaviour)this).StartCoroutine(PlaySpecificEmote(emote, skip: false, personalMapper, this)); } else { Logging.Info("Skipping random emote due to skipNextRandomPlay."); } skipNextRandomPlay = false; } Logging.Info("PlayEmotesRandomly coroutine ended because the enemy is dead."); } } public class RandomEmotesStarter : MonoBehaviour { internal EnemyAI enemyAI; public void Setup(EnemyAI enemyAI) { this.enemyAI = enemyAI; ((MonoBehaviour)this).StartCoroutine(SetupRandomEmotes(enemyAI)); } public IEnumerator SetupRandomEmotes(EnemyAI self) { yield return (object)new WaitForSeconds(0.1f); if (BoneMapper.playersToMappers?.ContainsKey(((Component)self).gameObject) ?? false) { BoneMapper b = BoneMapper.playersToMappers[((Component)self).gameObject]; RandomEmotePlayer component = ((Component)b).gameObject.AddComponent<RandomEmotePlayer>(); component.SetupToRandomlyEmote(b, self); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }