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 BetterEmotes v1.5.8
BetterEmotes.dll
Decompiled 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; 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 BetterEmote.AssetScripts; using BetterEmote.Compatibility; using BetterEmote.Netcode; using BetterEmote.Patches; using BetterEmote.Utils; using GameNetcodeStuff; using HarmonyLib; using LCVR; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using RuntimeNetcodeRPCValidator; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Animations.Rigging; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; 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: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("BetterEmotes")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Alters the integration method of more emotes")] [assembly: AssemblyFileVersion("1.5.8.0")] [assembly: AssemblyInformationalVersion("1.5.8+3651111eaf27e85ca12bdb9f4c1b8e0d36df7e6a")] [assembly: AssemblyProduct("BetterEmotes")] [assembly: AssemblyTitle("BetterEmotes")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.8.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 { [BepInPlugin("BetterEmotes", "BetterEmotes", "1.5.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private static readonly string AssetPath = "Assets/MoreEmotes"; public static ManualLogSource Logger; public static Dictionary<string, long> lastLog = new Dictionary<string, long>(); private void Awake() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0045: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) //IL_009a: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"BetterEmotes loading..."); loadAssetBundles(); Settings.LoadFromConfig(((BaseUnityPlugin)this).Config); Settings.Keybinds = new Keybinds(); Harmony val = new Harmony("BetterEmotes"); Patcher.patchCompat(val); val.PatchAll(typeof(EmotePatch)); val.PatchAll(typeof(SignChatPatch)); val.PatchAll(typeof(RoundPatch)); val.PatchAll(typeof(EmoteKeybindPatch)); NetcodeValidator val2 = new NetcodeValidator("BetterEmotes"); val2.PatchAll(); val2.BindToPreExistingObjectByBehaviour<SyncVRState, PlayerControllerB>(); val2.BindToPreExistingObjectByBehaviour<SignEmoteText, PlayerControllerB>(); val2.BindToPreExistingObjectByBehaviour<SyncAnimatorToOthers, PlayerControllerB>(); Logger.LogInfo((object)"BetterEmotes loaded"); } private void loadAssetBundles() { string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "BetterEmotes"); string text = Path.Combine(path, "animatorbundle"); string text2 = Path.Combine(path, "animationsbundle"); try { loadAnimatorControllers(AssetBundle.LoadFromFile(text)); loadAnimationObjects(AssetBundle.LoadFromFile(text2)); } catch (Exception ex) { Logger.LogError((object)("Failed to load AssetBundles. Make sure \"animatorsbundle\" and \"animationsbundle\" are inside the MoreEmotes folder.\nError: " + ex.Message)); } } private void loadAnimatorControllers(AssetBundle bundle) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown EmotePatch.local = (RuntimeAnimatorController)new AnimatorOverrideController(bundle.LoadAsset<RuntimeAnimatorController>(Path.Combine(AssetPath, "NEWmetarig.controller"))); EmotePatch.others = (RuntimeAnimatorController)new AnimatorOverrideController(bundle.LoadAsset<RuntimeAnimatorController>(Path.Combine(AssetPath, "NEWmetarigOtherPlayers.controller"))); } private void loadAnimationObjects(AssetBundle bundle) { CustomAudioAnimationEvent.claps[0] = bundle.LoadAsset<AudioClip>(Path.Combine(AssetPath, "SingleClapEmote1.wav")); CustomAudioAnimationEvent.claps[1] = bundle.LoadAsset<AudioClip>(Path.Combine(AssetPath, "SingleClapEmote2.wav")); LocalPlayer.LegsPrefab = bundle.LoadAsset<GameObject>(Path.Combine(AssetPath, "Resources/plegs.prefab")); LocalPlayer.SignPrefab = bundle.LoadAsset<GameObject>(Path.Combine(AssetPath, "Resources/Sign.prefab")); LocalPlayer.SignUIPrefab = bundle.LoadAsset<GameObject>(Path.Combine(AssetPath, "Resources/SignTextUI.prefab")); EmoteKeybindPatch.WheelPrefab = bundle.LoadAsset<GameObject>(Path.Combine(AssetPath, "Resources/MoreEmotesMenu.prefab")); } public static void Debug(string message) { if (Settings.Debug) { Logger.LogDebug((object)("[DEBUG] " + message)); } } public static void Trace(string message) { if (!Settings.Trace) { return; } long num = DateTimeOffset.Now.ToUnixTimeMilliseconds(); if (lastLog.ContainsKey(message)) { long num2 = lastLog[message]; if ((float)(num - num2) > Settings.LogDelay * 1000f) { Logger.LogDebug((object)("[TRACE] " + message)); lastLog[message] = num; } } else { Logger.LogDebug((object)("[TRACE] " + message)); lastLog.Add(message, num); } } } public static class PluginInfo { public const string PLUGIN_GUID = "BetterEmotes"; public const string PLUGIN_NAME = "BetterEmotes"; public const string PLUGIN_VERSION = "1.5.8"; } } namespace BetterEmote.Utils { public enum Emote { Dance = 1, Point, Middle_Finger, Clap, Shy, Griddy, Twerk, Salute, Prisyadka, Sign } public enum DoubleEmote { Double_Clap = 1004, Double_Middle_Finger = 1003 } public enum AltEmote { Sign_Text = 1010 } internal class EmoteDefs { public static int getEmoteNumber(Emote emote) { return (int)emote; } public static int getEmoteNumber(DoubleEmote emote) { return (int)emote; } public static int getEmoteNumber(AltEmote emote) { return (int)emote; } public static int getEmoteNumber(string name) { return (int)Enum.Parse(typeof(Emote), name); } public static Emote getEmote(string name) { try { return (Emote)Enum.Parse(typeof(Emote), name); } catch (Exception) { try { return (DoubleEmote)Enum.Parse(typeof(DoubleEmote), name) switch { DoubleEmote.Double_Middle_Finger => Emote.Middle_Finger, DoubleEmote.Double_Clap => Emote.Clap, _ => Emote.Dance, }; } catch (Exception) { if ((AltEmote)Enum.Parse(typeof(AltEmote), name) == AltEmote.Sign_Text) { return Emote.Sign; } return Emote.Dance; } } } public static DoubleEmote getDoubleEmote(string name) { return (DoubleEmote)Enum.Parse(typeof(DoubleEmote), name); } public static AltEmote getAltEmote(string name) { return (AltEmote)Enum.Parse(typeof(AltEmote), name); } public static int getEmoteCount() { return Enum.GetNames(typeof(Emote)).Length; } public static int normalizeEmoteNumber(int number) { if (number >= 1000) { number -= 1000; } return number; } } internal class GameValues { public static PlayerControllerB localPlayerController { get { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.localPlayerController; } } public static bool localPlayerUsingController { get { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null)) { return false; } return instance.localPlayerUsingController; } } } public class Keybinds : LcInputActions { public InputAction MiddleFinger => ((LcInputActions)this).Asset["Middle_Finger"]; public InputAction Clap => ((LcInputActions)this).Asset["Clap"]; public InputAction Shy => ((LcInputActions)this).Asset["Shy"]; public InputAction Griddy => ((LcInputActions)this).Asset["Griddy"]; public InputAction Twerk => ((LcInputActions)this).Asset["Twerk"]; public InputAction Salute => ((LcInputActions)this).Asset["Salute"]; public InputAction Prisyadka => ((LcInputActions)this).Asset["Prisyadka"]; public InputAction Sign => ((LcInputActions)this).Asset["Sign"]; public InputAction SignSubmit => ((LcInputActions)this).Asset["SignSubmit"]; public InputAction SignCancel => ((LcInputActions)this).Asset["SignCancel"]; public InputAction EmoteWheel => ((LcInputActions)this).Asset["EmoteWheel"]; public InputAction EmoteWheelNextPage => ((LcInputActions)this).Asset["EmoteWheelNextPage"]; public InputAction EmoteWheelPreviousPage => ((LcInputActions)this).Asset["EmoteWheelPreviousPage"]; public InputAction EmoteWheelController => ((LcInputActions)this).Asset["EmoteWheelController"]; public override void CreateInputActions(in InputActionMapBuilder builder) { ((LcInputActions)this).CreateInputActions(ref builder); if (Settings.DefaultInputList.Length != 0) { string[] names = Enum.GetNames(typeof(Emote)); foreach (string text in names) { if (EmoteDefs.getEmoteNumber(text) > 2) { builder.NewActionBinding().WithActionId(text).WithActionType((InputActionType)1) .WithKbmPath(Settings.DefaultInputList[EmoteDefs.getEmoteNumber(text)].keyboard) .WithBindingName(text) .WithGamepadPath(Settings.DefaultInputList[EmoteDefs.getEmoteNumber(text)].controller) .Finish(); } } } builder.NewActionBinding().WithActionId("SignSubmit").WithActionType((InputActionType)1) .WithKbmPath(Settings.SignSubmitInput.keyboard) .WithGamepadPath(Settings.SignSubmitInput.controller) .WithBindingName("Sign Submit") .Finish(); builder.NewActionBinding().WithActionId("SignCancel").WithActionType((InputActionType)1) .WithKbmPath(Settings.SignCancelInput.keyboard) .WithGamepadPath(Settings.SignCancelInput.controller) .WithBindingName("Sign Cancel") .Finish(); builder.NewActionBinding().WithActionId("EmoteWheel").WithActionType((InputActionType)1) .WithKbmPath(Settings.EmoteWheelInput.keyboard) .WithGamepadPath(Settings.EmoteWheelInput.controller) .WithBindingName("Emote Wheel") .Finish(); builder.NewActionBinding().WithActionId("EmoteWheelNextPage").WithActionType((InputActionType)1) .WithKbmPath(Settings.EmoteWheelNextInput.keyboard) .WithGamepadPath(Settings.EmoteWheelNextInput.controller) .WithBindingName("Emote Wheel Next Page") .Finish(); builder.NewActionBinding().WithActionId("EmoteWheelPreviousPage").WithActionType((InputActionType)1) .WithKbmPath(Settings.EmoteWheelPreviousInput.keyboard) .WithGamepadPath(Settings.EmoteWheelPreviousInput.controller) .WithBindingName("Emote Wheel Previous Page") .Finish(); builder.NewActionBinding().WithActionId("EmoteWheelController").WithActionType((InputActionType)0) .WithGamepadPath(Settings.EmoteWheelMoveInput.controller) .WithBindingName("Emote Wheel Selector") .Finish(); } public static InputBind getDisplayStrings(InputAction action) { Plugin.Debug("getDisplayStrings()"); return new InputBind(InputActionRebindingExtensions.GetBindingDisplayString(action, 0, (DisplayStringOptions)0) ?? "", (InputActionRebindingExtensions.GetBindingDisplayString(action, 1, (DisplayStringOptions)0) ?? "").Replace("Left Stick", "LS").Replace("Right Stick", "RS")); } public static string formatInputBind(InputBind bind) { Plugin.Trace("formatInputBind()"); if ((bind.keyboard == null || bind.keyboard == "") && (bind.controller == null || bind.controller == "")) { return ""; } if (bind.keyboard == null || bind.keyboard == "") { return "[" + bind.controller + "]"; } if (bind.controller == null || bind.controller == "") { return "[" + bind.keyboard + "]"; } return "[" + bind.keyboard + "/" + bind.controller + "]"; } public InputAction getByEmote(Emote emote) { PlayerInput component = GameObject.Find("PlayerSettingsObject").GetComponent<PlayerInput>(); return (InputAction)(emote switch { Emote.Middle_Finger => MiddleFinger, Emote.Clap => Clap, Emote.Shy => Shy, Emote.Griddy => Griddy, Emote.Twerk => Twerk, Emote.Salute => Salute, Emote.Prisyadka => Prisyadka, Emote.Sign => Sign, Emote.Dance => component.currentActionMap.FindAction("Emote1", false), Emote.Point => component.currentActionMap.FindAction("Emote2", false), _ => throw new Exception("Attempted to get input of unknown emote"), }); } } public class Settings { private static readonly string KeyLabel = "Emote Keys"; private static readonly string EnabledLabel = "Enabled Emotes"; private static readonly string ControllerLabel = "Emote Controller Bindings"; private static readonly string EmoteSettingsLabel = "Emote Settings"; private static readonly string DebugSettingsLabel = "Debug Settings"; public static bool Debug = false; public static bool Trace = false; public static Keybinds Keybinds; public static bool StopOnOuter = false; public static bool[] EnabledList = Array.Empty<bool>(); public static InputBind[] DefaultInputList = Array.Empty<InputBind>(); public static InputBind EmoteWheelInput = new InputBind("<Keyboard>/v", "<Gamepad>/leftShoulder"); public static InputBind EmoteWheelNextInput = new InputBind("<Mouse>/scroll/up", "<Gamepad>/dpad/right"); public static InputBind EmoteWheelPreviousInput = new InputBind("<Mouse>/scroll/down", "<Gamepad>/dpad/left"); public static InputBind EmoteWheelMoveInput = new InputBind("", "<Gamepad>/rightStick"); public static InputBind SignSubmitInput = new InputBind("<Keyboard>/enter", "<Gamepad>/buttonWest"); public static InputBind SignCancelInput = new InputBind("<Mouse>/rightButton", "<Gamepad>/buttonEast"); public static float GriddySpeed = 0.5f; public static float PrisyadkaSpeed = 0.34f; public static float EmoteCooldown = 0.2f; public static float SignTextCooldown = 0.1f; public static bool DisableSpeedChange = false; public static bool DisableModelOverride = false; public static float ControllerDeadzone = 0.25f; public static float LogDelay = 1f; public static void DebugAllSettings() { Plugin.Debug($"Debug: {Debug}"); Plugin.Debug($"Trace: {Trace}"); Plugin.Debug($"StopOnOuter: {StopOnOuter}"); Plugin.Debug("EnabledList: " + string.Join(", ", EnabledList)); Plugin.Debug("DefaultInputList: " + string.Join(", ", DefaultInputList)); Plugin.Debug($"EmoteWheelInput: {EmoteWheelInput}"); Plugin.Debug($"EmoteWheelNextInput: {EmoteWheelNextInput}"); Plugin.Debug($"EmoteWheelPreviousInput: {EmoteWheelPreviousInput}"); Plugin.Debug($"EmoteWheelMoveInput: {EmoteWheelMoveInput}"); Plugin.Debug($"SignSubmitInput: {SignSubmitInput}"); Plugin.Debug($"SignCancelInput: {SignCancelInput}"); Plugin.Debug($"GriddySpeed: {GriddySpeed}"); Plugin.Debug($"PrisyadkaSpeed: {PrisyadkaSpeed}"); Plugin.Debug($"EmoteCooldown: {EmoteCooldown}"); Plugin.Debug($"SignTextCooldown: {SignTextCooldown}"); Plugin.Debug($"DisableSpeedChange: {DisableSpeedChange}"); Plugin.Debug($"DisableModelOverride: {DisableModelOverride}"); Plugin.Debug($"ControllerDeadzone: {ControllerDeadzone}"); Plugin.Debug($"LogDelay: {LogDelay}"); } public static float ValidateGreaterThanEqualToZero(float value) { if (!(value < 0f)) { return value; } return 0f; } public static string ValidatePrefix(string prefix, string value) { return ValidatePrefixes(new string[1] { prefix }, prefix, value); } public static string ValidatePrefixes(string[] prefixes, string defaultPrefix, string value) { if (value.Equals("")) { return ""; } foreach (string text in prefixes) { if (value.ToLower().StartsWith(text.ToLower())) { return value; } } return defaultPrefix + "/" + value; } public static void LoadFromConfig(ConfigFile config) { EnabledList = new bool[EmoteDefs.getEmoteCount() + 1]; DefaultInputList = new InputBind[EmoteDefs.getEmoteCount() + 1]; string[] names = Enum.GetNames(typeof(Emote)); foreach (string text in names) { if (EmoteDefs.getEmoteNumber(text) > 2) { string keyboard = ""; int emoteNumber = EmoteDefs.getEmoteNumber(text); if (emoteNumber <= 10) { keyboard = $"<Keyboard>/{emoteNumber % 10}"; } DefaultInputList[emoteNumber] = GetFromConfig(config, new InputBind(keyboard, ""), text, text + " emote"); } EnabledList[EmoteDefs.getEmoteNumber(text)] = config.Bind<bool>(EnabledLabel, "Enable " + text, true, "Toggle " + text + " emote key").Value; } SignSubmitInput = GetFromConfig(config, SignSubmitInput, "Sign Submit", "sign submit"); SignCancelInput = GetFromConfig(config, SignCancelInput, "Sign Cancel", "sign cancel"); EmoteWheelInput = GetFromConfig(config, EmoteWheelInput, "Emote Wheel", "emote wheel"); EmoteWheelNextInput = GetFromConfig(config, EmoteWheelNextInput, "Emote Wheel Next Page", "emote wheel next page"); EmoteWheelPreviousInput = GetFromConfig(config, EmoteWheelPreviousInput, "Emote Wheel Previous Page", "emote wheel next page"); EmoteWheelMoveInput.controller = ValidatePrefix("<Gamepad>", config.Bind<string>(ControllerLabel, "Emote Wheel Move", EmoteWheelMoveInput.controller, "Default controller binding for the emote wheel movement").Value); ControllerDeadzone = ValidateGreaterThanEqualToZero(config.Bind<float>(ControllerLabel, "Emote Wheel Deadzone", ControllerDeadzone, "Default controller deadzone for emote selection").Value); GriddySpeed = ValidateGreaterThanEqualToZero(config.Bind<float>(EmoteSettingsLabel, "Griddy Speed", GriddySpeed, "Speed of griddy relative to regular speed").Value); PrisyadkaSpeed = ValidateGreaterThanEqualToZero(config.Bind<float>(EmoteSettingsLabel, "Prisyadka Speed", PrisyadkaSpeed, "Speed of Prisyadka relative to regular speed").Value); EmoteCooldown = ValidateGreaterThanEqualToZero(config.Bind<float>(EmoteSettingsLabel, "Cooldown", EmoteCooldown, "Time (in seconds) to wait before being able to switch emotes").Value); SignTextCooldown = ValidateGreaterThanEqualToZero(config.Bind<float>(EmoteSettingsLabel, "Sign Text Cooldown", SignTextCooldown, "Time (in seconds) to wait before being able to finish typing (was hard coded into MoreEmotes)").Value); StopOnOuter = config.Bind<bool>(EmoteSettingsLabel, "Stop on outer", StopOnOuter, "Whether or not to stop emoting when mousing to outside the emote wheel").Value; LogDelay = ValidateGreaterThanEqualToZero(config.Bind<float>(DebugSettingsLabel, "Trace Delay", LogDelay, "Time (in seconds) to wait before writing the same trace line, trace messages are very spammy").Value); Debug = config.Bind<bool>(DebugSettingsLabel, "Debug", Debug, "Whether or not to enable debug log messages, bepinex also needs to be configured to show debug logs").Value; Trace = config.Bind<bool>(DebugSettingsLabel, "Trace", Trace, "Whether or not to enable trace log messages, bepinex also needs to be configured to show debug logs").Value; DisableSpeedChange = config.Bind<bool>(DebugSettingsLabel, "Disable Speed Changed", DisableSpeedChange, "Whether or not to disable speed changes that might affect other mods").Value; DisableModelOverride = config.Bind<bool>(DebugSettingsLabel, "Disable Self Emote", DisableModelOverride, "Whether or not to disable overriding the player model, can help with conflicting mods").Value; } private static InputBind GetFromConfig(ConfigFile config, InputBind defaultBind, string name, string description) { return new InputBind(ValidatePrefixes(new string[2] { "<Keyboard>", "<Mouse>" }, "<Keyboard>", config.Bind<string>(KeyLabel, name + " Key", defaultBind.keyboard, "Default keybind for the " + description).Value), ValidatePrefix("<Gamepad>", config.Bind<string>(ControllerLabel, name + " Button", defaultBind.controller, "Default controller binding for the " + description).Value)); } } public struct InputBind { public string keyboard; public string controller; public InputBind(string keyboard, string controller) { this.keyboard = ""; this.controller = ""; this.keyboard = keyboard; this.controller = controller; } public override string ToString() { return "('" + keyboard + "', '" + controller + "')"; } } } namespace BetterEmote.Patches { internal class EmoteKeybindPatch { public static bool EmoteWheelIsOpened; private static EmoteWheel SelectionWheel; public static GameObject WheelPrefab; [HarmonyPatch(typeof(RoundManager), "Awake")] [HarmonyPostfix] private static void AwakePost(RoundManager __instance) { Plugin.Debug("EmoteKeybindPatch.AwakePost()"); GameObject gameObject = ((Component)((Component)GameObject.Find("Systems").gameObject.transform.Find("UI")).gameObject.transform.Find("Canvas")).gameObject; if ((Object)(object)WheelPrefab != (Object)null) { SelectionWheel = Object.Instantiate<GameObject>(WheelPrefab, gameObject.transform).AddComponent<EmoteWheel>(); } } [HarmonyPatch(typeof(PlayerControllerB), "Start")] [HarmonyPostfix] private static void StartPostfix(PlayerControllerB __instance) { Plugin.Debug("EmoteKeybindPatch.StartPostfix()"); if (Settings.Keybinds != null && !Settings.DisableModelOverride) { Settings.Keybinds.MiddleFinger.performed += onEmoteKeyMiddleFinger; Settings.Keybinds.Griddy.performed += onEmoteKeyGriddy; Settings.Keybinds.Shy.performed += onEmoteKeyShy; Settings.Keybinds.Clap.performed += onEmoteKeyClap; Settings.Keybinds.Salute.performed += onEmoteKeySalute; Settings.Keybinds.Prisyadka.performed += onEmoteKeyPrisyadka; Settings.Keybinds.Sign.performed += onEmoteKeySign; Settings.Keybinds.Twerk.performed += onEmoteKeyTwerk; Settings.Keybinds.SignSubmit.performed += onSignKeySubmit; Settings.Keybinds.SignCancel.performed += onSignKeyCancel; Settings.Keybinds.EmoteWheel.started += onEmoteKeyWheelStarted; Settings.Keybinds.EmoteWheel.canceled += onEmoteKeyWheelCanceled; Settings.Keybinds.EmoteWheelNextPage.performed += onEmoteKeyWheelNext; Settings.Keybinds.EmoteWheelPreviousPage.performed += onEmoteKeyWheelPrevious; Settings.Keybinds.MiddleFinger.Enable(); Settings.Keybinds.Griddy.Enable(); Settings.Keybinds.Shy.Enable(); Settings.Keybinds.Clap.Enable(); Settings.Keybinds.Salute.Enable(); Settings.Keybinds.Prisyadka.Enable(); Settings.Keybinds.Sign.Enable(); Settings.Keybinds.Twerk.Enable(); Settings.Keybinds.SignSubmit.Enable(); Settings.Keybinds.SignCancel.Enable(); Settings.Keybinds.EmoteWheel.Enable(); Settings.Keybinds.EmoteWheelNextPage.Enable(); Settings.Keybinds.EmoteWheelPreviousPage.Enable(); } } [HarmonyPatch(typeof(PlayerControllerB), "OnDisable")] [HarmonyPostfix] public static void OnDisablePostfix(PlayerControllerB __instance) { Plugin.Debug("EmoteKeybindPatch.OnDisablePostfix()"); if (Settings.Keybinds != null && (Object)(object)__instance == (Object)(object)GameValues.localPlayerController) { Settings.Keybinds.MiddleFinger.performed -= onEmoteKeyMiddleFinger; Settings.Keybinds.Griddy.performed -= onEmoteKeyGriddy; Settings.Keybinds.Shy.performed -= onEmoteKeyShy; Settings.Keybinds.Clap.performed -= onEmoteKeyClap; Settings.Keybinds.Salute.performed -= onEmoteKeySalute; Settings.Keybinds.Prisyadka.performed -= onEmoteKeyPrisyadka; Settings.Keybinds.Sign.performed -= onEmoteKeySign; Settings.Keybinds.Twerk.performed -= onEmoteKeyTwerk; Settings.Keybinds.SignSubmit.performed -= onSignKeySubmit; Settings.Keybinds.SignCancel.performed -= onSignKeyCancel; Settings.Keybinds.EmoteWheel.started -= onEmoteKeyWheelStarted; Settings.Keybinds.EmoteWheel.canceled -= onEmoteKeyWheelCanceled; Settings.Keybinds.EmoteWheelNextPage.performed -= onEmoteKeyWheelNext; Settings.Keybinds.EmoteWheelPreviousPage.performed -= onEmoteKeyWheelPrevious; Settings.Keybinds.MiddleFinger.Disable(); Settings.Keybinds.Griddy.Disable(); Settings.Keybinds.Shy.Disable(); Settings.Keybinds.Clap.Disable(); Settings.Keybinds.Salute.Disable(); Settings.Keybinds.Prisyadka.Disable(); Settings.Keybinds.Sign.Disable(); Settings.Keybinds.Twerk.Disable(); Settings.Keybinds.SignSubmit.Disable(); Settings.Keybinds.SignCancel.Disable(); Settings.Keybinds.EmoteWheel.Disable(); Settings.Keybinds.EmoteWheelNextPage.Disable(); Settings.Keybinds.EmoteWheelPreviousPage.Disable(); } } public static void onSignKeySubmit(CallbackContext context) { Plugin.Debug("onSignKeySubmit()"); if (((ButtonControl)Keyboard.current[(Key)52]).isPressed || ((ButtonControl)Keyboard.current[(Key)51]).isPressed) { Plugin.Debug("They have one of the shifts pressed"); } else if (!Settings.DisableModelOverride && (Object)(object)LocalPlayer.CustomSignInputField != (Object)null && LocalPlayer.CustomSignInputField.IsSignUIOpen) { LocalPlayer.CustomSignInputField.SubmitText(); } } public static void onSignKeyCancel(CallbackContext context) { Plugin.Debug("onSignKeyCancel()"); if (!Settings.DisableModelOverride && (Object)(object)LocalPlayer.CustomSignInputField != (Object)null && LocalPlayer.CustomSignInputField.IsSignUIOpen) { LocalPlayer.CustomSignInputField.Close(cancelAction: true); } } public static void onEmoteKeyWheelStarted(CallbackContext context) { Plugin.Debug("onEmoteKeyWheelStarted()"); if (EmoteWheelIsOpened || !((Object)(object)GameValues.localPlayerController != (Object)null) || GameValues.localPlayerController.isPlayerDead || GameValues.localPlayerController.inTerminalMenu || GameValues.localPlayerController.isTypingChat || GameValues.localPlayerController.quickMenuManager.isMenuOpen || (!((Object)(object)LocalPlayer.CustomSignInputField == (Object)null) && LocalPlayer.CustomSignInputField.IsSignUIOpen)) { return; } EmoteWheelIsOpened = true; Cursor.visible = true; Cursor.lockState = (CursorLockMode)2; EmoteWheel selectionWheel = SelectionWheel; if (selectionWheel != null) { GameObject gameObject = ((Component)selectionWheel).gameObject; if (gameObject != null) { gameObject.SetActive(EmoteWheelIsOpened); } } GameValues.localPlayerController.quickMenuManager.isMenuOpen = true; GameValues.localPlayerController.disableLookInput = true; } public static void onEmoteKeyWheelCanceled(CallbackContext context) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeyWheelCanceled()"); if (!EmoteWheelIsOpened || !((Object)(object)GameValues.localPlayerController != (Object)null) || !((Object)(object)SelectionWheel != (Object)null)) { return; } GameValues.localPlayerController.quickMenuManager.isMenuOpen = false; GameValues.localPlayerController.disableLookInput = false; if (SelectionWheel.selectedEmoteID >= Settings.EnabledList.Length) { if (SelectionWheel.stopEmote) { GameValues.localPlayerController.performingEmote = false; GameValues.localPlayerController.StopPerformingEmoteServerRpc(); GameValues.localPlayerController.timeSinceStartingEmote = 0f; } } else { CheckEmoteInput(context, Settings.EnabledList[SelectionWheel.selectedEmoteID], SelectionWheel.selectedEmoteID, GameValues.localPlayerController); } Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; EmoteWheelIsOpened = false; ((Component)SelectionWheel).gameObject.SetActive(EmoteWheelIsOpened); } public static void onEmoteKeyWheelNext(CallbackContext context) { Plugin.Debug("onEmoteKeyWheelNext()"); if (EmoteWheelIsOpened) { SelectionWheel?.alterPage(1); } } public static void onEmoteKeyWheelPrevious(CallbackContext context) { Plugin.Debug("onEmoteKeyWheelPrevious()"); if (EmoteWheelIsOpened) { SelectionWheel?.alterPage(-1); } } public static void onEmoteKeyMiddleFinger(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeyMiddleFinger()"); onEmoteKeyPerformed(context, Emote.Middle_Finger); } public static void onEmoteKeyGriddy(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeyGriddy()"); onEmoteKeyPerformed(context, Emote.Griddy); } public static void onEmoteKeyShy(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeyShy()"); onEmoteKeyPerformed(context, Emote.Shy); } public static void onEmoteKeyClap(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeyClap()"); onEmoteKeyPerformed(context, Emote.Clap); } public static void onEmoteKeySalute(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeySalute()"); onEmoteKeyPerformed(context, Emote.Salute); } public static void onEmoteKeyPrisyadka(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeyPrisyadka()"); onEmoteKeyPerformed(context, Emote.Prisyadka); } public static void onEmoteKeySign(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeySign()"); onEmoteKeyPerformed(context, Emote.Sign); } public static void onEmoteKeyTwerk(CallbackContext context) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("onEmoteKeyTwerk()"); onEmoteKeyPerformed(context, Emote.Twerk); } public static void onEmoteKeyPerformed(CallbackContext context, Emote emote) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) CheckEmoteInput(context, Settings.EnabledList[(int)emote], (int)emote, GameValues.localPlayerController); } private static void CheckEmoteInput(CallbackContext context, bool enabled, int emoteID, PlayerControllerB player) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug($"CheckEmoteInput({enabled}, {emoteID})"); if (enabled && (Object)(object)player != (Object)null && !player.isTypingChat) { player.PerformEmote(context, emoteID); } } } internal class EmotePatch { public static AssetBundle animationsBundle; public static AssetBundle animatorBundle; public static RuntimeAnimatorController local; public static RuntimeAnimatorController others; public static bool[] playersPerformingEmotes = new bool[40]; private static SyncAnimatorToOthers syncAnimator; public static SyncVRState syncVR; [HarmonyPatch(typeof(PlayerControllerB), "Start")] [HarmonyPostfix] [HarmonyPriority(200)] private static void StartPostfix(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { Plugin.Debug("EmotePatch.StartPostfix()"); ((Component)((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel")).transform.Find("metarig")).gameObject.AddComponent<CustomAudioAnimationEvent>().player = __instance; LocalPlayer.BaseSpeed = __instance.movementSpeed; ((Component)__instance).gameObject.AddComponent<CustomAnimationObjects>(); LocalPlayer.SpawnSign(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void ConnectClientToPlayerObjectPostfix(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { Plugin.Debug("EmotePatch.ConnectClientToPlayerObjectPostfix()"); if ((Object)(object)syncVR != (Object)null) { syncVR.RequestVRStateFromOthers(); syncVR.UpdateVRStateForOthers(Settings.DisableModelOverride); } } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPrefix] [HarmonyPriority(200)] private static void UpdatePrefix(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { Plugin.Trace("PlayerControllerB.UpdatePrefix()"); if (__instance.performingEmote) { playersPerformingEmotes[__instance.playerClientId] = true; } else if (playersPerformingEmotes[__instance.playerClientId]) { playersPerformingEmotes[__instance.playerClientId] = false; ResetIKWeights(__instance); } } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void UpdatePostfix(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null) { return; } Plugin.Trace("PlayerControllerB.UpdatePostfix()"); if (!__instance.isPlayerControlled || !((NetworkBehaviour)__instance).IsOwner) { if ((Object)(object)syncVR != (Object)null && SyncVRState.vrPlayers.ContainsKey(__instance.playerClientId) && !SyncVRState.vrPlayers[__instance.playerClientId]) { __instance.playerBodyAnimator.runtimeAnimatorController = others; } return; } if ((Object)(object)__instance.playerBodyAnimator != (Object)(object)local) { if (LocalPlayer.IsPlayerFirstFrame && !Settings.DisableModelOverride) { LocalPlayer.SpawnLegs(__instance); } if (!Settings.DisableModelOverride) { __instance.playerBodyAnimator.runtimeAnimatorController = local; } if (LocalPlayer.IsPlayerFirstFrame) { Plugin.Debug("isPlayerFirstFrame"); syncVR = ((Component)__instance).GetComponent<SyncVRState>(); syncAnimator = ((Component)__instance).GetComponent<SyncAnimatorToOthers>(); LocalPlayer.IsPlayerFirstFrame = false; if (!Settings.DisableModelOverride) { LocalPlayer.OnFirstLocalPlayerFrameWithNewAnimator(__instance); } if ((Object)(object)syncVR != (Object)null) { syncVR.RequestVRStateFromOthers(); syncVR.UpdateVRStateForOthers(Settings.DisableModelOverride); } Plugin.Debug("SpawnPlayerAnimation"); __instance.SpawnPlayerAnimation(); } } if (!Settings.DisableSpeedChange) { __instance.movementSpeed = LocalPlayer.BaseSpeed; if (__instance.CheckConditionsForEmote() && __instance.performingEmote) { if (LocalPlayer.CurrentEmoteID == EmoteDefs.getEmoteNumber(Emote.Griddy)) { __instance.movementSpeed = LocalPlayer.BaseSpeed * Settings.GriddySpeed; } else if (LocalPlayer.CurrentEmoteID == EmoteDefs.getEmoteNumber(Emote.Prisyadka)) { __instance.movementSpeed = LocalPlayer.BaseSpeed * Settings.PrisyadkaSpeed; } } } if (!Settings.DisableModelOverride) { __instance.localArmsRotationTarget = (LocalPlayer.IsArmsSeparatedFromCamera ? LocalPlayer.freeArmsTarget : LocalPlayer.lockedArmsTarget); } } private static void ResetIKWeights(PlayerControllerB player) { Plugin.Debug("ResetIKWeights()"); object obj; if (player == null) { obj = null; } else { Animator playerBodyAnimator = player.playerBodyAnimator; if (playerBodyAnimator == null) { obj = null; } else { Transform transform3 = ((Component)playerBodyAnimator).transform; obj = ((transform3 != null) ? transform3.Find("Rig 1") : null); } } Transform transform = (Transform)obj; if ((Object)(object)transform != (Object)null) { try { string[] source = new string[2] { "RightArm", "LeftArm" }; string[] source2 = new string[2] { "RightLeg", "LeftLeg" }; source.ToList().ForEach(delegate(string name) { ((RigConstraint<ChainIKConstraintJob, ChainIKConstraintData, ChainIKConstraintJobBinder<ChainIKConstraintData>>)(object)((Component)transform.Find(name)).GetComponent<ChainIKConstraint>()).weight = 1f; }); source2.ToList().ForEach(delegate(string name) { ((RigConstraint<TwoBoneIKConstraintJob, TwoBoneIKConstraintData, TwoBoneIKConstraintJobBinder<TwoBoneIKConstraintData>>)(object)((Component)transform.Find(name)).GetComponent<TwoBoneIKConstraint>()).weight = 1f; }); Transform transform2 = ((Component)player.playerBodyAnimator).transform.Find("ScavengerModelArmsOnly").Find("metarig").Find("spine.003") .Find("RigArms"); source.ToList().ForEach(delegate(string name) { ((RigConstraint<ChainIKConstraintJob, ChainIKConstraintData, ChainIKConstraintJobBinder<ChainIKConstraintData>>)(object)((Component)transform2.Find(name)).GetComponent<ChainIKConstraint>()).weight = 1f; }); return; } catch (NullReferenceException) { Plugin.Logger.LogWarning((object)"Unable to reset IK weights, if this is spammed please report it"); return; } } Plugin.Debug("ResetIKWeights transform is null"); } [HarmonyPatch(typeof(PlayerControllerB), "PerformEmote")] [HarmonyPrefix] private static bool PerformEmotePrefix(ref CallbackContext context, int emoteID, PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null) { return true; } Plugin.Debug($"PerformEmotePrefix({emoteID})"); int localEmoteID = emoteID; if (LocalPlayer.CheckIfTooManyEmotesIsPlaying(__instance) && localEmoteID > EmoteDefs.getEmoteNumber(Emote.Point)) { Plugin.Debug("Is custom emote with too many emotes currently playing"); return false; } if ((!((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject)) && !__instance.isTestingPlayer) { Plugin.Debug("Is player controllered or owner check failed"); return false; } if ((Object)(object)syncVR != (Object)null) { Plugin.Debug("syncVR not null, updating"); syncVR.RequestVRStateFromOthers(); syncVR.UpdateVRStateForOthers(Settings.DisableModelOverride); } if ((Object)(object)LocalPlayer.CustomSignInputField != (Object)null && LocalPlayer.CustomSignInputField.IsSignUIOpen && localEmoteID != EmoteDefs.getEmoteNumber(AltEmote.Sign_Text)) { Plugin.Debug("Sign UI is open, is this a sign?"); return false; } if (localEmoteID > 0 && localEmoteID <= EmoteDefs.getEmoteNumber(Emote.Point) && !EmoteKeybindPatch.EmoteWheelIsOpened && !((CallbackContext)(ref context)).performed) { Plugin.Debug("Normal emote with no emote wheel or context performed"); return false; } string[] names = Enum.GetNames(typeof(DoubleEmote)); foreach (string text in names) { Plugin.Debug("Checking double emote " + text); int emoteNumber = EmoteDefs.getEmoteNumber(EmoteDefs.getEmote(text)); bool flag = false; if (LocalPlayer.CurrentEmoteID == localEmoteID && localEmoteID >= EmoteDefs.getEmoteNumber(Emote.Point) && __instance.performingEmote && (!__instance.isHoldingObject || !flag)) { Plugin.Debug("Damn, emote ids match with all other checks"); if (localEmoteID == emoteNumber) { Plugin.Debug("Adding offset"); localEmoteID += 1000; } else if (localEmoteID > 1000) { Plugin.Debug("Removing offset"); localEmoteID -= 1000; } } } Plugin.Debug($"localEmoteID after: {localEmoteID}"); if ((localEmoteID != LocalPlayer.CurrentEmoteID && localEmoteID <= EmoteDefs.getEmoteNumber(Emote.Point)) || !__instance.performingEmote) { Plugin.Debug("Ressetting IKWeights because its not a custom emote"); ResetIKWeights(__instance); } Plugin.Trace($"__instance.inSpecialInteractAnimation: {__instance.inSpecialInteractAnimation}"); Plugin.Trace($"__instance.isPlayerDead: {__instance.isPlayerDead}"); Plugin.Trace($"__instance.isJumping: {__instance.isJumping}"); Plugin.Trace($"__instance.moveInputVector.x: {__instance.moveInputVector.x}"); Plugin.Trace($"__instance.isWalking: {__instance.isWalking}"); Plugin.Trace($"__instance.isSprinting: {__instance.isSprinting}"); Plugin.Trace($"__instance.isCrouching: {__instance.isCrouching}"); Plugin.Trace($"__instance.isClimbingLadder: {__instance.isClimbingLadder}"); Plugin.Trace($"__instance.isGrabbingObjectAnimation: {__instance.isGrabbingObjectAnimation}"); Plugin.Trace($"__instance.inTerminalMenu: {__instance.inTerminalMenu}"); Plugin.Trace($"__instance.isTypingChat: {__instance.isTypingChat}"); int currentEmoteID = LocalPlayer.CurrentEmoteID; LocalPlayer.CurrentEmoteID = localEmoteID; if (__instance.CheckConditionsForEmote()) { Plugin.Debug("Check conditions passed"); if (__instance.timeSinceStartingEmote >= Settings.EmoteCooldown) { Plugin.Debug("Time elapsed since last emote cooldown"); Action action = delegate { Plugin.Debug($"Starting emote {localEmoteID}"); __instance.timeSinceStartingEmote = 0f; __instance.playerBodyAnimator.SetInteger("emoteNumber", localEmoteID); __instance.performingEmote = true; __instance.StartPerformingEmoteServerRpc(); syncAnimator?.UpdateEmoteIDForOthers(localEmoteID); LocalPlayer.TogglePlayerBadges(enabled: false); }; if (localEmoteID == EmoteDefs.getEmoteNumber(Emote.Prisyadka) && !Settings.DisableModelOverride) { Plugin.Debug("Adding UpdateLegsMaterial for Prisyadka"); action = (Action)Delegate.Combine(action, (Action)delegate { LocalPlayer.UpdateLegsMaterial(__instance); }); } else if (localEmoteID == EmoteDefs.getEmoteNumber(Emote.Sign) && !Settings.DisableModelOverride) { Plugin.Debug("Adding customSignInputField setActive for Sign"); action = (Action)Delegate.Combine(action, (Action)delegate { ((Component)LocalPlayer.CustomSignInputField).gameObject.SetActive(true); }); } action(); return false; } LocalPlayer.CurrentEmoteID = currentEmoteID; Plugin.Debug("Emote cooldown still in effect, try again soon"); return false; } LocalPlayer.CurrentEmoteID = currentEmoteID; Plugin.Debug("Check confitions failed"); return false; } [HarmonyPatch(typeof(PlayerControllerB), "CheckConditionsForEmote")] [HarmonyPostfix] private static void postfixCheckConditions(ref bool __result, PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { Plugin.Trace($"prefixCheckConditions({LocalPlayer.CurrentEmoteID})"); if (LocalPlayer.CurrentEmoteID == EmoteDefs.getEmoteNumber(Emote.Griddy) || LocalPlayer.CurrentEmoteID == EmoteDefs.getEmoteNumber(Emote.Prisyadka)) { __result = !__instance.inSpecialInteractAnimation && !__instance.isPlayerDead && !__instance.isJumping && __instance.moveInputVector.x == 0f && !__instance.isSprinting && !__instance.isCrouching && !__instance.isClimbingLadder && !__instance.isGrabbingObjectAnimation && !__instance.inTerminalMenu && !__instance.isTypingChat; } else if (LocalPlayer.CurrentEmoteID == EmoteDefs.getEmoteNumber(Emote.Sign) || LocalPlayer.CurrentEmoteID == EmoteDefs.getEmoteNumber(AltEmote.Sign_Text)) { __result = !__instance.inSpecialInteractAnimation && !__instance.isPlayerDead && !__instance.isJumping && !__instance.isWalking && !__instance.isCrouching && !__instance.isClimbingLadder && !__instance.isGrabbingObjectAnimation && !__instance.inTerminalMenu; } } } [HarmonyPatch(typeof(PlayerControllerB), "StopPerformingEmoteServerRpc")] [HarmonyPostfix] private static void StopPerformingEmoteServerPrefix(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { Plugin.Debug("StopPerformingEmoteServerPrefix()"); if (((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled) { __instance.playerBodyAnimator.SetInteger("emoteNumber", 0); syncAnimator?.UpdateEmoteIDForOthers(0); LocalPlayer.CurrentEmoteID = 0; } LocalPlayer.TogglePlayerBadges(enabled: true); } } } internal class RoundPatch { [HarmonyPatch(typeof(RoundManager), "Awake")] [HarmonyPostfix] private static void AwakePost() { Plugin.Debug("AwakePost()"); Settings.DebugAllSettings(); if (!Settings.DisableModelOverride) { GameObject gameObject = ((Component)((Component)GameObject.Find("Systems").gameObject.transform.Find("UI")).gameObject.transform.Find("Canvas")).gameObject; LocalPlayer.CustomSignInputField = Object.Instantiate<GameObject>(LocalPlayer.SignUIPrefab, gameObject.transform).AddComponent<SignUI>(); } LocalPlayer.IsPlayerFirstFrame = true; } } internal class SignChatPatch { [HarmonyPatch(typeof(HUDManager), "EnableChat_performed")] [HarmonyPrefix] private static bool OpenChatPrefix() { if (!((Object)(object)LocalPlayer.CustomSignInputField == (Object)null)) { return !LocalPlayer.CustomSignInputField.IsSignUIOpen; } return true; } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] [HarmonyPrefix] private static bool SubmitChatPrefix() { if (!((Object)(object)LocalPlayer.CustomSignInputField == (Object)null)) { return !LocalPlayer.CustomSignInputField.IsSignUIOpen; } return true; } } } namespace BetterEmote.Netcode { public class SignEmoteText : NetworkBehaviour { private PlayerControllerB playerInstance; private TextMeshPro signModelText; private void Start() { Plugin.Debug("Start()"); playerInstance = ((Component)this).GetComponent<PlayerControllerB>(); PlayerControllerB obj = playerInstance; object obj2; if (obj == null) { obj2 = null; } else { Transform transform = ((Component)obj).transform; if (transform == null) { obj2 = null; } else { Transform obj3 = transform.Find("ScavengerModel"); if (obj3 == null) { obj2 = null; } else { Transform obj4 = obj3.Find("metarig"); if (obj4 == null) { obj2 = null; } else { Transform obj5 = obj4.Find("Sign"); if (obj5 == null) { obj2 = null; } else { Transform obj6 = obj5.Find("Text"); obj2 = ((obj6 != null) ? ((Component)obj6).GetComponent<TextMeshPro>() : null); } } } } } signModelText = (TextMeshPro)obj2; } public void UpdateSignText(string newText) { Plugin.Debug("UpdateSignText(" + newText + ")"); if ((Object)(object)playerInstance != (Object)null && ((NetworkBehaviour)playerInstance).IsOwner && playerInstance.isPlayerControlled) { UpdateSignTextServerRpc(newText); } } [ServerRpc(RequireOwnership = false)] private void UpdateSignTextServerRpc(string newText) { Plugin.Debug("UpdateSignTextServerRpc(" + newText + ")"); UpdateSignTextClientRpc(newText); } [ClientRpc] private void UpdateSignTextClientRpc(string newText) { Plugin.Debug("UpdateSignTextClientRpc(" + newText + ")"); if ((Object)(object)signModelText != (Object)null) { ((TMP_Text)signModelText).text = newText; } } } public class SyncAnimatorToOthers : NetworkBehaviour { private PlayerControllerB playerInstance; private void Start() { playerInstance = ((Component)this).GetComponent<PlayerControllerB>(); } public void UpdateEmoteIDForOthers(int newID) { Plugin.Debug($"UpdateEmoteIDForOthers({newID}, {((NetworkBehaviour)playerInstance).IsOwner}, {playerInstance.isPlayerControlled})"); if (((NetworkBehaviour)playerInstance).IsOwner && playerInstance.isPlayerControlled) { UpdateCurrentEmoteIDServerRpc(newID); } } [ServerRpc(RequireOwnership = false)] private void UpdateCurrentEmoteIDServerRpc(int newID) { Plugin.Debug($"UpdateCurrentEmoteIDServerRpc({newID})"); UpdateCurrentEmoteIDClientRpc(newID); } [ClientRpc] private void UpdateCurrentEmoteIDClientRpc(int newID) { Plugin.Debug($"UpdateCurrentEmoteIDClientRpc({newID}, {((NetworkBehaviour)playerInstance).IsOwner}, {playerInstance.isPlayerControlled})"); if (!((NetworkBehaviour)playerInstance).IsOwner || !playerInstance.isPlayerControlled) { playerInstance.playerBodyAnimator.SetInteger("emoteNumber", newID); } } } public class SyncVRState : NetworkBehaviour { private PlayerControllerB playerInstance; public static Dictionary<ulong, bool> vrPlayers = new Dictionary<ulong, bool>(); private void Start() { playerInstance = ((Component)this).GetComponent<PlayerControllerB>(); } public void UpdateVRStateForOthers(bool isVR) { Plugin.Debug($"UpdateVRStatusForOthers({isVR}, {playerInstance.playerClientId}, {((NetworkBehaviour)playerInstance).IsOwner}, {playerInstance.isPlayerControlled})"); if ((Object)(object)playerInstance != (Object)null && ((NetworkBehaviour)playerInstance).IsOwner && playerInstance.isPlayerControlled) { UpdateVRStateServerRpc(isVR, playerInstance.playerClientId); } } public void RequestVRStateFromOthers() { Plugin.Debug($"RequestVRStateFromOthers({((NetworkBehaviour)playerInstance).IsOwner}, {playerInstance.isPlayerControlled})"); if ((Object)(object)playerInstance != (Object)null && ((NetworkBehaviour)playerInstance).IsOwner && playerInstance.isPlayerControlled) { RequestedVRStateServerRpc(); } } [ServerRpc(RequireOwnership = false)] private void RequestedVRStateServerRpc() { Plugin.Debug("RequestedVRState()"); RequestedVRStateClientRpc(); } [ClientRpc] private void RequestedVRStateClientRpc() { Plugin.Debug($"RequestedVRStateClientRpc({Settings.DisableModelOverride}, {GameValues.localPlayerController.playerClientId})"); if ((Object)(object)playerInstance != (Object)null && !((NetworkBehaviour)playerInstance).IsOwner) { UpdateVRStateServerRpc(Settings.DisableModelOverride, GameValues.localPlayerController.playerClientId); } } [ServerRpc(RequireOwnership = false)] private void UpdateVRStateServerRpc(bool isVR, ulong clientId) { Plugin.Debug($"UpdateVRStateServerRpc({isVR}, {clientId})"); UpdateVRStateClientRpc(isVR, clientId); } [ClientRpc] private void UpdateVRStateClientRpc(bool isVRChange, ulong clientId) { Plugin.Debug($"UpdateVRStateClientRpc({isVRChange}, {clientId})"); vrPlayers[clientId] = isVRChange; } } } namespace BetterEmote.Compatibility { [Patcher.CompatPatch("io.daxcess.lcvr")] [HarmonyPatch] internal class LCVRChecks { [HarmonyPatch(typeof(InitializeGame), "Start")] [HarmonyPostfix] private static void StartPostfix() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("LCVRChecks.StartPostfix()"); try { if (((Enum)Plugin.Flags).HasFlag((Enum)(object)(Flags)1)) { Plugin.Debug("Found VR mode on LCVR, disabiling self emotes"); Settings.DisableModelOverride = true; } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Unable to hook into LCVR to see if the player is VR " + ex.Message)); } } } [Patcher.CompatPatch("Stoneman.LethalProgression")] [HarmonyPatch] internal class LethalProgression { [HarmonyPatch(typeof(InitializeGame), "Start")] [HarmonyPostfix] private static void StartPostfix() { Plugin.Debug("LethalProgression.StartPostfix()"); Settings.DisableSpeedChange = true; } } [Patcher.CompatPatch("com.malco.lethalcompany.moreshipupgrades")] [HarmonyPatch] internal class MoreShipUpgrades { [HarmonyPatch(typeof(InitializeGame), "Start")] [HarmonyPostfix] private static void StartPostfix() { Plugin.Debug("MoreShipUpgrades.StartPostfix()"); Settings.DisableSpeedChange = true; } } internal class Patcher { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] internal class CompatPatchAttribute : Attribute { public string Dependency { get; } public CompatPatchAttribute(string dependency) { Dependency = dependency; base..ctor(); } } public static void patchCompat(Harmony patcher) { Plugin.Debug("patchCompat()"); CollectionExtensions.Do<Type>((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()), (Action<Type>)delegate(Type type) { try { CompatPatchAttribute compatPatchAttribute = (CompatPatchAttribute)Attribute.GetCustomAttribute(type, typeof(CompatPatchAttribute)); if (compatPatchAttribute != null) { Plugin.Debug("Checking for mod to patch: " + compatPatchAttribute.Dependency); if (hasMod(compatPatchAttribute.Dependency)) { Plugin.Debug("Patching now"); patcher.CreateClassProcessor(type).Patch(); } } } catch (Exception ex) { Plugin.Logger.LogError((object)$"Failed to apply patches from {type}: {ex.Message}"); } }); } public static bool hasMod(string guid) { Plugin.Debug("Compatibility.hasMod(" + guid + ")"); foreach (PluginInfo value in Chainloader.PluginInfos.Values) { Plugin.Debug("Checking against " + value.Metadata.GUID); if (value.Metadata.GUID == guid) { Plugin.Debug("has mod!"); return true; } } return false; } } } namespace BetterEmote.AssetScripts { public class CustomAnimationObjects : MonoBehaviour { private PlayerControllerB playerInstance; private MeshRenderer sign; private GameObject signText; private SkinnedMeshRenderer legs; private void Start() { Plugin.Debug("CustomAnimationObjects.Start()"); playerInstance = ((Component)this).GetComponent<PlayerControllerB>(); } private void Update() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) Plugin.Trace("CustomAnimationObjects.Update()"); if ((Object)(object)sign == (Object)null || (Object)(object)signText == (Object)null) { FindSign(); return; } try { ((Component)sign).transform.localPosition = ((Component)sign).transform.parent.Find("spine").localPosition; if ((Object)(object)playerInstance == (Object)null) { return; } if ((Object)(object)legs == (Object)null && ((NetworkBehaviour)playerInstance).IsOwner && playerInstance.isPlayerControlled && !Settings.DisableModelOverride) { FindLegs(); return; } DisableEverything(); if (!playerInstance.performingEmote) { return; } Animator playerBodyAnimator = playerInstance.playerBodyAnimator; int num = ((playerBodyAnimator != null) ? playerBodyAnimator.GetInteger("emoteNumber") : 0); if (num == EmoteDefs.getEmoteNumber(Emote.Prisyadka)) { if ((Object)(object)legs != (Object)null) { ((Renderer)legs).enabled = true; } if (((NetworkBehaviour)playerInstance).IsOwner && !Settings.DisableModelOverride) { LocalPlayer.IsArmsSeparatedFromCamera = true; } } else if ((Object)(object)sign != (Object)null && (num == EmoteDefs.getEmoteNumber(Emote.Sign) || num == EmoteDefs.getEmoteNumber(AltEmote.Sign_Text))) { ((Renderer)sign).enabled = true; if ((Object)(object)signText != (Object)null && !signText.activeSelf) { Plugin.Trace("Sign isnt active self"); signText.SetActive(true); } if (((NetworkBehaviour)playerInstance).IsOwner && !Settings.DisableModelOverride) { LocalPlayer.IsArmsSeparatedFromCamera = true; } } } catch (Exception ex) { Plugin.Debug("Custom animation update failed " + ex.Message); } } private void DisableEverything() { Plugin.Trace("DisableEverything()"); if ((Object)(object)legs != (Object)null) { ((Renderer)legs).enabled = false; } ((Renderer)sign).enabled = false; if (signText.activeSelf) { signText.SetActive(false); } if ((Object)(object)playerInstance != (Object)null && ((NetworkBehaviour)playerInstance).IsOwner && playerInstance.isPlayerControlled && !Settings.DisableModelOverride) { LocalPlayer.IsArmsSeparatedFromCamera = false; } } private void FindSign() { Plugin.Debug("FindSign()"); if ((Object)(object)sign == (Object)null && (Object)(object)playerInstance != (Object)null) { Plugin.Debug("Sign is null and player exists"); sign = ((Component)((Component)playerInstance).transform.Find("ScavengerModel").Find("metarig").Find("Sign")).GetComponent<MeshRenderer>(); } if ((Object)(object)signText == (Object)null && (Object)(object)sign != (Object)null) { Plugin.Debug("Sign text is null and sign exists"); signText = ((Component)((Component)sign).transform.Find("Text")).gameObject; } } private void FindLegs() { Plugin.Debug("FindLegs()"); if ((Object)(object)legs == (Object)null && (Object)(object)playerInstance != (Object)null) { Plugin.Debug("Legs are null and player exists"); try { legs = ((Component)((Component)playerInstance).transform.Find("ScavengerModel").Find("LEGS")).GetComponent<SkinnedMeshRenderer>(); } catch (Exception) { Plugin.Logger.LogWarning((object)"Unable to find custom legs, this should be corrected soon."); } } } } 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<Animator>(); SoundsSource = player.movementAudio; } public void PlayClapSound() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)null && player.performingEmote && (!((NetworkBehaviour)player).IsOwner || !player.isPlayerControlled || getCurrentEmoteID() == 4)) { bool flag = player.isInHangarShipRoom && (player.playersManager?.hangarDoorsClosed ?? false); RoundManager.Instance.PlayAudibleNoise(((Component)player).transform.position, 22f, 0.6f, 0, flag, 6); SoundsSource.pitch = Random.Range(0.59f, 0.79f); if (claps != null && claps.Length != 0) { SoundsSource.PlayOneShot(claps[Random.Range(0, claps.Length)]); } } } public void PlayFootstepSound() { if ((Object)(object)player != (Object)null && player.performingEmote && (!((NetworkBehaviour)player).IsOwner || !player.isPlayerControlled || getCurrentEmoteID() == 6)) { player.PlayFootstepLocal(); player.PlayFootstepServer(); } } private int getCurrentEmoteID() { Animator obj = animator; return EmoteDefs.normalizeEmoteNumber((obj != null) ? obj.GetInteger("emoteNumber") : 0); } } internal class EmoteWheel : MonoBehaviour { private static readonly int TotalBlocks = 8; private static readonly float SelectionArrowDelaySpeed = 20f; private static readonly float PageCooldown = 0.1f; public static readonly float WheelMovementOffset = 3.3f; private float ignoreRadius = 235f; private float stopRadius = 470f; public RectTransform selectionBlock; public RectTransform selectionArrow; public Text emoteInformation; public Text pageInformation; public GameObject[] pages = Array.Empty<GameObject>(); public bool stopEmote; public bool controller; private int currentBlock = 1; public int pageNumber; public int selectedEmoteID; private float angle; private float pageCurrentCooldown = PageCooldown; private Vector2 centerScreen; private StickControl joystick; private void Awake() { Plugin.Debug("EmoteWheel.Awake()"); findGraphics(); findPages(((Component)this).gameObject.transform.Find("FunctionalContent")); updatePageInfo(); } private void OnEnable() { //IL_001b: 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_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_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_0038: 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_0069: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("EmoteWheel.OnEnable()"); centerScreen = new Vector2((float)(Screen.width / 2), (float)(Screen.height / 2)); Cursor.visible = true; if (!GameValues.localPlayerUsingController) { Mouse.current.WarpCursorPosition(centerScreen); } string text = ""; Enumerator<InputBinding> enumerator = Settings.Keybinds.EmoteWheelController.bindings.GetEnumerator(); try { while (enumerator.MoveNext()) { InputBinding current = enumerator.Current; if (((InputBinding)(ref current)).effectivePath != null && ((InputBinding)(ref current)).effectivePath.Length > 0) { text = ((InputBinding)(ref current)).effectivePath; } } } finally { ((IDisposable)enumerator).Dispose(); } if (Gamepad.current != null) { if (text == "<Gamepad>/leftStick") { joystick = Gamepad.current.leftStick; } else { joystick = Gamepad.current.rightStick; } } else { joystick = null; } if ((float)(Screen.width / Screen.height) >= 1f) { ignoreRadius = (float)Screen.height * 0.365f / 2f; stopRadius = (float)Screen.height * 0.729f / 2f; } else { ignoreRadius = (float)Screen.width * 0.183f / 2f; stopRadius = (float)Screen.width * 0.368f / 2f; } } private void findGraphics() { Plugin.Debug("EmoteWheel.findGraphics()"); try { Transform transform = ((Component)this).gameObject.transform; object obj; if (transform == null) { obj = null; } else { Transform obj2 = transform.Find("Graphics"); if (obj2 == null) { obj = null; } else { GameObject gameObject = ((Component)obj2).gameObject; if (gameObject == null) { obj = null; } else { Transform transform2 = gameObject.transform; if (transform2 == null) { obj = null; } else { Transform obj3 = transform2.Find("SelectionArrow"); if (obj3 == null) { obj = null; } else { GameObject gameObject2 = ((Component)obj3).gameObject; obj = ((gameObject2 != null) ? gameObject2.GetComponent<RectTransform>() : null); } } } } } selectionArrow = (RectTransform)obj; Transform transform3 = ((Component)this).gameObject.transform; object obj4; if (transform3 == null) { obj4 = null; } else { Transform obj5 = transform3.Find("SelectedEmote"); if (obj5 == null) { obj4 = null; } else { GameObject gameObject3 = ((Component)obj5).gameObject; obj4 = ((gameObject3 != null) ? gameObject3.GetComponent<RectTransform>() : null); } } selectionBlock = (RectTransform)obj4; Transform transform4 = ((Component)this).gameObject.transform; object obj6; if (transform4 == null) { obj6 = null; } else { Transform obj7 = transform4.Find("Graphics"); if (obj7 == null) { obj6 = null; } else { GameObject gameObject4 = ((Component)obj7).gameObject; if (gameObject4 == null) { obj6 = null; } else { Transform transform5 = gameObject4.transform; if (transform5 == null) { obj6 = null; } else { Transform obj8 = transform5.Find("EmoteInfo"); obj6 = ((obj8 != null) ? ((Component)obj8).GetComponent<Text>() : null); } } } } emoteInformation = (Text)obj6; Transform transform6 = ((Component)this).gameObject.transform; object obj9; if (transform6 == null) { obj9 = null; } else { Transform obj10 = transform6.Find("Graphics"); if (obj10 == null) { obj9 = null; } else { GameObject gameObject5 = ((Component)obj10).gameObject; if (gameObject5 == null) { obj9 = null; } else { Transform transform7 = gameObject5.transform; if (transform7 == null) { obj9 = null; } else { Transform obj11 = transform7.Find("PageNumber"); obj9 = ((obj11 != null) ? ((Component)obj11).GetComponent<Text>() : null); } } } } pageInformation = (Text)obj9; } catch (Exception ex) { Plugin.Debug("Unable to find graphics " + ex.Message); } } private void findPages(Transform contentParent) { pages = (GameObject[])(object)new GameObject[((Component)contentParent).transform.childCount]; updatePageInfo(); for (int i = 0; i < ((Component)contentParent).transform.childCount; i++) { pages[i] = ((Component)((Component)contentParent).transform.GetChild(i)).gameObject; } } private void Update() { Plugin.Trace("EmoteWheel.Update()"); wheelSelection(); updateSelectionArrow(); if (pageCurrentCooldown > 0f) { pageCurrentCooldown -= Time.deltaTime; } if ((Object)(object)selectionBlock != (Object)null && ((Component)selectionBlock).gameObject.activeSelf) { Plugin.Trace("Selection block active self"); selectedEmoteID = currentBlock + Mathf.RoundToInt((float)(TotalBlocks / 4)) + TotalBlocks * pageNumber; } else { Plugin.Trace("Selection block nooo active self"); selectedEmoteID = EmoteDefs.getEmoteCount() + 2; } displayEmoteInfo(); } private void wheelSelection() { //IL_0051: 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_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_0083: 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_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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00a6: 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) //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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0165: 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_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) Plugin.Trace("EmoteWheel.wheelSelection()"); Vector2 zero; Vector2 val; if (joystick != null && GameValues.localPlayerUsingController) { if (Vector2.Distance(Vector2.zero, ((InputControl<Vector2>)(object)joystick).ReadValue()) < WheelMovementOffset / 100f) { return; } zero = Vector2.zero; val = ((InputControl<Vector2>)(object)joystick).ReadValue(); } else { if (Vector2.Distance(centerScreen, ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue()) < WheelMovementOffset) { return; } zero = centerScreen; val = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue(); } Vector2 val2 = val - zero; double num = Math.Pow(val2.x, 2.0) + Math.Pow(val2.y, 2.0); bool flag; bool flag2; if (GameValues.localPlayerUsingController) { flag = num <= Math.Pow(Settings.ControllerDeadzone, 2.0); flag2 = false; } else { flag = num < Math.Pow(ignoreRadius, 2.0); flag2 = num >= Math.Pow(stopRadius, 2.0); } int num2 = ((!(val2.x > 0f)) ? ((val2.y > 0f) ? 2 : 3) : ((val2.y > 0f) ? 1 : 4)); float num3 = 180 * (num2 - ((num2 <= 2) ? 1 : 2)); angle = Mathf.Atan(val2.y / val2.x) * (180f / MathF.PI) + num3; if (angle == 90f) { angle = 270f; } else if (angle == 270f) { angle = 90f; } float num4 = 360 / TotalBlocks; currentBlock = Mathf.RoundToInt((angle - num4 * 1.5f) / num4); if (flag) { RectTransform obj = selectionBlock; if (obj != null) { GameObject gameObject = ((Component)obj).gameObject; if (gameObject != null) { gameObject.SetActive(false); } } return; } if ((Object)(object)selectionBlock != (Object)null) { GameObject gameObject2 = ((Component)selectionBlock).gameObject; if (gameObject2 != null) { gameObject2.SetActive(true); } ((Transform)selectionBlock).localRotation = Quaternion.Euler(((Component)this).transform.rotation.z, ((Component)this).transform.rotation.y, num4 * (float)currentBlock); } if (!flag2) { return; } if (Settings.StopOnOuter) { RectTransform obj2 = selectionBlock; if (obj2 != null) { GameObject gameObject3 = ((Component)obj2).gameObject; if (gameObject3 != null) { gameObject3.SetActive(false); } } stopEmote = true; } else { stopEmote = false; } } public void alterPage(int byValue) { Plugin.Trace("EmoteWheel.pageSelection()"); if (!(pageCurrentCooldown <= 0f)) { return; } GameObject[] array = pages; foreach (GameObject obj in array) { if (obj != null) { obj.SetActive(false); } } pageNumber = (pageNumber + byValue + pages.Length) % pages.Length; GameObject obj2 = pages[pageNumber]; if (obj2 != null) { obj2.SetActive(true); } pageCurrentCooldown = PageCooldown; updatePageInfo(); } private void updatePageInfo() { Plugin.Trace($"EmoteWheel.updatePageInfo({pageNumber}, {pages.Length})"); if ((Object)(object)pageInformation != (Object)null) { pageInformation.text = $"<color=#fe6b02><</color> Page {pageNumber + 1}/{pages.Length} <color=#fe6b02>></color>"; } } private void displayEmoteInfo() { Plugin.Trace($"EmoteWheel.displayEmoteInfo({selectedEmoteID})"); InputBind bind = ((selectedEmoteID > EmoteDefs.getEmoteCount()) ? new InputBind("", "") : Keybinds.getDisplayStrings(Settings.Keybinds.getByEmote((Emote)selectedEmoteID))); string text = "Empty"; if (selectedEmoteID <= EmoteDefs.getEmoteCount()) { Plugin.Trace("selectedEmoteID less or equal to emotes length"); Emote emote = (Emote)selectedEmoteID; text = emote.ToString().Replace("_", " "); } if ((Object)(object)emoteInformation != (Object)null) { emoteInformation.text = text + "\n" + Keybinds.formatInputBind(bind); } } private void updateSelectionArrow() { //IL_002d: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Plugin.Trace("EmoteWheel.updateSelectionArrow()"); Quaternion val = Quaternion.Euler(0f, 0f, angle - (float)(360 / TotalBlocks) * 2f); if ((Object)(object)selectionArrow != (Object)null) { ((Transform)selectionArrow).localRotation = Quaternion.Lerp(((Transform)selectionArrow).localRotation, val, Time.deltaTime * SelectionArrowDelaySpeed); } } } internal class LocalPlayer { public static GameObject LegsPrefab; public static GameObject SignPrefab; public static GameObject SignUIPrefab; private static GameObject LevelBadge; private static GameObject BetaBadge; public static Transform freeArmsTarget; public static Transform lockedArmsTarget; private static Transform legsMesh; public static int CurrentEmoteID; public static bool IsPlayerFirstFrame; public static bool IsArmsSeparatedFromCamera; public static float BaseSpeed; public static SignUI CustomSignInputField; public static void OnFirstLocalPlayerFrameWithNewAnimator(PlayerControllerB player) { Plugin.Debug("OnFirstLocalPlayerFrameWithNewAnimator()"); if ((Object)(object)CustomSignInputField != (Object)null) { CustomSignInputField.Player = player; } try { freeArmsTarget = Object.Instantiate<Transform>(player.localArmsRotationTarget, player.localArmsRotationTarget.parent.parent); lockedArmsTarget = player.localArmsRotationTarget; Transform obj = ((Component)player).transform.Find("ScavengerModel").Find("metarig").Find("spine") .Find("spine.001") .Find("spine.002") .Find("spine.003"); LevelBadge = ((Component)obj.Find("LevelSticker")).gameObject; BetaBadge = ((Component)obj.Find("BetaBadge")).gameObject; } catch (Exception ex) { Plugin.Debug("Unable to init first frame objects: " + ex.Message); } } public static void SpawnSign(PlayerControllerB player) { //IL_0078: 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) Plugin.Debug("SpawnSign()"); try { GameObject val = Object.Instantiate<GameObject>(SignPrefab, ((Component)((Component)((Component)player).transform.Find("ScavengerModel")).transform.Find("metarig")).transform); if ((Object)(object)val != (Object)null) { Plugin.Debug("Sign object not null"); ((Object)val).name = "Sign"; val.transform.SetSiblingIndex(6); val.transform.localPosition = new Vector3(0.029f, -0.45f, 1.3217f); val.transform.localRotation = Quaternion.Euler(65.556f, 180f, 180f); } } catch (Exception ex) { Plugin.Debug("Unable to spawn sign: " + ex.Message); } } public static void SpawnLegs(PlayerControllerB player) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) Plugin.Debug("SpawnLegs()"); try { GameObject obj = Object.Instantiate<GameObject>(LegsPrefab, ((Component)((Component)player.playerBodyAnimator).transform.parent).transform); legsMesh = obj.transform.Find("Mesh"); ((Object)legsMesh).name = "LEGS"; Transform transform = ((Component)legsMesh).transform; Animator playerBodyAnimator = player.playerBodyAnimator; object parent; if (playerBodyAnimator == null) { parent = null; } else { Transform transform2 = ((Component)playerBodyAnimator).transform; parent = ((transform2 != null) ? transform2.parent : null); } transform.parent = (Transform)parent; Transform transform3 = obj.transform; object obj2; if (transform3 == null) { obj2 = null; } else { Transform obj3 = transform3.Find("Armature"); obj2 = ((obj3 != null) ? ((Component)obj3).gameObject : null); } GameObject val = (GameObject)obj2; if ((Object)(object)val != (Object)null) { ((Object)val).name = "FistPersonLegs"; Transform transform4 = val.transform; Animator playerBodyAnimator2 = player.playerBodyAnimator; transform4.parent = ((playerBodyAnimator2 != null) ? ((Component)playerBodyAnimator2).transform : null); val.transform.position = new Vector3(0f, 0.197f, 0f); val.transform.localScale = new Vector3(13.99568f, 13.99568f, 13.99568f); } Object.Destroy((Object)(object)obj); } catch (Exception ex) { Plugin.Debug("Unable to spawn legs: " + ex.Message); } } public static void UpdateLegsMaterial(PlayerControllerB player) { Plugin.Debug("UpdateLegsMaterial()"); if ((Object)(object)legsMesh == (Object)null) { return; } SkinnedMeshRenderer component = ((Component)legsMesh).GetComponent<SkinnedMeshRenderer>(); if ((Object)(object)component == (Object)null) { return; } Animator playerBodyAnimator = player.playerBodyAnimator; object obj; if (playerBodyAnimator == null) { obj = null; } else { Transform transform = ((Component)playerBodyAnimator).transform; if (transform == null) { obj = null; } else { Transform parent = transform.parent; if (parent == null) { obj = null; } else { Transform transform2 = ((Component)parent).transform; if (transform2 == null) { obj = null; } else { Transform obj2 = transform2.Find("LOD1"); if (obj2 == null) { obj = null; } else { GameObject gameObject = ((Component)obj2).gameObject; if (gameObject == null) { obj = null; } else { SkinnedMeshRenderer component2 = gameObject.GetComponent<SkinnedMeshRenderer>(); obj = ((component2 != null) ? ((Renderer)component2).material : null); } } } } } } Material val = (Material)obj; if (!((Object)(object)val == (Object)null)) { ((Renderer)component).material = val; } } public static bool CheckIfTooManyEmotesIsPlaying(PlayerControllerB player) { //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) Plugin.Debug("CheckIfTooManyEmotesIsPlaying()"); Animator playerBodyAnimator = player.playerBodyAnimator; if ((Object)(object)playerBodyAnimator != (Object)null) { try { AnimatorStateInfo currentAnimatorStateInfo = playerBodyAnimator.GetCurrentAnimatorStateInfo(1); return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Dance1") && player.performingEmote && GetAnimatorEmoteClipName(playerBodyAnimator) != "Dance1"; } catch (Exception) { return false; } } return false; } private static string GetAnimatorEmoteClipName(Animator animator) { Plugin.Debug("GetAnimatorEmoteClipName()"); try { return ((Object)((AnimatorClipInfo)(ref animator.GetCurrentAnimatorClipInfo(1)[0])).clip).name; } catch (Exception) { return ""; } } public static void TogglePlayerBadges(bool enabled) { Plugin.Debug($"TogglePlayerBadges({enabled})"); if ((Object)(object)BetaBadge != (Object)null) { ((Renderer)BetaBadge.GetComponent<MeshRenderer>()).enabled = enabled; } if ((Object)(object)LevelBadge != (Object)null) { ((Renderer)LevelBadge.GetComponent<MeshRenderer>()).enabled = enabled; } else if (Settings.DisableModelOverride) { Plugin.Debug("Couldn't find the level badge (its fine for the settings)"); } else { Plugin.Logger.LogError((object)"Couldn't find the level badge"); } } } public class SignUI : MonoBehaviour { public PlayerControllerB Player; private TMP_InputField inputField; private TMP_Text previewText; private Text charactersLeftText; private Text submitText; private Text cancelText; private Button submitButton; private Button cancelButton; public bool IsSignUIOpen; private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown Plugin.Debug("SignUI.Awake()"); FindComponents(); Button obj = submitButton; if (obj != null) { ButtonClickedEvent onClick = obj.onClick; if (onClick != null) { ((UnityEvent)onClick).AddListener(new UnityAction(SubmitText)); } } Button obj2 = cancelButton; if (obj2 != null) { ButtonClickedEvent onClick2 = obj2.onClick; if (onClick2 != null) { ((UnityEvent)onClick2).AddListener((UnityAction)delegate { Close(cancelAction: true); }); } } TMP_InputField obj3 = inputField; if (obj3 != null) { ((UnityEvent<string>)(object)obj3.onValueChanged)?.AddListener((UnityAction<string>)delegate(string fieldText) { UpdatePreviewText(fieldText); UpdateCharactersLeftText(); }); } } private void OnEnable() { Plugin.Debug("SignUI.OnEnable()"); if ((Object)(object)Player == (Object)null) { Plugin.Logger.LogWarning((object)"Player is null, this is fine when it happens on load, however SignUI may not function properly if it repeats"); } else { Player.isTypingChat = true; Player.disableLookInput = true; } IsSignUIOpen = true; if ((Object)(object)inputField != (Object)null) { ((Selectable)inputField).Select(); inputField.text = string.Empty; } if ((Object)(object)previewText != (Object)null) { previewText.text = "PREVIEW"; } updateKeybindText(); } public void updateKeybindText() { Plugin.Debug("SignUI.updateKeybindText()"); InputBind displayStrings = Keybinds.getDisplayStrings(Settings.Keybinds.SignSubmit); InputBind displayStrings2 = Keybinds.getDisplayStrings(Settings.Keybinds.SignCancel); if ((Object)(object)submitText != (Object)null) { submitText.text = "<color=orange>" + Keybinds.formatInputBind(displayStrings) + "</color> Submit"; } if ((Object)(object)cancelText != (Object)null) { cancelText.text = "<color=orange>" + Keybinds.formatInputBind(displayStrings2) + "</color> Cancel"; } } private void Update() { Plugin.Trace("SignUI.Update()"); Cursor.visible = true; Cursor.lockState = (CursorLockMode)2; if (!Player.performingEmote) { Plugin.Debug("SignUI Player isnt performing emote"); Close(cancelAction: true); } if (Player.quickMenuManager.isMenuOpen || EmoteKeybindPatch.EmoteWheelIsOpened) { Plugin.Debug("Menu is open or right mouse button is clicked"); Close(cancelAction: true); } } private void FindComponents() { Plugin.Debug("SignUI.FindComponents()"); try { Transform obj = ((Component)this).transform.Find("InputField"); inputField = ((obj != null) ? ((Component)obj).GetComponent<TMP_InputField>() : null); Transform obj2 = ((Component)this).transform.Find("CharsLeft"); charactersLeftText = ((obj2 != null) ? ((Component)obj2).GetComponent<Text>() : null); Transform obj3 = ((Component)this).transform.Find("Submit"); submitButton = ((obj3 != null) ? ((Component)obj3).GetComponent<Button>() : null); Transform obj4 = ((Component)this).transform.Find("Cancel"); cancelButton = ((obj4 != null) ? ((Component)obj4).GetComponent<Button>() : null); Transform obj5 = ((Component)this).transform.Find("Sign"); object obj6; if (obj5 == null) { obj6 = null; } else { Transform transform = ((Component)obj5).transform; if (transform == null) { obj6 = null; } else { Transform obj7 = transform.Find("Text"); obj6 = ((obj7 != null) ? ((Component)obj7).GetComponent<TMP_Text>() : null); } } previewText = (TMP_Text)obj6; Transform obj8 = ((Component)this).transform.Find("Submit"); object obj9; if (obj8 == null) { obj9 = null; } else { Transform transform2 = ((Component)obj8).transform; if (transform2 == null) { obj9 = null; } else { Transform obj10 = transform2.Find("Text"); obj9 = ((obj10 != null) ? ((Component)obj10).GetComponent<Text>() : null); } } submitText = (Text)obj9; Transform obj11 = ((Component)this).transform.Find("Cancel"); object obj12; if (obj11 == null) { obj12 = null; } else { Transform transform3 = ((Component)obj11).transform; if (transform3 == null) { obj12 = null; } else { Transform obj13 = transform3.Find("Text"); obj12 = ((obj13 != null) ? ((Component)obj13).GetComponent<Text>() : null); } } cancelText = (Text)obj12; } catch (Exception arg) { Plugin.Debug($"Unable to find components for sign UI {arg}"); } } private void UpdateCharactersLeftText() { Plugin.Debug("SignUI.UpdateCharactersLeftText()"); if ((Object)(object)charactersLeftText != (Object)null) { Text obj = charactersLeftText; TMP_InputField obj2 = inputField; int num = ((obj2 != null) ? obj2.characterLimit : 0); TMP_InputField obj3 = inputField; obj.text = $"CHARACTERS LEFT: <color=yellow>{num - ((obj3 == null) ? null : obj3.text?.Length).GetValueOrDefault()}</color>"; } } private void UpdatePreviewText(string text) { Plugin.Debug("SignUI.UpdatePreviewText(" + text + ")"); if ((Object)(object)previewText != (Object)null) { previewText.text = text; } } public void SubmitText() { //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) Plugin.Debug("SignUI.SubmitText()"); TMP_InputField obj = inputField; if (((obj == null) ? null : obj.text?.Equals(string.Empty)).GetValueOrDefault(true)) { Close(cancelAction: true); return; } if ((Object)(object)inputField != (Object)null) { Plugin.Debug("Submitted " + inputField.text + " to server"); ((Component)Player).GetComponent<SignEmoteText>().UpdateSignText(inputField.text); } if (Player.timeSinceStartingEmote > Settings.SignTextCooldown) { Plugin.Debug("Time elapsed, time to perform"); Player.PerformEmote(default(CallbackContext), EmoteDefs.getEmoteNumber(AltEmote.Sign_Text)); } Close(cancelAction: false); } public void Close(bool cancelAction) { Plugin.Debug($"SignUI.Close({cancelAction})"); Player.isTypingChat = false; IsSignUIOpen = false; if (cancelAction) { Player.performingEmote = false; Player.StopPerformingEmoteServerRpc(); } if (!Player.quickMenuManager.isMenuOpen) { Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } Player.disableLookInput = false; ((Component)this).gameObject.SetActive(false); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }