using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; 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 GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BetterEmotes")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Alters the integration method of more emotes")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1+a15948a69109c25e8a4c654780258e3985c2dd12")] [assembly: AssemblyProduct("BetterEmotes")] [assembly: AssemblyTitle("BetterEmotes")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BetterEmote { public class CustomAudioAnimationEvent : MonoBehaviour { private Animator animator; private AudioSource SoundsSource; public static AudioClip[] claps = (AudioClip[])(object)new AudioClip[2]; public PlayerControllerB player; private void Start() { animator = ((Component)this).GetComponent(); SoundsSource = player.movementAudio; } public void PlayClapSound() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (player.performingEmote && (!((NetworkBehaviour)player).IsOwner || !player.isPlayerControlled || animator.GetInteger("emoteNumber") == 4)) { bool flag = player.isInHangarShipRoom && player.playersManager.hangarDoorsClosed; RoundManager.Instance.PlayAudibleNoise(((Component)player).transform.position, 22f, 0.6f, 0, flag, 6); SoundsSource.pitch = Random.Range(0.59f, 0.79f); SoundsSource.PlayOneShot(claps[Random.Range(0, claps.Length)]); } } public void PlayFootstepSound() { if (player.performingEmote && (!((NetworkBehaviour)player).IsOwner || !player.isPlayerControlled || animator.GetInteger("emoteNumber") == 6)) { player.PlayFootstepLocal(); player.PlayFootstepServer(); } } } internal class EmotePatch { public enum Emotes { Dance = 1, Point, Middle_Finger, Clap, Shy, Griddy, Twerk, Salute } public static Keybinds keybinds = new Keybinds(); public static AssetBundle animationsBundle; public static AssetBundle animatorBundle; public static bool stopOnOuter = false; public static bool[] enabledList; public static float griddySpeed = 0.5f; public static float emoteCooldown = 0.5f; private static CallbackContext context; public static RuntimeAnimatorController local; public static RuntimeAnimatorController others; private static int currentEmoteID; private static float movSpeed; public static bool incompatibleStuff; public static bool emoteWheelIsOpened; public static GameObject wheel; private static SelectionWheel selectionWheel; private static PlayerControllerB localPlayerController { get { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.localPlayerController; } } [HarmonyPatch(typeof(PlayerControllerB), "Start")] [HarmonyPostfix] private static void StartPostfix(PlayerControllerB __instance) { ((Component)((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel")).transform.Find("metarig")).gameObject.AddComponent().player = __instance; movSpeed = __instance.movementSpeed; if (Object.FindObjectsOfType(typeof(SelectionWheel)).Length == 0) { GameObject obj = animationsBundle.LoadAsset("Assets/MoreEmotes/Resources/MoreEmotesMenu.prefab"); GameObject gameObject = ((Component)((Component)GameObject.Find("Systems").gameObject.transform.Find("UI")).gameObject.transform.Find("Canvas")).gameObject; if ((Object)(object)wheel != (Object)null) { Object.Destroy((Object)(object)wheel.gameObject); } wheel = Object.Instantiate(obj, gameObject.transform); selectionWheel = wheel.AddComponent(); SelectionWheel.emoteNames = new string[Enum.GetNames(typeof(Emotes)).Length + 1]; string[] names = Enum.GetNames(typeof(Emotes)); foreach (string text in names) { SelectionWheel.emoteNames[(int)Enum.Parse(typeof(Emotes), text) - 1] = text; } } keybinds.MiddleFinger.performed += onEmoteKeyMiddleFinger; keybinds.Griddy.performed += onEmoteKeyGriddy; keybinds.Shy.performed += onEmoteKeyShy; keybinds.Clap.performed += onEmoteKeyClap; keybinds.Salute.performed += onEmoteKeySalute; keybinds.Twerk.performed += onEmoteKeyTwerk; keybinds.EmoteWheel.started += onEmoteKeyWheelStarted; keybinds.EmoteWheel.canceled += onEmoteKeyWheelCanceled; } [HarmonyPatch(typeof(PlayerControllerB), "OnDisable")] [HarmonyPostfix] public static void OnDisablePostfix(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)(object)localPlayerController) { keybinds.MiddleFinger.performed -= onEmoteKeyMiddleFinger; keybinds.Griddy.performed -= onEmoteKeyGriddy; keybinds.Shy.performed -= onEmoteKeyShy; keybinds.Clap.performed -= onEmoteKeyClap; keybinds.Salute.performed -= onEmoteKeySalute; keybinds.Twerk.performed -= onEmoteKeyTwerk; keybinds.EmoteWheel.started -= onEmoteKeyWheelStarted; keybinds.EmoteWheel.canceled -= onEmoteKeyWheelCanceled; keybinds.MiddleFinger.Disable(); keybinds.Griddy.Disable(); keybinds.Shy.Disable(); keybinds.Clap.Disable(); keybinds.Salute.Disable(); keybinds.Twerk.Disable(); keybinds.EmoteWheel.Disable(); } } public static void onEmoteKeyWheelStarted(CallbackContext context) { if (!emoteWheelIsOpened && !localPlayerController.isPlayerDead && !localPlayerController.inTerminalMenu && !localPlayerController.quickMenuManager.isMenuOpen) { emoteWheelIsOpened = true; Cursor.visible = true; Cursor.lockState = (CursorLockMode)2; wheel.SetActive(emoteWheelIsOpened); localPlayerController.quickMenuManager.isMenuOpen = true; localPlayerController.disableLookInput = true; } } public static void onEmoteKeyWheelCanceled(CallbackContext context) { localPlayerController.quickMenuManager.isMenuOpen = false; localPlayerController.disableLookInput = false; if (selectionWheel.selectedEmoteID >= enabledList.Length) { if (selectionWheel.stopEmote) { localPlayerController.performingEmote = false; localPlayerController.StopPerformingEmoteServerRpc(); localPlayerController.timeSinceStartingEmote = 0f; } } else { CheckEmoteInput(enabledList[selectionWheel.selectedEmoteID], selectionWheel.selectedEmoteID, localPlayerController); } Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; emoteWheelIsOpened = false; wheel.SetActive(emoteWheelIsOpened); } public static void onEmoteKeyMiddleFinger(CallbackContext context) { onEmoteKeyPerformed(Emotes.Middle_Finger); } public static void onEmoteKeyGriddy(CallbackContext context) { onEmoteKeyPerformed(Emotes.Griddy); } public static void onEmoteKeyShy(CallbackContext context) { onEmoteKeyPerformed(Emotes.Shy); } public static void onEmoteKeyClap(CallbackContext context) { onEmoteKeyPerformed(Emotes.Clap); } public static void onEmoteKeySalute(CallbackContext context) { onEmoteKeyPerformed(Emotes.Salute); } public static void onEmoteKeyTwerk(CallbackContext context) { onEmoteKeyPerformed(Emotes.Twerk); } public static void onEmoteKeyPerformed(Emotes emote) { CheckEmoteInput(enabledList[(int)emote], (int)emote, localPlayerController); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void UpdatePrefix(PlayerControllerB __instance) { if (!__instance.isPlayerControlled || !((NetworkBehaviour)__instance).IsOwner) { __instance.playerBodyAnimator.runtimeAnimatorController = others; return; } if ((Object)(object)__instance.playerBodyAnimator != (Object)(object)local) { __instance.playerBodyAnimator.runtimeAnimatorController = local; } bool valueOrDefault = (Traverse.Create((object)__instance).Method("CheckConditionsForEmote", Array.Empty()).GetValue() as bool?).GetValueOrDefault(); currentEmoteID = __instance.playerBodyAnimator.GetInteger("emoteNumber"); if (!incompatibleStuff) { __instance.movementSpeed = ((valueOrDefault && currentEmoteID == 6 && __instance.performingEmote) ? (movSpeed * griddySpeed) : movSpeed); } } private static void CheckEmoteInput(bool enabled, int emoteID, PlayerControllerB player) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (enabled) { player.PerformEmote(context, emoteID); } } [HarmonyPatch(typeof(PlayerControllerB), "PerformEmote")] [HarmonyPrefix] private static void PerformEmotePrefix(ref CallbackContext context, int emoteID, PlayerControllerB __instance) { currentEmoteID = emoteID; if (((((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject)) || __instance.isTestingPlayer) && (Traverse.Create((object)__instance).Method("CheckConditionsForEmote", Array.Empty()).GetValue() as bool?).GetValueOrDefault() && __instance.timeSinceStartingEmote >= emoteCooldown) { __instance.timeSinceStartingEmote = 0f; __instance.performingEmote = true; __instance.playerBodyAnimator.SetInteger("emoteNumber", emoteID); __instance.StartPerformingEmoteServerRpc(); } } [HarmonyPatch(typeof(PlayerControllerB), "CheckConditionsForEmote")] [HarmonyPrefix] private static bool prefixCheckConditions(ref bool __result, PlayerControllerB __instance) { bool valueOrDefault = (Traverse.Create((object)__instance).Field("isJumping").GetValue() as bool?).GetValueOrDefault(); if (currentEmoteID == 6) { __result = !__instance.inSpecialInteractAnimation && !__instance.isPlayerDead && !valueOrDefault && __instance.moveInputVector.x == 0f && !__instance.isSprinting && !__instance.isCrouching && !__instance.isClimbingLadder && !__instance.isGrabbingObjectAnimation && !__instance.inTerminalMenu && !__instance.isTypingChat; return false; } return true; } } internal class InitGamePatch { [HarmonyPatch(typeof(InitializeGame), "Start")] [HarmonyPrefix] private static void StartPostfix() { foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { BepInPlugin metadata = pluginInfo.Value.Metadata; if (metadata.GUID.Equals("com.malco.lethalcompany.moreshipupgrades") || metadata.GUID.Equals("Stoneman.LethalProgression")) { EmotePatch.incompatibleStuff = true; break; } } } } internal class Keybinds : LcInputActions { [InputAction("/3", Name = "Middle Finger")] public InputAction MiddleFinger { get; set; } [InputAction("/6", Name = "Griddy")] public InputAction Griddy { get; set; } [InputAction("/5", Name = "Shy")] public InputAction Shy { get; set; } [InputAction("/4", Name = "Clap")] public InputAction Clap { get; set; } [InputAction("/7", Name = "Salute")] public InputAction Salute { get; set; } [InputAction("/8", Name = "Twerk")] public InputAction Twerk { get; set; } [InputAction("/v", Name = "Emote Wheel")] public InputAction EmoteWheel { get; set; } } [BepInPlugin("BetterEmotes", "BetterEmotes", "1.1.1")] public class Plugin : BaseUnityPlugin { public static ManualLogSource StaticLogger; private Harmony _harmony; private void Awake() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown StaticLogger = ((BaseUnityPlugin)this).Logger; StaticLogger.LogInfo((object)"BetterEmotes loading..."); EmotePatch.animationsBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "BetterEmotes/animationsbundle")); EmotePatch.animatorBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "BetterEmotes/animatorbundle")); EmotePatch.local = (RuntimeAnimatorController)new AnimatorOverrideController(EmotePatch.animatorBundle.LoadAsset("Assets/MoreEmotes/NEWmetarig.controller")); EmotePatch.others = EmotePatch.animatorBundle.LoadAsset("Assets/MoreEmotes/NEWmetarigOtherPlayers.controller"); CustomAudioAnimationEvent.claps[0] = EmotePatch.animationsBundle.LoadAsset("Assets/MoreEmotes/SingleClapEmote1.wav"); CustomAudioAnimationEvent.claps[1] = EmotePatch.animationsBundle.LoadAsset("Assets/MoreEmotes/SingleClapEmote2.wav"); ConfigFile(); _harmony = new Harmony("BetterEmotes"); _harmony.PatchAll(typeof(InitGamePatch)); _harmony.PatchAll(typeof(EmotePatch)); StaticLogger.LogInfo((object)"BetterEmotes loaded"); } private void ConfigFile() { EmotePatch.enabledList = new bool[Enum.GetNames(typeof(EmotePatch.Emotes)).Length + 1]; string[] names = Enum.GetNames(typeof(EmotePatch.Emotes)); foreach (string text in names) { ConfigEntry val = ((BaseUnityPlugin)this).Config.Bind("Enabled Emotes", "Enable " + text, true, "Toggle " + text + " emote key"); EmotePatch.enabledList[(int)Enum.Parse(typeof(EmotePatch.Emotes), text)] = val.Value; } EmotePatch.griddySpeed = ((BaseUnityPlugin)this).Config.Bind("Emote Settings", "Griddy Speed", 0.5f, "Speed of griddy relative to regular speed").Value; EmotePatch.emoteCooldown = ((BaseUnityPlugin)this).Config.Bind("Emote Settings", "Cooldown", 0.5f, "Time (in seconds) to wait before being able to switch emotes").Value; EmotePatch.stopOnOuter = ((BaseUnityPlugin)this).Config.Bind("Emote Settings", "Stop on outer", false, "Whether or not to stop emoting when mousing to outside the emote wheel").Value; } } internal class SelectionWheel : MonoBehaviour { public RectTransform selectionBlock; public bool stopEmote; public Text emoteInformation; public Text pageInformation; private int blocksNumber = 8; private int currentBlock = 1; public int pageNumber; public int selectedEmoteID; private float angle; private float pageCooldown = 0.1f; public GameObject[] Pages; public string selectedEmoteName; public float wheelMovementOffset = 3.3f; public static string[] emoteNames; public static string[] emoteKeybinds; private Vector2 center; private void OnEnable() { //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_025a: Unknown result type (might be due to invalid IL or missing references) center = new Vector2((float)(Screen.width / 2), (float)(Screen.height / 2)); PlayerInput component = GameObject.Find("PlayerSettingsObject").GetComponent(); emoteKeybinds = new string[Enum.GetNames(typeof(EmotePatch.Emotes)).Length + 1]; emoteKeybinds[0] = InputActionRebindingExtensions.GetBindingDisplayString(component.currentActionMap.FindAction("Emote1", false), 0, (DisplayStringOptions)0); emoteKeybinds[1] = InputActionRebindingExtensions.GetBindingDisplayString(component.currentActionMap.FindAction("Emote2", false), 0, (DisplayStringOptions)0); emoteKeybinds[2] = InputActionRebindingExtensions.GetBindingDisplayString(EmotePatch.keybinds.MiddleFinger, (DisplayStringOptions)0, (string)null); emoteKeybinds[3] = InputActionRebindingExtensions.GetBindingDisplayString(EmotePatch.keybinds.Clap, (DisplayStringOptions)0, (string)null); emoteKeybinds[4] = InputActionRebindingExtensions.GetBindingDisplayString(EmotePatch.keybinds.Shy, (DisplayStringOptions)0, (string)null); emoteKeybinds[5] = InputActionRebindingExtensions.GetBindingDisplayString(EmotePatch.keybinds.Griddy, (DisplayStringOptions)0, (string)null); emoteKeybinds[7] = InputActionRebindingExtensions.GetBindingDisplayString(EmotePatch.keybinds.Salute, (DisplayStringOptions)0, (string)null); emoteKeybinds[6] = InputActionRebindingExtensions.GetBindingDisplayString(EmotePatch.keybinds.Twerk, (DisplayStringOptions)0, (string)null); Cursor.visible = true; selectionBlock = ((Component)((Component)this).gameObject.transform.Find("SelectedEmote")).gameObject.GetComponent(); ((Component)selectionBlock).gameObject.SetActive(false); GameObject gameObject = ((Component)((Component)this).gameObject.transform.Find("FunctionalContent")).gameObject; emoteInformation = ((Component)((Component)((Component)this).gameObject.transform.Find("Graphics")).gameObject.transform.Find("EmoteInfo")).GetComponent(); Pages = (GameObject[])(object)new GameObject[gameObject.transform.childCount]; pageInformation = ((Component)((Component)((Component)this).gameObject.transform.Find("Graphics")).gameObject.transform.Find("PageNumber")).GetComponent(); pageInformation.text = "Page " + Pages.Length + "/" + (pageNumber + 1); for (int i = 0; i < gameObject.transform.childCount; i++) { Pages[i] = ((Component)gameObject.transform.GetChild(i)).gameObject; } Mouse.current.WarpCursorPosition(center); } private void Update() { wheelSelection(); pageSelection(); if (((Component)selectionBlock).gameObject.activeSelf) { selectedEmoteID = currentBlock + Mathf.RoundToInt((float)(blocksNumber / 4)) + blocksNumber * pageNumber; } else { selectedEmoteID = emoteNames.Length + 2; } displayEmoteInfo(); } private void wheelSelection() { //IL_0001: 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_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) if (!(Vector2.Distance(center, ((InputControl)(object)((Pointer)Mouse.current).position).ReadValue()) >= wheelMovementOffset)) { return; } Math.Abs(((InputControl)(object)((Pointer)Mouse.current).position.x).ReadValue() - center.x); Math.Abs(((InputControl)(object)((Pointer)Mouse.current).position.y).ReadValue() - center.y); float num = 235f; float num2 = 470f; bool num3 = Math.Pow(((InputControl)(object)((Pointer)Mouse.current).position.x).ReadValue() - center.x, 2.0) + Math.Pow(((InputControl)(object)((Pointer)Mouse.current).position.y).ReadValue() - center.y, 2.0) < Math.Pow(num, 2.0); bool flag = Math.Pow(((InputControl)(object)((Pointer)Mouse.current).position.x).ReadValue() - center.x, 2.0) + Math.Pow(((InputControl)(object)((Pointer)Mouse.current).position.y).ReadValue() - center.y, 2.0) >= Math.Pow(num2, 2.0); bool num4 = ((InputControl)(object)((Pointer)Mouse.current).position.x).ReadValue() > center.x; bool flag2 = ((InputControl)(object)((Pointer)Mouse.current).position.y).ReadValue() > center.y; int num5 = ((!num4) ? (flag2 ? 2 : 3) : (flag2 ? 1 : 4)); float num6 = (((InputControl)(object)((Pointer)Mouse.current).position.y).ReadValue() - center.y) / (((InputControl)(object)((Pointer)Mouse.current).position.x).ReadValue() - center.x); float num7 = 180 * (num5 - ((num5 <= 2) ? 1 : 2)); angle = Mathf.Atan(num6) * (180f / MathF.PI) + num7; if (angle == 90f) { angle = 270f; } else if (angle == 270f) { angle = 90f; } float num8 = 360 / blocksNumber; currentBlock = Mathf.RoundToInt((angle - num8 * 1.5f) / num8); if (num3) { ((Component)selectionBlock).gameObject.SetActive(false); return; } ((Component)selectionBlock).gameObject.SetActive(true); ((Transform)selectionBlock).localRotation = Quaternion.Euler(((Component)this).transform.rotation.z, ((Component)this).transform.rotation.y, num8 * (float)currentBlock); if (flag) { if (EmotePatch.stopOnOuter) { ((Component)selectionBlock).gameObject.SetActive(false); stopEmote = true; } else { stopEmote = false; } } } private void pageSelection() { pageInformation.text = "Page " + Pages.Length + "/" + (pageNumber + 1); if (pageCooldown > 0f) { pageCooldown -= Time.deltaTime; } else if (((InputControl)(object)((Vector2Control)Mouse.current.scroll).y).ReadValue() != 0f) { GameObject[] pages = Pages; for (int i = 0; i < pages.Length; i++) { pages[i].SetActive(false); } int num = ((((InputControl)(object)((Vector2Control)Mouse.current.scroll).y).ReadValue() > 0f) ? 1 : (-1)); if (pageNumber + 1 > Pages.Length - 1 && num > 0) { pageNumber = 0; } else if (pageNumber - 1 < 0 && num < 0) { pageNumber = Pages.Length - 1; } else { pageNumber += num; } Pages[pageNumber].SetActive(true); pageCooldown = 0.1f; } } private void displayEmoteInfo() { string text = ((selectedEmoteID > emoteKeybinds.Length) ? "" : emoteKeybinds[selectedEmoteID - 1]); string text2; if (selectedEmoteID <= Enum.GetValues(typeof(EmotePatch.Emotes)).Length) { EmotePatch.Emotes emotes = (EmotePatch.Emotes)selectedEmoteID; text2 = emotes.ToString().Replace("_", " "); } else { text2 = "EMPTY"; } emoteInformation.text = text2 + "\n[" + text.ToUpper() + "]"; } } public static class PluginInfo { public const string PLUGIN_GUID = "BetterEmotes"; public const string PLUGIN_NAME = "BetterEmotes"; public const string PLUGIN_VERSION = "1.1.1"; } }