using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BoneLib; using BoneLib.BoneMenu; using Il2CppSLZ.Bonelab; using Il2CppSLZ.Marrow; using Il2CppSLZ.VRMK; using LabFusion.Entities; using MelonLoader; using MelonLoader.Preferences; using RabbitDirector; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(RabbitDirectorMod), "Rabbit Director", "1.0.1", "EQUALIZER", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("0.0.0.0")] namespace RabbitDirector; public sealed class RabbitDirectorMod : MelonMod { private enum VoiceTopic { Behind, Threat, Chase, Search } private const int VoiceLineCount = 30; private static readonly int[] DefaultFavorites = new int[8] { 1, 7, 8, 15, 17, 24, 27, 30 }; private const float WheelDeadzone = 0.52f; private const float WheelActivationSeconds = 0.25f; private const float WheelHandDistance = 0.32f; private const float WheelDirectionDistance = 0.18f; private static readonly Dictionary TopicLines = new Dictionary { [VoiceTopic.Behind] = new int[9] { 2, 3, 6, 9, 13, 15, 18, 27, 29 }, [VoiceTopic.Threat] = new int[10] { 1, 4, 7, 11, 12, 22, 23, 25, 28, 30 }, [VoiceTopic.Chase] = new int[6] { 10, 14, 16, 19, 21, 26 }, [VoiceTopic.Search] = new int[5] { 5, 8, 17, 20, 24 } }; private static readonly Dictionary LineTexts = new Dictionary { [1] = "Mr. and Mrs. Waterman, were very, very bad people.", [2] = "Happy Halloween from the Waterman's", [3] = "This year's harvest will be so pleasant!", [4] = "A new year, more bunnies for the slaughter.", [5] = "My victims are never forgotten.", [6] = "This Year's haunt will be so delightful", [7] = "I will rip, and I will cut, and I will punish you.", [8] = "Such naughty bunnies, I will find you", [9] = "Let's go trick-or-treating.", [10] = "Ready or not, here I come", [11] = "You will be punished.", [12] = "You won't feel a thing.", [13] = "Here's your treat.", [14] = "You shouldn't run from me.", [15] = "*laugh*", [16] = "Oh, you're in trouble now!", [17] = "It's fun when you hide, but now I seek.", [18] = "Trick-or-treat", [19] = "What a naughty bunny", [20] = "You shouldn't be here.", [21] = "You stay put", [22] = "It's time to join the fair eye.", [23] = "See, doesn't that feel better?", [24] = "And you look like a scarecrow.", [25] = "...And bunnies must be punished", [26] = "Playtime is over", [27] = "*laugh*", [28] = "The boogieman claims his victims", [29] = "Here's your trick.", [30] = "You'll be with us forever" }; private readonly MelonPreferences_Entry[] _favoriteEntries = new MelonPreferences_Entry[8]; private readonly FunctionElement[] _quickButtons = (FunctionElement[])(object)new FunctionElement[8]; private MelonPreferences_Category _preferences; private Hand _maskHand; private Transform _physicalMask; private Renderer _physicalMaskRenderer; private Transform _maskGrabPoint; private Transform _maskHomeParent; private Transform _wornMaskBone; private Vector3 _maskHomePosition; private Quaternion _maskHomeRotation; private Vector3 _maskHomeScale; private int _boundAvatarId; private float _maskTakenAt; private readonly Random _random = new Random(); private readonly Dictionary _lastTopicLine = new Dictionary(); private GameObject _wheelRoot; private readonly Dictionary _wheelLabels = new Dictionary(); private TextMesh _wheelCenter; private bool _wheelHeld; private VoiceTopic? _wheelSelection; private float _wheelActivationStartedAt = -1f; private Transform _wheelLeftPalm; private Transform _wheelRightPalm; public override void OnInitializeMelon() { CreatePreferences(); CreateMenu(); ((MelonBase)this).LoggerInstance.Msg("Rabbit Director ready: voice library, mask hand-follow and visibility controls."); } public override void OnUpdate() { UpdateVoiceWheel(); RefreshMaskReferences(); if ((Object)(object)_maskHand == (Object)null) { if (!TryTakeMask(Player.LeftHand)) { TryTakeMask(Player.RightHand); } return; } BaseController controller = _maskHand.Controller; if ((Object)(object)controller == (Object)null) { ReturnMask(); } else if (Time.time > _maskTakenAt + 0.12f && controller.isBelowGripThreshold) { ReturnMask(); } } private void CreatePreferences() { _preferences = MelonPreferences.CreateCategory("RabbitDirector", "Rabbit Director"); for (int i = 0; i < _favoriteEntries.Length; i++) { _favoriteEntries[i] = _preferences.CreateEntry($"Favorite_{i + 1}", DefaultFavorites[i], $"Favorite {i + 1}", (string)null, false, false, (ValueValidator)null, (string)null); _favoriteEntries[i].Value = ClampLine(_favoriteEntries[i].Value); } } private void CreateMenu() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(0.92f, 0.36f, 0.08f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.95f, 0.87f, 0.68f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.72f, 0.06f, 0.05f); Page val4 = Page.Root.CreatePage("Rabbit Director", val, 0, true); Page val5 = val4.CreatePage("Quick Voice Lines", val, 0, true); Page val6 = val4.CreatePage("Voice Wheel Topics", val, 0, true); Page val7 = val4.CreatePage("All 30 Voice Lines", val2, 8, true); Page val8 = val4.CreatePage("Edit Favorites", Color.yellow, 0, true); val4.CreateFunction("INVISIBLE", new Color(0.35f, 0.35f, 0.35f), (Action)delegate { TriggerNamedEvent("VisibilityControl", menuTap: false); }); val4.CreateFunction("VISIBLE", Color.white, (Action)delegate { TriggerNamedEvent("VisibilityControl", menuTap: true); }); val4.CreateFunction("RETURN MASK NOW", val2, (Action)ReturnMask); val6.CreateFunction("BEHIND - random", val, (Action)delegate { PlayRandomTopic(VoiceTopic.Behind); }); val6.CreateFunction("THREAT - random", val3, (Action)delegate { PlayRandomTopic(VoiceTopic.Threat); }); val6.CreateFunction("CHASE - random", Color.yellow, (Action)delegate { PlayRandomTopic(VoiceTopic.Chase); }); val6.CreateFunction("SEARCH - random", Color.cyan, (Action)delegate { PlayRandomTopic(VoiceTopic.Search); }); val6.CreateFunction("VR WHEEL: hold left Y + right stick", val2, (Action)delegate { ((MelonBase)this).LoggerInstance.Msg("Voice wheel: hold left Y, point the right stick at a topic, then release Y."); }); for (int num = 0; num < _quickButtons.Length; num++) { int capturedSlot = num; _quickButtons[num] = val5.CreateFunction(QuickButtonName(num), val, (Action)delegate { PlayLine(_favoriteEntries[capturedSlot].Value); }); } val5.CreateFunction("STOP VOICE", val3, (Action)StopVoice); for (int num2 = 1; num2 <= 30; num2++) { int capturedLine = num2; val7.CreateFunction(MenuLineName(num2), val2, (Action)delegate { PlayLine(capturedLine); }); } for (int num3 = 0; num3 < _favoriteEntries.Length; num3++) { int capturedSlot2 = num3; val8.CreateInt($"Slot {num3 + 1}: {LineId(_favoriteEntries[num3].Value)}", Color.yellow, _favoriteEntries[num3].Value, 1, 1, 30, (Action)delegate(int value) { SetFavorite(capturedSlot2, value); }); } val4.CreateFunction("STOP VOICE", val3, (Action)StopVoice); val4.CreateFunction("Rescan Avatar Audio", Color.cyan, (Action)delegate { int count = FindAudioEvents().Count; ((MelonBase)this).LoggerInstance.Msg($"Rabbit Director found {count}/31 audio events on the avatar."); }); } private void SetFavorite(int slot, int value) { value = ClampLine(value); _favoriteEntries[slot].Value = value; ((Element)_quickButtons[slot]).ElementName = QuickButtonName(slot); MelonPreferences.Save(); } private string QuickButtonName(int slot) { return $"{slot + 1}. {LineId(_favoriteEntries[slot].Value)}"; } private static string MenuLineName(int line) { return LineId(line) + " - " + LineTexts[line]; } private void PlayLine(int line) { TriggerEvent("AudioEvent_" + LineId(ClampLine(line))); } private void PlayRandomTopic(VoiceTopic topic) { int[] array = TopicLines[topic]; int value; int num = (_lastTopicLine.TryGetValue(topic, out value) ? value : (-1)); int num2; do { num2 = array[_random.Next(array.Length)]; } while (array.Length > 1 && num2 == num); _lastTopicLine[topic] = num2; ((MelonBase)this).LoggerInstance.Msg($"Voice wheel: {TopicName(topic)} -> {LineId(num2)} {LineTexts[num2]}"); PlayLine(num2); } private void UpdateVoiceWheel() { if (!_wheelHeld) { if (!TryGetWheelActivationPose(out var leftPalm, out var rightPalm)) { _wheelActivationStartedAt = -1f; return; } if (_wheelActivationStartedAt < 0f) { _wheelActivationStartedAt = Time.time; } if (!(Time.time < _wheelActivationStartedAt + 0.25f)) { _wheelHeld = true; _wheelLeftPalm = leftPalm; _wheelRightPalm = rightPalm; _wheelSelection = null; ShowVoiceWheel(null); } } else if ((Object)(object)_wheelLeftPalm == (Object)null || (Object)(object)_wheelRightPalm == (Object)null || (Object)(object)_wheelLeftPalm == (Object)(object)_wheelRightPalm) { CancelVoiceWheel(); } else { Hand leftHand = Player.LeftHand; BaseController val = ((leftHand != null) ? leftHand.Controller : null); if ((Object)(object)val == (Object)null) { CancelVoiceWheel(); return; } if (val.isBelowGripThreshold) { FinishVoiceWheel(); return; } _wheelSelection = TopicFromHandPosition(_wheelLeftPalm, _wheelRightPalm); ShowVoiceWheel(_wheelSelection); } } private static bool TryGetWheelActivationPose(out Transform leftPalm, out Transform rightPalm) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) leftPalm = null; rightPalm = null; Hand leftHand = Player.LeftHand; Hand rightHand = Player.RightHand; if ((Object)(object)leftHand == (Object)null || (Object)(object)rightHand == (Object)null || leftHand.HasAttachedObject() || rightHand.HasAttachedObject()) { return false; } BaseController controller = leftHand.Controller; leftPalm = (((Object)(object)leftHand.palmPositionTransform != (Object)null) ? leftHand.palmPositionTransform : ((Component)leftHand).transform); rightPalm = (((Object)(object)rightHand.palmPositionTransform != (Object)null) ? rightHand.palmPositionTransform : ((Component)rightHand).transform); if ((Object)(object)controller == (Object)null || controller.isBelowGripThreshold || (Object)(object)leftPalm == (Object)null || (Object)(object)rightPalm == (Object)null || Vector3.Distance(leftPalm.position, rightPalm.position) > 0.32f) { return false; } Camera val = Camera.main ?? ((IEnumerable)Camera.allCameras).FirstOrDefault((Func)((Camera active) => ((Behaviour)active).enabled)); if ((Object)(object)val == (Object)null) { return false; } Vector3 val2 = (leftPalm.position + rightPalm.position) * 0.5f - ((Component)val).transform.position; if (((Vector3)(ref val2)).sqrMagnitude > 0.09f) { return Vector3.Dot(((Component)val).transform.forward, ((Vector3)(ref val2)).normalized) > 0.2f; } return false; } private static VoiceTopic? TopicFromHandPosition(Transform leftPalm, Transform rightPalm) { //IL_0047: 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_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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Camera val = Camera.main ?? ((IEnumerable)Camera.allCameras).FirstOrDefault((Func)((Camera active) => ((Behaviour)active).enabled)); if ((Object)(object)val == (Object)null) { return null; } Vector3 val2 = rightPalm.position - leftPalm.position; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(Vector3.Dot(val2, ((Component)val).transform.right) / 0.18f, Vector3.Dot(val2, ((Component)val).transform.up) / 0.18f); if (((Vector2)(ref val3)).magnitude < 0.52f) { return null; } if (Mathf.Abs(val3.y) >= Mathf.Abs(val3.x)) { return (!(val3.y >= 0f)) ? VoiceTopic.Chase : VoiceTopic.Behind; } return (val3.x >= 0f) ? VoiceTopic.Threat : VoiceTopic.Search; } private void FinishVoiceWheel() { HideVoiceWheel(); _wheelHeld = false; _wheelActivationStartedAt = -1f; _wheelLeftPalm = null; _wheelRightPalm = null; if (_wheelSelection.HasValue) { PlayRandomTopic(_wheelSelection.Value); } _wheelSelection = null; } private void CancelVoiceWheel() { HideVoiceWheel(); _wheelHeld = false; _wheelSelection = null; _wheelActivationStartedAt = -1f; _wheelLeftPalm = null; _wheelRightPalm = null; } private void ShowVoiceWheel(VoiceTopic? selected) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) EnsureVoiceWheel(); Camera val = Camera.main ?? ((IEnumerable)Camera.allCameras).FirstOrDefault((Func)((Camera active) => ((Behaviour)active).enabled)); if ((Object)(object)val == (Object)null || (Object)(object)_wheelRoot == (Object)null) { return; } _wheelRoot.SetActive(true); Transform transform = ((Component)val).transform; Transform val2 = (((Object)(object)_wheelLeftPalm != (Object)null) ? _wheelLeftPalm : transform); Vector3 val3 = transform.position - val2.position; Vector3 normalized = ((Vector3)(ref val3)).normalized; _wheelRoot.transform.position = val2.position + normalized * 0.08f; _wheelRoot.transform.rotation = Quaternion.LookRotation(transform.forward, transform.up); foreach (KeyValuePair wheelLabel in _wheelLabels) { wheelLabel.Deconstruct(out var key, out var value); VoiceTopic voiceTopic = key; TextMesh obj = value; VoiceTopic? voiceTopic2 = selected; key = voiceTopic; obj.color = ((voiceTopic2 == key) ? Color.white : TopicColor(voiceTopic)); } _wheelCenter.text = (selected.HasValue ? (TopicName(selected.Value) + "\nrelease Y") : "VOICE\nchoose a direction"); } private void HideVoiceWheel() { if ((Object)(object)_wheelRoot != (Object)null) { _wheelRoot.SetActive(false); } } private void EnsureVoiceWheel() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_wheelRoot != (Object)null)) { _wheelRoot = new GameObject("RabbitDirectorVoiceWheel") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)_wheelRoot); _wheelRoot.transform.localScale = Vector3.one * 0.04f; _wheelCenter = CreateWheelText("Center", Vector3.zero, "VOICE\nMOVE RIGHT HAND", 0.025f); _wheelLabels[VoiceTopic.Behind] = CreateWheelText("Behind", Vector3.up * 4.2f, "UP\nBEHIND", 0.032f); _wheelLabels[VoiceTopic.Threat] = CreateWheelText("Threat", Vector3.right * 5.4f, "RIGHT\nTHREAT", 0.032f); _wheelLabels[VoiceTopic.Chase] = CreateWheelText("Chase", Vector3.down * 4.2f, "DOWN\nCHASE", 0.032f); _wheelLabels[VoiceTopic.Search] = CreateWheelText("Search", Vector3.left * 5.4f, "LEFT\nSEARCH", 0.032f); HideVoiceWheel(); } } private TextMesh CreateWheelText(string objectName, Vector3 localPosition, string text, float size) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(objectName); val.transform.SetParent(_wheelRoot.transform, false); val.transform.localPosition = localPosition; TextMesh obj = val.AddComponent(); obj.text = text; obj.anchor = (TextAnchor)4; obj.alignment = (TextAlignment)1; obj.characterSize = size; obj.fontSize = 64; obj.color = new Color(0.92f, 0.36f, 0.08f); return obj; } private static Color TopicColor(VoiceTopic topic) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) return (Color)(topic switch { VoiceTopic.Behind => new Color(0.78f, 0.32f, 0.95f), VoiceTopic.Threat => new Color(0.86f, 0.08f, 0.08f), VoiceTopic.Chase => new Color(0.95f, 0.75f, 0.12f), VoiceTopic.Search => new Color(0.12f, 0.75f, 0.92f), _ => Color.white, }); } private static string TopicName(VoiceTopic topic) { return topic switch { VoiceTopic.Behind => "BEHIND", VoiceTopic.Threat => "THREAT", VoiceTopic.Chase => "CHASE", VoiceTopic.Search => "SEARCH", _ => "VOICE", }; } private void StopVoice() { TriggerEvent("AudioEvent_STOP_ALL"); } private void TriggerEvent(string objectName) { SimpleGripEvents val = ((IEnumerable)FindAvatarEvents()).FirstOrDefault((Func)((SimpleGripEvents component) => ((Object)((Component)component).gameObject).name == objectName)); if ((Object)(object)val == (Object)null) { ((MelonBase)this).LoggerInstance.Warning("'" + objectName + "' was not found. Equip PumpkinRabbit_TEST_MIN and try again."); return; } UnityEvent onIndexDown = val.OnIndexDown; if (onIndexDown != null) { onIndexDown.Invoke(); } TryRelayFusionEvent(val, "TRIGGER_DOWN"); } private void TriggerNamedEvent(string objectName, bool menuTap) { SimpleGripEvents val = ((IEnumerable)FindAvatarEvents()).FirstOrDefault((Func)((SimpleGripEvents component) => ((Object)((Component)component).gameObject).name == objectName)); if ((Object)(object)val == (Object)null) { ((MelonBase)this).LoggerInstance.Warning("'" + objectName + "' was not found on the equipped avatar."); } else if (menuTap) { UnityEvent onMenuTapDown = val.OnMenuTapDown; if (onMenuTapDown != null) { onMenuTapDown.Invoke(); } TryRelayFusionEvent(val, "MENU_TAP"); } else { UnityEvent onIndexDown = val.OnIndexDown; if (onIndexDown != null) { onIndexDown.Invoke(); } TryRelayFusionEvent(val, "TRIGGER_DOWN"); } } private void RefreshMaskReferences() { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.RigManager == (Object)null) { ClearMaskReferences(); return; } Avatar val = null; try { val = Player.Avatar; } catch { ClearMaskReferences(); return; } if ((Object)(object)val == (Object)null) { ClearMaskReferences(); return; } int instanceID = ((Object)val).GetInstanceID(); if (_boundAvatarId == instanceID && (Object)(object)_physicalMask != (Object)null && (Object)(object)_maskGrabPoint != (Object)null) { return; } ClearMaskReferences(); Transform val2 = FindDeep(((Component)val).transform, "PhysicalMaskAccessory"); if (!((Object)(object)val2 == (Object)null)) { _physicalMask = FindDeep(val2, "PhysicalMask"); _maskGrabPoint = FindDeep(val2, "MaskGrabPoint"); _wornMaskBone = FindDeep(((Component)val).transform, "Mask"); Transform physicalMask = _physicalMask; _physicalMaskRenderer = ((physicalMask != null) ? ((Component)physicalMask).GetComponent() : null); if ((Object)(object)_physicalMask == (Object)null || (Object)(object)_maskGrabPoint == (Object)null || (Object)(object)_wornMaskBone == (Object)null || (Object)(object)_physicalMaskRenderer == (Object)null) { ClearMaskReferences(); return; } _boundAvatarId = instanceID; _maskHomeParent = _physicalMask.parent; _maskHomePosition = _physicalMask.localPosition; _maskHomeRotation = _physicalMask.localRotation; _maskHomeScale = _physicalMask.localScale; _physicalMaskRenderer.enabled = false; ((MelonBase)this).LoggerInstance.Msg("Mask proximity control bound to Pumpkin Rabbit avatar."); } } private bool TryTakeMask(Hand hand) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hand == (Object)null || (Object)(object)_physicalMask == (Object)null || (Object)(object)_maskGrabPoint == (Object)null) { return false; } BaseController controller = hand.Controller; Transform val = (((Object)(object)hand.palmPositionTransform != (Object)null) ? hand.palmPositionTransform : ((Component)hand).transform); if ((Object)(object)controller == (Object)null || controller.isBelowGripThreshold || (Object)(object)val == (Object)null || hand.HasAttachedObject()) { return false; } if (Vector3.Distance(val.position, _maskGrabPoint.position) > 0.18f) { return false; } _maskHand = hand; _maskTakenAt = Time.time; TriggerNamedEvent("PhysicalMaskAccessory", menuTap: false); _wornMaskBone.localScale = Vector3.one * 0.1f; _physicalMaskRenderer.enabled = true; _physicalMask.SetParent(val, true); ((MelonBase)this).LoggerInstance.Msg($"Mask taken with {hand.handedness} hand; grab distance={Vector3.Distance(val.position, _maskGrabPoint.position):F3}m."); return true; } private void ReturnMask() { //IL_004f: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_physicalMaskRenderer != (Object)null) { _physicalMaskRenderer.enabled = false; } if ((Object)(object)_physicalMask != (Object)null && (Object)(object)_maskHomeParent != (Object)null) { _physicalMask.SetParent(_maskHomeParent, false); _physicalMask.localPosition = _maskHomePosition; _physicalMask.localRotation = _maskHomeRotation; _physicalMask.localScale = _maskHomeScale; } bool num = (Object)(object)_maskHand != (Object)null; _maskHand = null; if (num) { if ((Object)(object)_wornMaskBone != (Object)null) { _wornMaskBone.localScale = Vector3.one; } TriggerNamedEvent("MaskReturnSyncEvent", menuTap: false); ((MelonBase)this).LoggerInstance.Msg("Mask returned after controller grip release."); } } private void ClearMaskReferences() { _maskHand = null; _physicalMask = null; _physicalMaskRenderer = null; _maskGrabPoint = null; _maskHomeParent = null; _wornMaskBone = null; _boundAvatarId = 0; _maskTakenAt = 0f; } private List FindAudioEvents() { return (from component in FindAvatarEvents() where ((Object)((Component)component).gameObject).name.StartsWith("AudioEvent_", StringComparison.Ordinal) select component).ToList(); } private List FindAvatarEvents() { List list = new List(); if ((Object)(object)Player.Avatar == (Object)null) { return list; } foreach (SimpleGripEvents componentsInChild in ((Component)Player.Avatar).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null) { list.Add(componentsInChild); } } return list; } private void TryRelayFusionEvent(SimpleGripEvents source, string eventName) { try { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly2) => assembly2.GetName().Name == "BonelabSupport"); if (assembly == null) { return; } Type type = assembly.GetType("MarrowFusion.Bonelab.Extenders.SimpleGripEventsExtender"); Type type2 = assembly.GetType("MarrowFusion.Bonelab.Patching.SimpleGripEventsPatches"); Type type3 = assembly.GetType("MarrowFusion.Bonelab.Messages.SimpleGripEventType"); if (type == null || type2 == null || type3 == null) { return; } object obj = type.GetField("Cache", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return; } MethodInfo methodInfo = obj.GetType().GetMethods().First((MethodInfo method) => method.Name == "TryGet" && method.GetParameters().Length == 2); object[] array = new object[2] { source, null }; if (!(bool)methodInfo.Invoke(obj, array)) { return; } object obj2 = array[1]; NetworkEntity val = (NetworkEntity)((obj2 is NetworkEntity) ? obj2 : null); if (val == null) { return; } object extender = val.GetExtender(type); if (extender != null) { object obj3 = extender.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).First((MethodInfo method) => method.Name == "GetIndex" && method.GetParameters().Length == 1) .Invoke(extender, new object[1] { source }); if (obj3 != null) { byte b = checked((byte)Convert.ToInt32(obj3)); object obj4 = Enum.Parse(type3, eventName); type2.GetMethod("SendGripEvent", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, new object[3] { val.ID, b, obj4 }); } } } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("Local avatar event worked, but Fusion relay failed: " + ex.Message); } } private static int ClampLine(int value) { return Math.Clamp(value, 1, 30); } private static string LineId(int line) { return $"PR_{line:000}"; } private static Transform FindDeep(Transform parent, string objectName) { foreach (Transform componentsInChild in ((Component)parent).GetComponentsInChildren(true)) { if (((Object)componentsInChild).name == objectName) { return componentsInChild; } } return null; } }