Due to update 2.4.3, some mods may no longer function. FixedConfig may be necessary.
Decompiled source of FourthAbility v1.0.0
BepInEx\plugins\FourthAbility\FourthAbilitySlot.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BepInEx; using BepInEx.Logging; using BoplFixedMath; using HarmonyLib; using Steamworks; using Steamworks.Data; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace FourthAbilitySlotMod; [BepInPlugin("com.openai.boplbattle.fourthabilityslot", "Fourth Ability Slot", "1.1.3")] public sealed class FourthAbilityPlugin : BaseUnityPlugin { private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) FourthAbilityRuntime.Log = ((BaseUnityPlugin)this).Logger; new Harmony("com.openai.boplbattle.fourthabilityslot").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Fourth Ability Slot v1.1.3 loaded: repaired local loss selector, visible four-player HUD slots, diamond indicator layout, and synchronized online play enabled."); } private void Update() { FourthAbilityRuntime.NetworkUpdate(); } } internal sealed class FourthSlotPointer : MonoBehaviour, IPointerEnterHandler, IPointerClickHandler, IEventSystemHandler { internal CharacterSelectBox Box; internal SelectAbility Slot; private int SlotIndex() { List<SelectableMonoBehaviour> field = FourthAbilityRuntime.GetField<List<SelectableMonoBehaviour>>(Box, "selectables"); if (field != null && !((Object)(object)Slot == (Object)null)) { return field.IndexOf((SelectableMonoBehaviour)(object)Slot); } return -1; } public void OnPointerEnter(PointerEventData eventData) { int num = SlotIndex(); if ((Object)(object)Box != (Object)null && num >= 0) { Box.SetSelectedHover(num); } } public void OnPointerClick(PointerEventData eventData) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (eventData == null || (int)eventData.button == 0) { int num = SlotIndex(); if (!((Object)(object)Box == (Object)null) && num >= 0) { Box.SetSelectedHover(num); Box.ClickEnterAbilityGrid(); } } } } internal sealed class MidGameFourthPointer : MonoBehaviour, IPointerEnterHandler, IPointerClickHandler, IEventSystemHandler { internal MidGameAbilitySelect Selector; public void OnPointerEnter(PointerEventData eventData) { if (!((Object)(object)Selector == (Object)null)) { FourthAbilityRuntime.SetField(Selector, "YPos", 3); Selector.SyncArrowPositionToCurrentYPos(); AudioManager.Get().Play("navigateMenu"); } } public void OnPointerClick(PointerEventData eventData) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if ((eventData == null || (int)eventData.button == 0) && !((Object)(object)Selector == (Object)null)) { FourthAbilityRuntime.SetField(Selector, "YPos", 3); Selector.SyncArrowPositionToCurrentYPos(); } } } internal sealed class MatchTeamTextColor : MonoBehaviour { internal TMP_Text Source; private TMP_Text target; private void Awake() { target = ((Component)this).GetComponent<TMP_Text>(); } private void LateUpdate() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { target = ((Component)this).GetComponent<TMP_Text>(); } if ((Object)(object)target != (Object)null && (Object)(object)Source != (Object)null) { ((Graphic)target).color = ((Graphic)Source).color; } } } internal static class FourthAbilityRuntime { internal sealed class PickupState { internal AbilityMonoBehaviour FourthAbility; internal AbilityReadyIndicator FourthIndicator; internal Fix FourthCooldown; internal bool Active; } internal const int KeyboardChoiceKey = -1; internal const int FourthBindingIndex = 8; internal const byte PacketHello = 1; internal const byte PacketChoice = 2; internal static ManualLogSource Log; internal static NamedSpriteList AllIcons; internal static readonly Dictionary<int, SelectAbility> SlotsByBox = new Dictionary<int, SelectAbility>(); internal static readonly Dictionary<int, CharacterSelectBox> BoxesBySlot = new Dictionary<int, CharacterSelectBox>(); internal static readonly Dictionary<int, int> Choices = new Dictionary<int, int>(); internal static readonly Dictionary<int, InputControl> FourthBindings = new Dictionary<int, InputControl>(); internal static readonly Dictionary<int, Vector2[]> MidGameOriginalPositions = new Dictionary<int, Vector2[]>(); internal static readonly HashSet<int> VerifiedInputPlayers = new HashSet<int>(); internal static readonly Dictionary<int, int> OnlineChoices = new Dictionary<int, int>(); internal static readonly HashSet<string> SeenOnlinePeers = new HashSet<string>(); internal static readonly byte[] PacketMagic = new byte[4] { 70, 65, 83, 55 }; internal static float nextNetworkHeartbeat; internal static FieldInfo Field(Type type, string name) { return AccessTools.Field(type, name); } internal static T GetField<T>(object instance, string name) { if (instance == null) { return default(T); } FieldInfo fieldInfo = Field(instance.GetType(), name); if (fieldInfo == null) { return default(T); } object value = fieldInfo.GetValue(instance); if (value == null) { return default(T); } return (T)value; } internal static void SetField(object instance, string name, object value) { if (instance != null) { FieldInfo fieldInfo = Field(instance.GetType(), name); if (fieldInfo != null) { fieldInfo.SetValue(instance, value); } } } internal static bool IsOnline() { try { FieldInfo fieldInfo = Field(typeof(GameLobby), "isOnlineGame"); return fieldInfo != null && (bool)fieldInfo.GetValue(null); } catch { return false; } } internal static bool IsOurPacket(byte[] data) { if (data != null && data.Length >= 5 && data[0] == PacketMagic[0] && data[1] == PacketMagic[1] && data[2] == PacketMagic[2]) { return data[3] == PacketMagic[3]; } return false; } internal static byte[] NewPacket(byte type, int payloadBytes) { byte[] array = new byte[5 + payloadBytes]; for (int i = 0; i < PacketMagic.Length; i++) { array[i] = PacketMagic[i]; } array[4] = type; return array; } internal static void WriteInt(byte[] data, int offset, int value) { byte[] bytes = BitConverter.GetBytes(value); for (int i = 0; i < 4; i++) { data[offset + i] = bytes[i]; } } internal static void SendPacket(byte[] data) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (!IsOnline() || data == null) { return; } try { SteamManager instance = SteamManager.instance; if ((Object)(object)instance == (Object)null || instance.connectedPlayers == null) { return; } foreach (SteamConnection connectedPlayer in instance.connectedPlayers) { if (connectedPlayer != null && ((ConnectionManager)connectedPlayer).Connected) { ((Connection)(ref ((ConnectionManager)connectedPlayer).Connection)).SendMessage(data, (SendType)8); } } } catch (Exception ex) { Log.LogWarning((object)("Fourth-slot network send failed: " + ex.Message)); } } internal static void SendHello() { byte[] array = NewPacket(1, 1); array[5] = 11; SendPacket(array); } internal static void SendChoice(int playerId, int choice) { byte[] data = NewPacket(2, 8); WriteInt(data, 5, playerId); WriteInt(data, 9, choice); SendPacket(data); } internal static void NetworkUpdate() { if (!IsOnline() || Time.unscaledTime < nextNetworkHeartbeat) { return; } nextNetworkHeartbeat = Time.unscaledTime + 0.5f; SendHello(); foreach (KeyValuePair<int, int> onlineChoice in OnlineChoices) { SendChoice(onlineChoice.Key, onlineChoice.Value); } } internal static bool SenderMatchesPlayer(int playerId, NetIdentity identity) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) try { PlayerHandler val = PlayerHandler.Get(); Player val2 = ((val == null) ? null : val.GetPlayer(playerId)); if (val2 == null || val2.IsLocalPlayer) { return false; } return string.Equals(((object)val2.steamId/*cast due to .constrained prefix*/).ToString(), ((object)((NetIdentity)(ref identity)).SteamId/*cast due to .constrained prefix*/).ToString(), StringComparison.Ordinal); } catch { return false; } } internal static void ReceivePacket(byte[] data, NetIdentity identity) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (!IsOurPacket(data)) { return; } try { switch (data[4]) { case 1: { string text = ((object)((NetIdentity)(ref identity)).SteamId/*cast due to .constrained prefix*/).ToString(); int num2 = ((data.Length > 5) ? data[5] : 0); if (SeenOnlinePeers.Add(text)) { if (num2 == 11) { Log.LogInfo((object)("Fourth Ability Slot v1.1.3 handshake received from online peer " + text + ".")); } else { Log.LogWarning((object)("Online peer " + text + " is using an older Fourth Ability Slot build. Install v1.1.3 on every computer for identical menus.")); } } break; } case 2: if (data.Length >= 13) { int num = BitConverter.ToInt32(data, 5); if (SenderMatchesPlayer(num, identity)) { int value = BitConverter.ToInt32(data, 9); OnlineChoices[num] = value; } } break; } } catch (Exception ex) { Log.LogWarning((object)("Ignored malformed fourth-slot network packet: " + ex.Message)); } } internal static int GetBoxKey(CharacterSelectBox box) { if (GetField<bool>(box, "UseskeyboardMouse")) { return -1; } Gamepad field = GetField<Gamepad>(box, "currentGamePad"); if (field != null) { return ((InputDevice)field).deviceId; } return int.MinValue; } internal static int GetPlayerKey(Player player) { if (player.UsesKeyboardAndMouse) { return -1; } InputDevice inputDevice = player.inputDevice; Gamepad val = (Gamepad)(object)((inputDevice is Gamepad) ? inputDevice : null); if (val != null) { return ((InputDevice)val).deviceId; } return int.MinValue; } internal static void SaveChoice(CharacterSelectBox box) { if ((Object)(object)box == (Object)null || !SlotsByBox.TryGetValue(((Object)box).GetInstanceID(), out var value) || (Object)(object)value == (Object)null) { return; } int boxKey = GetBoxKey(box); if (boxKey == int.MinValue) { return; } Choices[boxKey] = value.SelectedIndex; if (!IsOnline()) { return; } PlayerHandler val = PlayerHandler.Get(); List<Player> list = ((val == null) ? null : val.PlayerList()); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { Player val2 = list[i]; if (val2 != null && val2.IsLocalPlayer && GetPlayerKey(val2) == boxKey) { OnlineChoices[val2.Id] = value.SelectedIndex; SendChoice(val2.Id, value.SelectedIndex); break; } } } internal static void AdjustAnimationTarget(SelectAbility slot, float oldTarget, float newTarget) { //IL_0077: 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_00a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)slot == (Object)null) { return; } float num = newTarget - oldTarget; AnimateInOutUI component = ((Component)slot).GetComponent<AnimateInOutUI>(); if ((Object)(object)component != (Object)null) { bool field = GetField<bool>(component, "horizontalInstead"); float[] field2 = GetField<float[]>(component, "originalHeights"); if (!field && field2 != null) { for (int i = 0; i < field2.Length; i++) { field2[i] += num; } } } RectTransform component2 = ((Component)slot).GetComponent<RectTransform>(); if ((Object)(object)component2 != (Object)null && Mathf.Abs(component2.anchoredPosition.y - oldTarget) < 1f) { Vector2 anchoredPosition = component2.anchoredPosition; anchoredPosition.y = newTarget; component2.anchoredPosition = anchoredPosition; } } internal static AnimateInOutUI[] InsertAnimation(AnimateInOutUI[] source, AnimateInOutUI after, AnimateInOutUI item) { if (source == null) { if (!((Object)(object)item == (Object)null)) { return (AnimateInOutUI[])(object)new AnimateInOutUI[1] { item }; } return null; } int num = source.Length; for (int i = 0; i < source.Length; i++) { if ((Object)(object)source[i] == (Object)(object)after) { num = i + 1; break; } } AnimateInOutUI[] array = (AnimateInOutUI[])(object)new AnimateInOutUI[source.Length + 1]; for (int j = 0; j < num; j++) { array[j] = source[j]; } array[num] = item; for (int k = num; k < source.Length; k++) { array[k + 1] = source[k]; } return array; } internal static T[] AppendValue<T>(T[] source, T value) { int num = ((source != null) ? source.Length : 0); T[] array = new T[num + 1]; for (int i = 0; i < num; i++) { array[i] = source[i]; } array[num] = value; return array; } internal static T[] PrependValue<T>(T[] source, T value) { int num = ((source != null) ? source.Length : 0); T[] array = new T[num + 1]; array[0] = value; for (int i = 0; i < num; i++) { array[i + 1] = source[i]; } return array; } internal static T CloneUiBelow<T>(T[] source, string objectName) where T : Component { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if (source == null || source.Length == 0 || (Object)(object)source[^1] == (Object)null) { return default(T); } T val = source[^1]; GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val2).name = objectName; val2.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1); RectTransform component = val2.GetComponent<RectTransform>(); RectTransform component2 = ((Component)val/*cast due to .constrained prefix*/).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, -34f); if (source.Length > 1 && (Object)(object)source[^2] != (Object)null) { RectTransform component3 = ((Component)source[^2]/*cast due to .constrained prefix*/).GetComponent<RectTransform>(); if ((Object)(object)component3 != (Object)null) { val3 = component2.anchoredPosition - component3.anchoredPosition; } } component.anchoredPosition = component2.anchoredPosition + val3; } return val2.GetComponent<T>(); } internal static T CloneUiAbove<T>(T[] source, string objectName) where T : Component { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if (source == null || source.Length == 0 || (Object)(object)source[0] == (Object)null) { return default(T); } T val = source[0]; GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val2).name = objectName; val2.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex()); RectTransform component = val2.GetComponent<RectTransform>(); RectTransform component2 = ((Component)val/*cast due to .constrained prefix*/).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 34f); if (source.Length > 1 && (Object)(object)source[1] != (Object)null) { RectTransform component3 = ((Component)source[1]/*cast due to .constrained prefix*/).GetComponent<RectTransform>(); if ((Object)(object)component3 != (Object)null) { val3 = component2.anchoredPosition - component3.anchoredPosition; } } component.anchoredPosition = component2.anchoredPosition + val3; } return val2.GetComponent<T>(); } internal static void PrepareKeyBindMenu(KeyBindButton button) { if ((Object)(object)button == (Object)null) { return; } try { string[] field = GetField<string[]>(button, "KeyListGamePad"); string[] field2 = GetField<string[]>(button, "KeyListKeyboardMouse"); if (field == null || field2 == null || field.Length >= 9 || field2.Length >= 9) { return; } SetField(button, "KeyListGamePad", PrependValue(field, field[Math.Min(3, field.Length - 1)])); SetField(button, "KeyListKeyboardMouse", PrependValue(field2, field2[Math.Min(3, field2.Length - 1)])); bool[] field3 = GetField<bool[]>(button, "MouseOnlyKeyList"); SetField(button, "MouseOnlyKeyList", PrependValue(field3, value: false)); Sprite[] field4 = GetField<Sprite[]>(button, "CircleIndicators_gamePad"); Sprite[] field5 = GetField<Sprite[]>(button, "CircleIndicators_keyboard"); Sprite value = ((field4 != null && field4.Length > 3) ? field4[3] : null); Sprite value2 = ((field5 != null && field5.Length > 3) ? field5[3] : null); SetField(button, "CircleIndicators_gamePad", PrependValue(field4, value)); SetField(button, "CircleIndicators_keyboard", PrependValue(field5, value2)); SetField(button, "indicatorRotations_keyboard", PrependValue(GetField<float[]>(button, "indicatorRotations_keyboard"), 0f)); TextMeshProUGUI[] field6 = GetField<TextMeshProUGUI[]>(button, "bindingListLabels"); TextMeshProUGUI val = FourthAbilityRuntime.CloneUiAbove<TextMeshProUGUI>(field6, "Ability 4 Binding Label"); if ((Object)(object)val != (Object)null) { ((TMP_Text)val).text = "A4"; MatchTeamTextColor matchTeamTextColor = ((Component)val).gameObject.GetComponent<MatchTeamTextColor>(); if ((Object)(object)matchTeamTextColor == (Object)null) { matchTeamTextColor = ((Component)val).gameObject.AddComponent<MatchTeamTextColor>(); } matchTeamTextColor.Source = (TMP_Text)(object)((field6 != null && field6.Length > 0) ? field6[0] : null); } SetField(button, "bindingListLabels", PrependValue(field6, val)); TextMeshProUGUI[] field7 = GetField<TextMeshProUGUI[]>(button, "bindingListChoices"); TextMeshProUGUI val2 = FourthAbilityRuntime.CloneUiAbove<TextMeshProUGUI>(field7, "Ability 4 Binding Choice"); if ((Object)(object)val2 != (Object)null) { ((TMP_Text)val2).text = ""; MatchTeamTextColor matchTeamTextColor2 = ((Component)val2).gameObject.GetComponent<MatchTeamTextColor>(); if ((Object)(object)matchTeamTextColor2 == (Object)null) { matchTeamTextColor2 = ((Component)val2).gameObject.AddComponent<MatchTeamTextColor>(); } matchTeamTextColor2.Source = (TMP_Text)(object)((field7 != null && field7.Length > 0) ? field7[0] : null); } SetField(button, "bindingListChoices", PrependValue(field7, val2)); } catch (Exception ex) { Log.LogError((object)("Could not extend the in-game keybind menu: " + ex)); } } internal static void FinishKeyBindMenu(KeyBindButton button) { if (!((Object)(object)button == (Object)null)) { string[] field = GetField<string[]>(button, "keyListGamepad_spaced"); string[] field2 = GetField<string[]>(button, "KeyListKeyboardMouse_spaced"); if (field != null && field.Length > 8) { field[0] = "A4"; } if (field2 != null && field2.Length > 8) { field2[0] = "A4"; } } } internal static InputControl DefaultFourthBinding(bool keyboardMouse, Gamepad pad) { if (keyboardMouse) { Mouse current = Mouse.current; if (current != null) { return (InputControl)(object)current.middleButton; } return null; } if (pad != null) { return (InputControl)(object)pad.rightTrigger; } return null; } internal static InputControl FourthBindingFor(Player player) { if (player == null) { return null; } int playerKey = GetPlayerKey(player); if (playerKey != int.MinValue && FourthBindings.TryGetValue(playerKey, out var value) && value != null) { return value; } bool usesKeyboardAndMouse = player.UsesKeyboardAndMouse; InputDevice inputDevice = player.inputDevice; return DefaultFourthBinding(usesKeyboardAndMouse, (Gamepad)(object)((inputDevice is Gamepad) ? inputDevice : null)); } internal static InputControl[] ToBindingMenuOrder(Player player) { if (player == null) { return null; } InputControl[] customKeyBinding = player.CustomKeyBinding; InputControl[] array = (InputControl[])(object)new InputControl[9] { FourthBindingFor(player), default(InputControl), default(InputControl), default(InputControl), default(InputControl), default(InputControl), default(InputControl), default(InputControl), default(InputControl) }; for (int i = 0; i < 8; i++) { array[i + 1] = ((customKeyBinding != null && customKeyBinding.Length > i) ? customKeyBinding[i] : null); } return array; } internal static InputControl[] ToVanillaBindingOrder(InputControl[] ordered) { if (ordered == null || ordered.Length <= 8) { return ordered; } InputControl[] array = (InputControl[])(object)new InputControl[8]; for (int i = 0; i < 8; i++) { array[i] = ordered[i + 1]; } return array; } internal static void EnsureFourthBinding(Player player) { if (player != null && player.IsLocalPlayer) { int playerKey = GetPlayerKey(player); if (playerKey != int.MinValue && !FourthBindings.ContainsKey(playerKey)) { Dictionary<int, InputControl> fourthBindings = FourthBindings; bool usesKeyboardAndMouse = player.UsesKeyboardAndMouse; InputDevice inputDevice = player.inputDevice; fourthBindings[playerKey] = DefaultFourthBinding(usesKeyboardAndMouse, (Gamepad)(object)((inputDevice is Gamepad) ? inputDevice : null)); } } } internal static InputControl[] HideFourthBinding(Player player) { return null; } internal static bool EventCalls(UnityEvent callback, string methodName) { if (callback == null) { return false; } for (int i = 0; i < ((UnityEventBase)callback).GetPersistentEventCount(); i++) { if (string.Equals(((UnityEventBase)callback).GetPersistentMethodName(i), methodName, StringComparison.Ordinal)) { return true; } } return false; } internal static void InstallFourthSlotPointer(CharacterSelectBox box, SelectAbility fourth) { if ((Object)(object)box == (Object)null || (Object)(object)fourth == (Object)null) { return; } bool flag = false; CallOnHover[] componentsInChildren = ((Component)fourth).GetComponentsInChildren<CallOnHover>(true); foreach (CallOnHover val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && (EventCalls(val.onHover, "SetSelectedHover") || EventCalls(val.onClick, "ClickEnterAbilityGrid"))) { GameObject gameObject = ((Component)val).gameObject; Object.Destroy((Object)(object)val); FourthSlotPointer fourthSlotPointer = gameObject.GetComponent<FourthSlotPointer>(); if ((Object)(object)fourthSlotPointer == (Object)null) { fourthSlotPointer = gameObject.AddComponent<FourthSlotPointer>(); } fourthSlotPointer.Box = box; fourthSlotPointer.Slot = fourth; flag = true; } } if (!flag) { Image field = GetField<Image>(fourth, "abilityIconRenderer"); GameObject val2 = (((Object)(object)field == (Object)null) ? ((Component)fourth).gameObject : ((Component)field).gameObject); FourthSlotPointer fourthSlotPointer2 = val2.GetComponent<FourthSlotPointer>(); if ((Object)(object)fourthSlotPointer2 == (Object)null) { fourthSlotPointer2 = val2.AddComponent<FourthSlotPointer>(); } fourthSlotPointer2.Box = box; fourthSlotPointer2.Slot = fourth; } } internal static void CreateFourthSlot(CharacterSelectBox box) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)box == (Object)null) { return; } try { List<SelectableMonoBehaviour> field = GetField<List<SelectableMonoBehaviour>>(box, "selectables"); if (field == null || field.Count < 5 || SlotsByBox.ContainsKey(((Object)box).GetInstanceID())) { return; } SelectableMonoBehaviour obj = field[2]; SelectAbility val = (SelectAbility)(object)((obj is SelectAbility) ? obj : null); SelectableMonoBehaviour obj2 = field[3]; SelectAbility val2 = (SelectAbility)(object)((obj2 is SelectAbility) ? obj2 : null); SelectableMonoBehaviour obj3 = field[4]; SelectAbility val3 = (SelectAbility)(object)((obj3 is SelectAbility) ? obj3 : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { return; } Vector3 localScale = ((Component)val).transform.localScale * 0.76f; ((Component)val).transform.localScale = localScale; ((Component)val2).transform.localScale = localScale; ((Component)val3).transform.localScale = localScale; GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, ((Component)val3).transform.parent); ((Object)val4).name = "Fourth Ability Slot"; val4.transform.SetSiblingIndex(((Component)val3).transform.GetSiblingIndex() + 1); SelectAbility component = val4.GetComponent<SelectAbility>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val4); return; } SetField(component, "csb", box); SetField(component, "Skip", false); ((Component)component).transform.localScale = localScale; field.Insert(5, (SelectableMonoBehaviour)(object)component); List<Vector2> field2 = GetField<List<Vector2>>(box, "arrow_Separation_YPos"); if (field2 != null && field2.Count >= 5) { field2.Insert(5, field2[4]); } List<Image> field3 = GetField<List<Image>>(box, "imagesToDisable"); if (field3 != null && field3.Count >= 5) { field3.Insert(5, null); } AnimateInOutUI[] field4 = GetField<AnimateInOutUI[]>(box, "animateSelectables"); SetField(box, "animateSelectables", InsertAnimation(field4, ((Component)val3).GetComponent<AnimateInOutUI>(), ((Component)component).GetComponent<AnimateInOutUI>())); float[] field5 = GetField<float[]>(box, "originalAbilitySelectPos"); if (field5 != null && field5.Length >= 3) { float num = field5[0]; float num2 = field5[2]; float num3 = (num + num2) * 0.5f; float num4 = (num2 - num) * 0.5f * 0.78f; float newTarget = num3 - num4 * 1.5f; float newTarget2 = num3 - num4 * 0.5f; float newTarget3 = num3 + num4 * 0.5f; float newTarget4 = num3 + num4 * 1.5f; AdjustAnimationTarget(val, field5[0], newTarget); AdjustAnimationTarget(val2, field5[1], newTarget2); AdjustAnimationTarget(val3, field5[2], newTarget3); AdjustAnimationTarget(component, field5[2], newTarget4); } AllIcons = GetField<NamedSpriteList>(component, "abilityIcons"); SlotsByBox[((Object)box).GetInstanceID()] = component; BoxesBySlot[((Object)component).GetInstanceID()] = box; ((SelectableMonoBehaviour)component).Select(val3.SelectedIndex); InstallFourthSlotPointer(box, component); Log.LogInfo((object)("Added fourth ability choice to character select box " + ((Object)box).GetInstanceID() + ".")); } catch (Exception ex) { Log.LogError((object)("Could not create the fourth character-select slot: " + ex)); } } internal static bool RawFourthInputHeld(Player player) { if (player == null || player.ignoreAllInputs) { return false; } if (!player.IsLocalPlayer) { return false; } EnsureFourthBinding(player); InputControl val = FourthBindingFor(player); ButtonControl val2 = (ButtonControl)(object)((val is ButtonControl) ? val : null); bool flag = val2 != null && val2.isPressed; if (flag && VerifiedInputPlayers.Add(player.Id)) { Log.LogInfo((object)("Fourth-slot input detected for local player " + player.Id + ".")); } return flag; } internal static bool HasFourMidGameRows(MidGameAbilitySelect selector) { if ((Object)(object)selector == (Object)null) { return false; } Player field = GetField<Player>(selector, "player"); RectTransform[] field2 = GetField<RectTransform[]>(selector, "Circles"); if (field != null && field.Abilities != null && field.Abilities.Count > 3 && field2 != null) { return field2.Length > 3; } return false; } internal static void InstallMidGamePointer(MidGameAbilitySelect selector, RectTransform circle) { if ((Object)(object)selector == (Object)null || (Object)(object)circle == (Object)null) { return; } bool flag = false; CallOnHover[] componentsInChildren = ((Component)circle).GetComponentsInChildren<CallOnHover>(true); foreach (CallOnHover val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && EventCalls(val.onHover, "HoverCircle")) { GameObject gameObject = ((Component)val).gameObject; Object.Destroy((Object)(object)val); MidGameFourthPointer midGameFourthPointer = gameObject.GetComponent<MidGameFourthPointer>(); if ((Object)(object)midGameFourthPointer == (Object)null) { midGameFourthPointer = gameObject.AddComponent<MidGameFourthPointer>(); } midGameFourthPointer.Selector = selector; flag = true; } } if (!flag) { MidGameFourthPointer midGameFourthPointer2 = ((Component)circle).GetComponent<MidGameFourthPointer>(); if ((Object)(object)midGameFourthPointer2 == (Object)null) { midGameFourthPointer2 = ((Component)circle).gameObject.AddComponent<MidGameFourthPointer>(); } midGameFourthPointer2.Selector = selector; } } internal static void EnsureMidGameFourthCircle(MidGameAbilitySelect selector) { //IL_0115: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0131: 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_0138: 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) if ((Object)(object)selector == (Object)null) { return; } RectTransform[] field = GetField<RectTransform[]>(selector, "Circles"); if (field == null || field.Length < 3 || (Object)(object)field[2] == (Object)null) { return; } int instanceID = ((Object)selector).GetInstanceID(); if (!MidGameOriginalPositions.ContainsKey(instanceID)) { Vector2[] array = (Vector2[])(object)new Vector2[3]; for (int i = 0; i < 3; i++) { ref Vector2 reference = ref array[i]; reference = (((Object)(object)field[i] == (Object)null) ? Vector2.zero : field[i].anchoredPosition); } MidGameOriginalPositions[instanceID] = array; } RectTransform val; if (field.Length > 3 && (Object)(object)field[3] != (Object)null) { val = field[3]; } else { GameObject val2 = Object.Instantiate<GameObject>(((Component)field[2]).gameObject, ((Transform)field[2]).parent); ((Object)val2).name = "Fourth Between-Round Ability Circle"; val2.transform.SetSiblingIndex(((Transform)field[2]).GetSiblingIndex() + 1); val = val2.GetComponent<RectTransform>(); if ((Object)(object)val == (Object)null) { Object.Destroy((Object)(object)val2); return; } Vector2 val3 = (((Object)(object)field[1] == (Object)null) ? (Vector2.down * GetField<float>(selector, "circleDistance")) : (field[2].anchoredPosition - field[1].anchoredPosition)); val.anchoredPosition = field[2].anchoredPosition + val3; RectTransform[] array2 = (RectTransform[])(object)new RectTransform[4]; for (int j = 0; j < 3; j++) { array2[j] = field[j]; } array2[3] = val; SetField(selector, "Circles", array2); } InstallMidGamePointer(selector, val); LayoutMidGameRows(selector); } internal static void LayoutMidGameRows(MidGameAbilitySelect selector) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)selector == (Object)null) { return; } RectTransform[] field = GetField<RectTransform[]>(selector, "Circles"); if (field == null || field.Length < 4 || !MidGameOriginalPositions.TryGetValue(((Object)selector).GetInstanceID(), out var value) || value == null || value.Length < 3) { return; } Vector2 val = (value[0] + value[2]) * 0.5f; Vector2 val2 = (value[2] - value[0]) * 0.5f; Vector2 val3 = val2 * 0.72f; val += Vector2.up * Mathf.Abs(val2.y) * 0.16f; for (int i = 0; i < 4; i++) { if (!((Object)(object)field[i] == (Object)null)) { field[i].anchoredPosition = val + val3 * ((float)i - 1.5f); ((Transform)field[i]).localScale = Vector3.one * 0.9f; ((Component)field[i]).gameObject.SetActive(true); } } SyncAbilitySelectControllerLayout(selector, field); } internal static void SyncAbilitySelectControllerLayout(MidGameAbilitySelect selector, RectTransform[] circles) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)selector == (Object)null || circles == null || circles.Length < 4) { return; } AbilitySelectController componentInParent = ((Component)selector).GetComponentInParent<AbilitySelectController>(); if (!((Object)(object)componentInParent == (Object)null)) { Vector2[] array = (Vector2[])(object)new Vector2[4]; for (int i = 0; i < 4; i++) { ref Vector2 reference = ref array[i]; reference = (((Object)(object)circles[i] == (Object)null) ? Vector2.zero : circles[i].anchoredPosition); } SetField(componentInParent, "abilityListOriginalPositions", array); Log.LogInfo((object)("Repaired four-row between-round animation targets for local player " + componentInParent.GetPlayerId() + ".")); } } internal static void EnsureAbilitySelectAnimationTargets(AbilitySelectController controller) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } MidGameAbilitySelect field = GetField<MidGameAbilitySelect>(controller, "abilityCirclesParent"); RectTransform[] array = (((Object)(object)field == (Object)null) ? null : GetField<RectTransform[]>(field, "Circles")); if (array == null) { return; } Vector2[] field2 = GetField<Vector2[]>(controller, "abilityListOriginalPositions"); if (field2 == null || field2.Length != array.Length) { Vector2[] array2 = (Vector2[])(object)new Vector2[array.Length]; for (int i = 0; i < array2.Length; i++) { ref Vector2 reference = ref array2[i]; reference = (((Object)(object)array[i] == (Object)null) ? Vector2.zero : array[i].anchoredPosition); } SetField(controller, "abilityListOriginalPositions", array2); } } internal static int IconIndexForAbility(NamedSpriteList icons, GameObject ability) { if ((Object)(object)icons == (Object)null || icons.sprites == null || (Object)(object)ability == (Object)null) { return 1; } int num = icons.IndexOf(((Object)ability).name); if (num > 0 && num < icons.sprites.Count) { return num; } return 1; } internal static void PrepareMidGameSelector(MidGameAbilitySelect selector) { if (!HasFourMidGameRows(selector)) { return; } Player field = GetField<Player>(selector, "player"); RectTransform[] field2 = GetField<RectTransform[]>(selector, "Circles"); NamedSpriteList field3 = GetField<NamedSpriteList>(selector, "localAbilityIcons"); if (field != null && field2 != null && !((Object)(object)field2[3] == (Object)null) && !((Object)(object)field3 == (Object)null)) { Image[] field4 = GetField<Image[]>(selector, "CircleImages"); int[] field5 = GetField<int[]>(selector, "XPos"); Image[] array = (Image[])(object)new Image[4]; int[] array2 = new int[4]; for (int i = 0; i < 3; i++) { array[i] = ((field4 != null && field4.Length > i) ? field4[i] : null); array2[i] = ((field5 == null || field5.Length <= i) ? 1 : field5[i]); } ((Component)field2[3]).gameObject.SetActive(true); array[3] = ((((Transform)field2[3]).childCount > 0) ? ((Component)((Transform)field2[3]).GetChild(0)).GetComponent<Image>() : null); array2[3] = IconIndexForAbility(field3, field.Abilities[3]); if ((Object)(object)array[3] != (Object)null) { array[3].sprite = field3.GetSprite(array2[3]); } SetField(selector, "CircleImages", array); SetField(selector, "XPos", array2); LayoutMidGameRows(selector); selector.SyncArrowPositionToCurrentYPos(); } } internal static bool MoveMidGameRow(MidGameAbilitySelect selector, int direction) { if (!HasFourMidGameRows(selector)) { return false; } AudioManager.Get().Play("navigateMenu"); int field = GetField<int>(selector, "YPos"); SetField(selector, "YPos", (field + direction + 4) % 4); return true; } internal static void SaveMidGameFourthChoice(MidGameAbilitySelect selector) { if (!HasFourMidGameRows(selector) || GetField<int>(selector, "YPos") != 3) { return; } Player field = GetField<Player>(selector, "player"); int[] field2 = GetField<int[]>(selector, "XPos"); if (field != null && field.IsLocalPlayer && field2 != null && field2.Length >= 4) { int num = field2[3]; int playerKey = GetPlayerKey(field); if (playerKey != int.MinValue) { Choices[playerKey] = num; } if (IsOnline()) { OnlineChoices[field.Id] = num; SendChoice(field.Id, num); } Log.LogInfo((object)("Updated fourth ability from the between-round loss selector for player " + field.Id + ".")); } } internal static bool FourthInputHeld(Player player) { if (player == null || player.ignoreAllInputs) { return false; } if (IsOnline() || GameLobby.isPlayingAReplay) { return player.SelectButton_isDown(); } return RawFourthInputHeld(player); } internal static void PutFourthInputInPacket(int playerId, ref InputPacket packet) { if (IsOnline()) { PlayerHandler val = PlayerHandler.Get(); Player val2 = ((val == null) ? null : val.GetPlayer(playerId)); if (val2 != null && val2.IsLocalPlayer) { packet.select = RawFourthInputHeld(val2); } } } internal static void AddFourthToPlayers(List<Player> players) { //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) if (players == null) { return; } if ((Object)(object)AllIcons == (Object)null) { foreach (SelectAbility value2 in SlotsByBox.Values) { if ((Object)(object)value2 != (Object)null) { AllIcons = GetField<NamedSpriteList>(value2, "abilityIcons"); if ((Object)(object)AllIcons != (Object)null) { break; } } } } if ((Object)(object)AllIcons == (Object)null || AllIcons.sprites == null || AllIcons.sprites.Count <= 1) { Log.LogError((object)"The ability icon list was unavailable; the fourth loadout ability was not added."); return; } for (int i = 0; i < players.Count; i++) { Player val = players[i]; if (val == null) { continue; } if (val.IsLocalPlayer) { EnsureFourthBinding(val); } int num = 1; if (val.IsLocalPlayer && Choices.TryGetValue(GetPlayerKey(val), out var value)) { num = value; } else if (IsOnline() && OnlineChoices.TryGetValue(val.Id, out value)) { num = value; } if (num <= 0 || num >= AllIcons.sprites.Count) { num = 1; } if (IsOnline()) { if (val.IsLocalPlayer) { OnlineChoices[val.Id] = num; SendChoice(val.Id, num); } else if (!OnlineChoices.ContainsKey(val.Id)) { Log.LogWarning((object)("No fourth-ability selection was received yet for online player " + val.Id + "; using the default until the next selection screen.")); } } NamedSprite val2 = AllIcons.sprites[num]; if (!((Object)(object)val2.associatedGameObject == (Object)null)) { if (val.Abilities == null) { val.Abilities = new List<GameObject>(); } if (val.AbilityIcons == null) { val.AbilityIcons = new List<Sprite>(); } if (val.Abilities.Count > 3) { val.Abilities[3] = val2.associatedGameObject; } else { val.Abilities.Add(val2.associatedGameObject); } if (val.AbilityIcons.Count > 3) { val.AbilityIcons[3] = val2.sprite; } else { val.AbilityIcons.Add(val2.sprite); } Log.LogInfo((object)("Prepared fourth gameplay ability '" + val2.name + "' for player " + val.Id + " (loadout count " + val.Abilities.Count + ").")); } } } internal static void EnsureCooldownArray(SlimeController controller) { //IL_0066: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } List<AbilityMonoBehaviour> field = GetField<List<AbilityMonoBehaviour>>(controller, "abilities"); int num = ((field == null) ? 4 : Math.Max(4, field.Count)); Fix[] field2 = GetField<Fix[]>(controller, "abilityCooldownTimers"); if (field2 == null || field2.Length < num) { Fix[] array = (Fix[])(object)new Fix[num]; int num2 = ((field2 != null) ? field2.Length : 0); for (int i = 0; i < num2; i++) { ref Fix reference = ref array[i]; reference = field2[i]; } for (int j = num2; j < array.Length; j++) { ref Fix reference2 = ref array[j]; reference2 = (Fix)(-1.5f); } SetField(controller, "abilityCooldownTimers", array); } } internal static void AppendFourthIndicator(SlimeController controller, Sprite sprite) { //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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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_0104: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } AbilityReadyIndicator[] field = GetField<AbilityReadyIndicator[]>(controller, "AbilityReadyIndicators"); if (field == null || field.Length < 3 || (Object)(object)field[2] == (Object)null) { return; } AbilityReadyIndicator val = field[2]; FollowTransform component = ((Component)val).GetComponent<FollowTransform>(); Vector3 val2 = ((Component)val).transform.localPosition; if ((Object)(object)component != (Object)null && GetField<bool>(component, "initializedPosition")) { val2 = GetField<Vector3>(component, "PositionOffset"); } AbilityReadyIndicator val3 = ((field.Length > 3) ? field[3] : null); Vector3 val4 = (((Object)(object)val3 == (Object)null) ? val2 : ((val2 + IndicatorOffset(val3)) * 0.5f)); float num = 0.32f; if ((Object)(object)field[0] != (Object)null && (Object)(object)field[1] != (Object)null) { Vector3 val5 = IndicatorOffset(field[0]); num = Mathf.Max(0.28f, Mathf.Abs(IndicatorOffset(field[1]).x - val5.x) * 0.22f); } Vector3 offset = val4 + Vector3.right * num; Vector3 offset2 = val4 + Vector3.left * num; SetIndicatorOffset(val, controller, offset); AbilityReadyIndicator val6 = val3; GameObject val7 = (((Object)(object)val6 == (Object)null) ? Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent) : ((Component)val6).gameObject); if ((Object)(object)val6 == (Object)null) { ((Object)val7).name = "Fourth Ability Ready Indicator"; val6 = val7.GetComponent<AbilityReadyIndicator>(); if ((Object)(object)val6 != (Object)null) { val6.Init(); } } if ((Object)(object)val6 != (Object)null) { SetIndicatorOffset(val6, controller, offset2); if ((Object)(object)sprite != (Object)null) { val6.SetSprite(sprite, true); } ((Component)val6).gameObject.SetActive(true); } AbilityReadyIndicator[] array = (AbilityReadyIndicator[])(object)new AbilityReadyIndicator[Math.Max(4, field.Length)]; for (int i = 0; i < field.Length; i++) { array[i] = field[i]; } array[3] = val6; SetField(controller, "AbilityReadyIndicators", array); } internal static Vector3 IndicatorOffset(AbilityReadyIndicator indicator) { //IL_0009: 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_0032: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)indicator == (Object)null) { return Vector3.zero; } FollowTransform component = ((Component)indicator).GetComponent<FollowTransform>(); if ((Object)(object)component != (Object)null && GetField<bool>(component, "initializedPosition")) { return GetField<Vector3>(component, "PositionOffset"); } return ((Component)indicator).transform.localPosition; } internal static void SetIndicatorOffset(AbilityReadyIndicator indicator, SlimeController controller, Vector3 offset) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)indicator == (Object)null)) { ((Component)indicator).transform.localPosition = offset; FollowTransform component = ((Component)indicator).GetComponent<FollowTransform>(); if (!((Object)(object)component == (Object)null)) { component.Leader = ((Component)controller).transform; SetField(component, "PositionOffset", offset); } } } internal static void FinishSpawn(GameSessionHandler handler) { if ((Object)(object)handler == (Object)null) { return; } SlimeController[] field = GetField<SlimeController[]>(handler, "slimeControllers"); PlayerHandler val = PlayerHandler.Get(); if (field == null || val == null) { return; } foreach (SlimeController val2 in field) { if (!((Object)(object)val2 == (Object)null)) { List<AbilityMonoBehaviour> field2 = GetField<List<AbilityMonoBehaviour>>(val2, "abilities"); if (field2 == null || field2.Count < 4) { Log.LogError((object)("Player " + val2.GetPlayerId() + " spawned with " + (field2?.Count ?? 0) + " abilities; fourth ability injection failed before SpawnPlayers.")); continue; } Player player = val.GetPlayer(val2.GetPlayerId()); Sprite sprite = ((player != null && player.AbilityIcons != null && player.AbilityIcons.Count > 3) ? player.AbilityIcons[3] : null); AppendFourthIndicator(val2, sprite); EnsureCooldownArray(val2); AbilityReadyIndicator[] field3 = GetField<AbilityReadyIndicator[]>(val2, "AbilityReadyIndicators"); Fix[] field4 = GetField<Fix[]>(val2, "abilityCooldownTimers"); Log.LogInfo((object)("Fourth gameplay slot ready for player " + val2.GetPlayerId() + ": abilities=" + field2.Count + ", indicators=" + ((field3 != null) ? field3.Length : 0) + ", cooldowns=" + ((field4 != null) ? field4.Length : 0) + ".")); } } } internal static void AddFourthToClone(SlimeController clone, SlimeController source, Player player, AbilityReadyIndicator[] sourceIndicators) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)clone == (Object)null || (Object)(object)source == (Object)null) { return; } try { Sprite val = null; if (sourceIndicators != null && sourceIndicators.Length > 3 && (Object)(object)sourceIndicators[3] != (Object)null) { val = sourceIndicators[3].GetPrimarySprite(); } if ((Object)(object)val == (Object)null && player != null && player.AbilityIcons != null && player.AbilityIcons.Count > 3) { val = player.AbilityIcons[3]; } GameObject val2 = null; NamedSpriteList abilityIcons = source.abilityIcons; if ((Object)(object)abilityIcons != (Object)null && (Object)(object)val != (Object)null) { int num = abilityIcons.IndexOf(val); if (num >= 0 && num < abilityIcons.sprites.Count) { val2 = abilityIcons.sprites[num].associatedGameObject; } } if ((Object)(object)val2 == (Object)null && player != null && player.Abilities != null && player.Abilities.Count > 3) { val2 = player.Abilities[3]; } if ((Object)(object)val2 == (Object)null) { return; } GameObject val3 = FixTransform.InstantiateFixed(val2, Vec2.zero); val3.SetActive(false); AbilityMonoBehaviour component = val3.GetComponent<AbilityMonoBehaviour>(); List<AbilityMonoBehaviour> list = GetField<List<AbilityMonoBehaviour>>(clone, "abilities"); if (list == null) { list = new List<AbilityMonoBehaviour>(); SetField(clone, "abilities", list); } list.Add(component); AppendFourthIndicator(clone, val); EnsureCooldownArray(clone); Revive val4 = (((Object)(object)component == (Object)null) ? null : ((Component)component).GetComponent<Revive>()); if ((Object)(object)val4 != (Object)null && player != null && (Object)(object)player.ReviveInstance != (Object)null && ((Object)val4).GetInstanceID() == ((Object)player.ReviveInstance).GetInstanceID()) { Fix[] field = GetField<Fix[]>(clone, "abilityCooldownTimers"); if (field != null && field.Length > 3) { ref Fix reference = ref field[3]; reference = Fix.Zero; } } } catch (Exception ex) { Log.LogError((object)("Could not restore the fourth ability on a clone: " + ex)); } } internal static PickupState BeginVanillaPickup(SlimeController controller) { //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_00d9: 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) if ((Object)(object)controller == (Object)null) { return null; } List<AbilityMonoBehaviour> field = GetField<List<AbilityMonoBehaviour>>(controller, "abilities"); AbilityReadyIndicator[] field2 = GetField<AbilityReadyIndicator[]>(controller, "AbilityReadyIndicators"); Fix[] field3 = GetField<Fix[]>(controller, "abilityCooldownTimers"); if (field == null || field.Count < 4 || field2 == null || field2.Length < 4 || field3 == null || field3.Length < 4) { return null; } PickupState pickupState = new PickupState(); pickupState.FourthAbility = field[3]; pickupState.FourthIndicator = field2[3]; pickupState.FourthCooldown = field3[3]; pickupState.Active = true; List<AbilityMonoBehaviour> list = new List<AbilityMonoBehaviour>(); for (int i = 0; i < 3; i++) { list.Add(field[i]); } AbilityReadyIndicator[] array = (AbilityReadyIndicator[])(object)new AbilityReadyIndicator[3]; Fix[] array2 = (Fix[])(object)new Fix[3]; for (int j = 0; j < 3; j++) { array[j] = field2[j]; ref Fix reference = ref array2[j]; reference = field3[j]; } SetField(controller, "abilities", list); SetField(controller, "AbilityReadyIndicators", array); SetField(controller, "abilityCooldownTimers", array2); return pickupState; } internal static void EndVanillaPickup(SlimeController controller, PickupState state) { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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) if (!((Object)(object)controller == (Object)null) && state != null && state.Active) { state.Active = false; List<AbilityMonoBehaviour> list = GetField<List<AbilityMonoBehaviour>>(controller, "abilities"); if (list == null) { list = new List<AbilityMonoBehaviour>(); } while (list.Count > 3) { list.RemoveAt(list.Count - 1); } while (list.Count < 3) { list.Add(null); } list.Add(state.FourthAbility); SetField(controller, "abilities", list); AbilityReadyIndicator[] field = GetField<AbilityReadyIndicator[]>(controller, "AbilityReadyIndicators"); AbilityReadyIndicator[] array = (AbilityReadyIndicator[])(object)new AbilityReadyIndicator[4]; for (int i = 0; i < 3; i++) { array[i] = ((field != null && field.Length > i) ? field[i] : null); } array[3] = state.FourthIndicator; SetField(controller, "AbilityReadyIndicators", array); Fix[] field2 = GetField<Fix[]>(controller, "abilityCooldownTimers"); Fix[] array2 = (Fix[])(object)new Fix[4]; for (int j = 0; j < 3; j++) { ref Fix reference = ref array2[j]; reference = ((field2 != null && field2.Length > j) ? field2[j] : ((Fix)(-1.5f))); } ref Fix reference2 = ref array2[3]; reference2 = state.FourthCooldown; SetField(controller, "abilityCooldownTimers", array2); Log.LogInfo((object)"Ability pickup replaced slot 3 and preserved fourth slot."); } } } [HarmonyPatch(typeof(KeyBindButton), "Awake")] internal static class KeyBindAwakePatch { private static void Prefix(KeyBindButton __instance) { FourthAbilityRuntime.PrepareKeyBindMenu(__instance); } private static void Postfix(KeyBindButton __instance) { FourthAbilityRuntime.FinishKeyBindMenu(__instance); } } [HarmonyPatch(typeof(KeyBindButton), "SetToPlayerChoices")] internal static class KeyBindPlayerChoicesPatch { internal sealed class BindingState { internal Player Player; internal InputControl[] Canonical; } private static void Prefix(Player player, ref BindingState __state) { FourthAbilityRuntime.EnsureFourthBinding(player); if (player != null) { __state = new BindingState(); __state.Player = player; __state.Canonical = player.CustomKeyBinding; player.CustomKeyBinding = FourthAbilityRuntime.ToBindingMenuOrder(player); } } private static void Postfix(BindingState __state) { if (__state != null && __state.Player != null) { __state.Player.CustomKeyBinding = __state.Canonical; } } private static Exception Finalizer(Exception __exception, BindingState __state) { if (__state != null && __state.Player != null) { __state.Player.CustomKeyBinding = __state.Canonical; } return __exception; } } [HarmonyPatch(typeof(KeyBindButton), "UpdateKeybind")] internal static class KeyBindUpdatePatch { private static bool Prefix(KeyBindButton __instance) { //IL_006f: 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_0085: Unknown result type (might be due to invalid IL or missing references) CharacterSelectBox field = FourthAbilityRuntime.GetField<CharacterSelectBox>(__instance, "charSelectBox"); if ((Object)(object)field == (Object)null) { return true; } bool field2 = FourthAbilityRuntime.GetField<bool>(field, "UseskeyboardMouse"); InputControl[] field3 = FourthAbilityRuntime.GetField<InputControl[]>(__instance, field2 ? "newBinding_keyboardMouse" : "newBinding_gamepad"); if (field3 == null || field3.Length <= 8) { return true; } int boxKey = FourthAbilityRuntime.GetBoxKey(field); if (boxKey != int.MinValue) { FourthAbilityRuntime.FourthBindings[boxKey] = field3[0]; } InputControl[] keybindOverride = FourthAbilityRuntime.ToVanillaBindingOrder(field3); PlayerInit field4 = FourthAbilityRuntime.GetField<PlayerInit>(field, "playerInit"); field4.keybindOverride = keybindOverride; FourthAbilityRuntime.SetField(field, "playerInit", field4); FourthAbilityRuntime.Log.LogInfo((object)"Saved A4 binding without changing Bopl's fixed eight-control local-start data."); return false; } } [HarmonyPatch(typeof(InputUpdater), "Init")] internal static class InputUpdaterInitPatch { internal sealed class BindingState { internal Player Player; internal InputControl[] FullBinding; } private static void Prefix(int __0, ref BindingState __state) { PlayerHandler val = PlayerHandler.Get(); Player val2 = ((val == null) ? null : val.GetPlayer(__0)); if (val2 != null) { InputControl[] array = FourthAbilityRuntime.HideFourthBinding(val2); if (array != null) { __state = new BindingState(); __state.Player = val2; __state.FullBinding = array; } } } private static void Postfix(BindingState __state) { if (__state != null && __state.Player != null && __state.FullBinding != null) { __state.Player.CustomKeyBinding = __state.FullBinding; } } private static Exception Finalizer(BindingState __state, Exception __exception) { if (__state != null && __state.Player != null && __state.FullBinding != null) { __state.Player.CustomKeyBinding = __state.FullBinding; } return __exception; } } [HarmonyPatch(typeof(SlimeController), "AddAdditionalAbility")] internal static class AbilityPickupPatch { private static void Prefix(SlimeController __instance, ref FourthAbilityRuntime.PickupState __state) { __state = FourthAbilityRuntime.BeginVanillaPickup(__instance); } private static void Postfix(SlimeController __instance, FourthAbilityRuntime.PickupState __state) { FourthAbilityRuntime.EndVanillaPickup(__instance, __state); } private static Exception Finalizer(SlimeController __instance, Exception __exception, FourthAbilityRuntime.PickupState __state) { FourthAbilityRuntime.EndVanillaPickup(__instance, __state); return __exception; } } [HarmonyPatch(typeof(CharacterSelectBox), "Awake")] internal static class CharacterSelectAwakePatch { private static void Postfix(CharacterSelectBox __instance) { FourthAbilityRuntime.CreateFourthSlot(__instance); } } [HarmonyPatch(typeof(CharacterSelectBox), "UpdatePlayerInit")] internal static class CharacterSelectSavePatch { private static void Postfix(CharacterSelectBox __instance) { FourthAbilityRuntime.SaveChoice(__instance); } } [HarmonyPatch(typeof(SelectAbility), "Select")] internal static class FourthSelectPatch { private static void Postfix(SelectAbility __instance) { if (FourthAbilityRuntime.BoxesBySlot.TryGetValue(((Object)__instance).GetInstanceID(), out var value)) { FourthAbilityRuntime.SaveChoice(value); } } } [HarmonyPatch(typeof(CharacterSelectBox), "LateUpdate")] internal static class FourthSlotEnterPatch { private static bool Prefix(CharacterSelectBox __instance) { object field = FourthAbilityRuntime.GetField<object>(__instance, "menuState"); if (field == null || Convert.ToInt32(field) != 1) { return true; } if (!FourthAbilityRuntime.SlotsByBox.TryGetValue(((Object)__instance).GetInstanceID(), out var value) || (Object)(object)value == (Object)null) { return true; } List<SelectableMonoBehaviour> field2 = FourthAbilityRuntime.GetField<List<SelectableMonoBehaviour>>(__instance, "selectables"); int field3 = FourthAbilityRuntime.GetField<int>(__instance, "selectedIndex"); if (field2 == null || field3 != field2.IndexOf((SelectableMonoBehaviour)(object)value)) { return true; } bool flag = false; if (FourthAbilityRuntime.GetField<bool>(__instance, "UseskeyboardMouse")) { Keyboard current = Keyboard.current; flag = current != null && ((ButtonControl)current.enterKey).wasPressedThisFrame; } else { Gamepad field4 = FourthAbilityRuntime.GetField<Gamepad>(__instance, "currentGamePad"); flag = field4 != null && field4.aButton.wasPressedThisFrame; } if (!flag) { return true; } FourthAbilityRuntime.SaveChoice(__instance); __instance.EnterAbilityGrid(); return false; } } [HarmonyPatch(typeof(CharacterSelectBox), "SetSelected")] internal static class CharacterSelectArrowPatch { private static void Postfix(CharacterSelectBox __instance, int __0) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) List<SelectableMonoBehaviour> field = FourthAbilityRuntime.GetField<List<SelectableMonoBehaviour>>(__instance, "selectables"); if (field != null && __0 == field.Count - 1) { RectTransform field2 = FourthAbilityRuntime.GetField<RectTransform>(__instance, "arrows"); if (!((Object)(object)field2 == (Object)null)) { Vector2 anchoredPosition = field2.anchoredPosition; anchoredPosition.y = -1024f; field2.anchoredPosition = anchoredPosition; } } } } [HarmonyPatch(typeof(MidGameAbilitySelect), "SetPlayer")] internal static class MidGameSetPlayerPatch { private static void Prefix(MidGameAbilitySelect __instance, ref RectTransform[] __state) { RectTransform[] field = FourthAbilityRuntime.GetField<RectTransform[]>(__instance, "Circles"); if (field != null && field.Length > 3) { __state = field; RectTransform[] array = (RectTransform[])(object)new RectTransform[3]; for (int i = 0; i < 3; i++) { array[i] = field[i]; } if ((Object)(object)field[3] != (Object)null) { ((Component)field[3]).gameObject.SetActive(false); } FourthAbilityRuntime.SetField(__instance, "Circles", array); } } private static void Postfix(MidGameAbilitySelect __instance, RectTransform[] __state) { if (__state != null) { FourthAbilityRuntime.SetField(__instance, "Circles", __state); } FourthAbilityRuntime.EnsureMidGameFourthCircle(__instance); FourthAbilityRuntime.PrepareMidGameSelector(__instance); } private static Exception Finalizer(MidGameAbilitySelect __instance, Exception __exception, RectTransform[] __state) { if (__state != null) { FourthAbilityRuntime.SetField(__instance, "Circles", __state); } return __exception; } } [HarmonyPatch(typeof(MidGameAbilitySelect), "TotalYOffset")] internal static class MidGameTotalOffsetPatch { private static void Postfix(MidGameAbilitySelect __instance, ref float __result) { } } [HarmonyPatch(typeof(MidGameAbilitySelect), "Down")] internal static class MidGameDownPatch { private static bool Prefix(MidGameAbilitySelect __instance) { return !FourthAbilityRuntime.MoveMidGameRow(__instance, 1); } } [HarmonyPatch(typeof(MidGameAbilitySelect), "Up")] internal static class MidGameUpPatch { private static bool Prefix(MidGameAbilitySelect __instance) { return !FourthAbilityRuntime.MoveMidGameRow(__instance, -1); } } [HarmonyPatch(typeof(MidGameAbilitySelect), "UpdatePlayerAbilityChoices")] internal static class MidGameChoicePatch { private static void Postfix(MidGameAbilitySelect __instance) { FourthAbilityRuntime.SaveMidGameFourthChoice(__instance); } } [HarmonyPatch(typeof(AbilitySelectController), "UpdateAnimation")] internal static class AbilitySelectAnimationPatch { private static void Prefix(AbilitySelectController __instance) { FourthAbilityRuntime.EnsureAbilitySelectAnimationTargets(__instance); } } [HarmonyPatch(typeof(Player), "AbilityButtonIsDown")] internal static class FourthAbilityInputPatch { private static bool Prefix(Player __instance, int index012, ref bool __result) { if (index012 != 3) { return true; } __result = FourthAbilityRuntime.FourthInputHeld(__instance); return false; } } [HarmonyPatch(typeof(Host), "CurrentInputAsPacket")] internal static class FourthAbilityPacketPatch { private static void Postfix(int __0, ref InputPacket __result) { FourthAbilityRuntime.PutFourthInputInPacket(__0, ref __result); } } [HarmonyPatch(typeof(GameSessionHandler), "SpawnPlayers")] internal static class SpawnPlayersPatch { private static void Prefix() { PlayerHandler val = PlayerHandler.Get(); if (val != null) { FourthAbilityRuntime.AddFourthToPlayers(val.PlayerList()); } } private static void Postfix(GameSessionHandler __instance) { FourthAbilityRuntime.FinishSpawn(__instance); } } [HarmonyPatch(typeof(SlimeController), "Init")] internal static class SlimeInitPatch { private static void Postfix(SlimeController __instance) { List<AbilityMonoBehaviour> field = FourthAbilityRuntime.GetField<List<AbilityMonoBehaviour>>(__instance, "abilities"); if (field != null && field.Count > 3) { FourthAbilityRuntime.EnsureCooldownArray(__instance); } } } [HarmonyPatch(typeof(PlayerCollision), "SpawnClone")] internal static class SpawnClonePatch { internal sealed class CloneState { internal SlimeController Source; internal List<AbilityMonoBehaviour> Abilities; internal AbilityReadyIndicator[] Indicators; } private static void Prefix(SlimeController slimeContToRevive, ref CloneState __state) { if ((Object)(object)slimeContToRevive == (Object)null) { return; } List<AbilityMonoBehaviour> field = FourthAbilityRuntime.GetField<List<AbilityMonoBehaviour>>(slimeContToRevive, "abilities"); AbilityReadyIndicator[] field2 = FourthAbilityRuntime.GetField<AbilityReadyIndicator[]>(slimeContToRevive, "AbilityReadyIndicators"); if (field != null && field.Count >= 4 && field2 != null && field2.Length >= 4) { __state = new CloneState(); __state.Source = slimeContToRevive; __state.Abilities = field; __state.Indicators = field2; List<AbilityMonoBehaviour> list = new List<AbilityMonoBehaviour>(); for (int i = 0; i < 3; i++) { list.Add(field[i]); } AbilityReadyIndicator[] array = (AbilityReadyIndicator[])(object)new AbilityReadyIndicator[3]; for (int j = 0; j < 3; j++) { array[j] = field2[j]; } FourthAbilityRuntime.SetField(slimeContToRevive, "abilities", list); FourthAbilityRuntime.SetField(slimeContToRevive, "AbilityReadyIndicators", array); } } private static void Postfix(Player player, SlimeController slimeContToRevive, ref SlimeController __result, CloneState __state) { if (__state != null) { FourthAbilityRuntime.SetField(slimeContToRevive, "abilities", __state.Abilities); FourthAbilityRuntime.SetField(slimeContToRevive, "AbilityReadyIndicators", __state.Indicators); if ((Object)(object)__result != (Object)null) { FourthAbilityRuntime.AddFourthToClone(__result, __state.Source, player, __state.Indicators); } } } private static Exception Finalizer(SlimeController slimeContToRevive, Exception __exception, CloneState __state) { if (__state != null && (Object)(object)slimeContToRevive != (Object)null) { FourthAbilityRuntime.SetField(slimeContToRevive, "abilities", __state.Abilities); FourthAbilityRuntime.SetField(slimeContToRevive, "AbilityReadyIndicators", __state.Indicators); } return __exception; } } [HarmonyPatch(typeof(SteamSocket), "OnMessage")] internal static class FourthAbilityNetworkReceivePatch { private static bool Prefix(NetIdentity identity, IntPtr data, int size) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (size < 5 || data == IntPtr.Zero) { return true; } byte[] array = new byte[size]; Marshal.Copy(data, array, 0, size); if (!FourthAbilityRuntime.IsOurPacket(array)) { return true; } FourthAbilityRuntime.ReceivePacket(array, identity); return false; } }
BepInEx\plugins\FourthAbility\FourthAbilitySlotStableRepair.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace FourthAbilitySlotStableRepair; [BepInPlugin("com.openai.boplbattle.fourthabilityslot.stablerepair", "Fourth Ability Slot Stable Repair", "1.1.18")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class StableRepairPlugin : BaseUnityPlugin { internal const string PluginGuid = "com.openai.boplbattle.fourthabilityslot.stablerepair"; internal const string PluginVersion = "1.1.18"; internal const string BasePluginGuid = "com.openai.boplbattle.fourthabilityslot"; private Harmony harmony; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown RepairRuntime.Log = ((BaseUnityPlugin)this).Logger; RepairRuntime.InitializeBaseReflection(); harmony = new Harmony("com.openai.boplbattle.fourthabilityslot.stablerepair"); RepairRuntime.RemoveBrokenBaseUiHooks(harmony); harmony.PatchAll(); bool flag = RepairRuntime.PatchBaseRawInput(harmony); bool flag2 = RepairRuntime.PatchBaseIndicatorCreation(harmony); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Stable Repair v1.1.18 active on Fourth Ability Slot v1.1.3."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loss selector now preserves Bopl's three vanilla animation targets exactly and only extrapolates a fourth target after SetPlayer."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Gameplay HUD now leaves v1.1.3's proven diamond layout untouched on spawn; a one-shot A3 visibility gate prevents the early A4 flash without coupling cooldown visuals."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Player 2 A4 direct-input repair=" + flag + "; indicator creation repair=" + flag2 + ".")); ((BaseUnityPlugin)this).Logger.LogInfo((object)"F6 HUD layout hotkey is polled from both the plugin frame loop and Host.CurrentInputAsPacket using Win32, Input System, and BepInEx KeyboardShortcut detection."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"No NumberOfAbilities selector patch, Settings save, forced lobby setting, or layout-picker UI is installed."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"v1.1.18 changes only the loss-screen vertical offsets again: the live four ability circles are now lifted +105px and the arrow is +95px, putting the stack closer to directly above the losing-player portrait. All other behavior is unchanged."); } private void Update() { RepairRuntime.PollLayoutHotkey(); } } [DefaultExecutionOrder(20000)] internal sealed class MidGameFourthFollower : MonoBehaviour { internal RectTransform Third; internal RectTransform Fourth; internal Image ThirdImage; internal Image FourthImage; private void LateUpdate() { if ((Object)(object)Third == (Object)null || (Object)(object)Fourth == (Object)null) { return; } bool activeSelf = ((Component)Third).gameObject.activeSelf; if (((Component)Fourth).gameObject.activeSelf != activeSelf) { ((Component)Fourth).gameObject.SetActive(activeSelf); } if (activeSelf) { RepairRuntime.CopyUiTreeAppearance((Component)(object)Third, (Component)(object)Fourth, ThirdImage, FourthImage); CanvasGroup component = ((Component)Third).GetComponent<CanvasGroup>(); CanvasGroup component2 = ((Component)Fourth).GetComponent<CanvasGroup>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { component2.alpha = component.alpha; component2.interactable = component.interactable; component2.blocksRaycasts = component.blocksRaycasts; } } } } [DefaultExecutionOrder(25000)] internal sealed class GameplayFourthVisualFollower : MonoBehaviour { internal AbilityReadyIndicator Source; internal AbilityReadyIndicator Target; private bool released; internal void SyncNow() { if (released || (Object)(object)Source == (Object)null || (Object)(object)Target == (Object)null) { return; } SpriteRenderer[] componentsInChildren = ((Component)Source).GetComponentsInChildren<SpriteRenderer>(true); SpriteRenderer[] componentsInChildren2 = ((Component)Target).GetComponentsInChildren<SpriteRenderer>(true); int num = Math.Min(componentsInChildren.Length, componentsInChildren2.Length); bool flag = false; foreach (SpriteRenderer val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Component)Source).gameObject.activeInHierarchy && ((Renderer)val).enabled) { flag = true; break; } } for (int j = 0; j < num; j++) { if (!((Object)(object)componentsInChildren[j] == (Object)null) && !((Object)(object)componentsInChildren2[j] == (Object)null)) { ((Renderer)componentsInChildren2[j]).enabled = ((Component)Source).gameObject.activeInHierarchy && ((Renderer)componentsInChildren[j]).enabled; } } if (flag) { released = true; Object.Destroy((Object)(object)this); } } private void LateUpdate() { SyncNow(); } } internal sealed class IndicatorLayoutState : MonoBehaviour { internal SlimeController Controller; internal Vector3 First; internal Vector3 Second; internal Vector3 Third; internal bool Ready; internal void Initialize(SlimeController controller, Vector3[] original) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_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_007e: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (Ready || (Object)(object)controller == (Object)null) { return; } AbilityReadyIndicator[] field = RepairRuntime.GetField<AbilityReadyIndicator[]>(controller, "AbilityReadyIndicators"); if (field != null && field.Length >= 4 && !((Object)(object)field[0] == (Object)null) && !((Object)(object)field[1] == (Object)null) && !((Object)(object)field[2] == (Object)null) && !((Object)(object)field[3] == (Object)null)) { Controller = controller; if (original != null && original.Length >= 3) { First = original[0]; Second = original[1]; Third = original[2]; } else { First = RepairRuntime.IndicatorOffset(field[0]); Second = RepairRuntime.IndicatorOffset(field[1]); Third = (RepairRuntime.IndicatorOffset(field[2]) + RepairRuntime.IndicatorOffset(field[3])) * 0.5f; } Ready = true; } } } internal sealed class MidGameState { internal Settings Settings; internal FieldInfo RawAbilityCountField; internal int RawAbilityCount; internal bool ChangedRawAbilityCount; internal RectTransform[] FullCircles; } internal sealed class LossArrowCounterLiftState : MonoBehaviour { internal RectTransform ArrowRoot; internal Vector2 ArrowBase; internal Vector2 ArrowShifted; internal bool Applied; internal bool Logged; } internal sealed class LossAbilityVisualLiftState : MonoBehaviour { internal RectTransform[] Circles; internal Vector2[] BasePositions; internal Vector2[] ShiftedPositions; internal bool Applied; internal bool Logged; } internal static class RepairRuntime { private const int VkF6 = 117; internal static ManualLogSource Log; private static bool previousF6; private static int lastF6PollFrame = -1; private static bool loggedF6Poller; private static readonly KeyboardShortcut LayoutShortcut = new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[0]); private static Type baseRuntimeType; private static MethodInfo baseInstallMidGamePointer; private static MethodInfo baseFourthBindingFor; private static MethodInfo baseRawFourthInputHeld; private static MethodInfo baseAppendFourthIndicator; private static FieldInfo baseSlotsByBox; private static readonly Dictionary<int, Vector3[]> PendingIndicatorOriginals = new Dictionary<int, Vector3[]>(); private static readonly HashSet<int> LoggedMidGameSelectors = new HashSet<int>(); private static readonly HashSet<int> LossSelectorLiftApplied = new HashSet<int>(); private static readonly HashSet<int> LoggedInputConfirmed = new HashSet<int>(); private static readonly HashSet<int> LoggedInputRoutes = new HashSet<int>(); private static readonly string[] LayoutNames = new string[5] { "A4 left / A3 right", "A4 below A3", "A3 left / A4 right", "A4 above A3", "single row" }; internal static int CurrentLayout => Mathf.Clamp(PlayerPrefs.GetInt("FourthAbilitySlot.LayoutPreset", 0), 0, 4); [DllImport("user32.dll")] private static extern short GetAsyncKeyState(int virtualKey); internal static void PollLayoutHotkey() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) int frameCount = Time.frameCount; if (lastF6PollFrame == frameCount) { return; } lastF6PollFrame = frameCount; bool flag = false; bool flag2 = false; try { short asyncKeyState = GetAsyncKeyState(117); if ((asyncKeyState & 0x8000) != 0) { flag = true; } if ((asyncKeyState & 1) != 0) { flag2 = true; } } catch { } try { Keyboard current = Keyboard.current; if (current != null) { if (((ButtonControl)current.f6Key).isPressed) { flag = true; } if (((ButtonControl)current.f6Key).wasPressedThisFrame) { flag2 = true; } } } catch { } try { KeyboardShortcut layoutShortcut = LayoutShortcut; if (((KeyboardShortcut)(ref layoutShortcut)).IsDown()) { flag2 = true; } } catch { } if (!loggedF6Poller) { loggedF6Poller = true; Log.LogInfo((object)"F6 layout hotkey poller is running (frame loop + gameplay packet hook)."); } if (flag2 || (flag && !previousF6)) { CycleLayout(); } previousF6 = flag; } internal static void InitializeBaseReflection() { baseRuntimeType = AccessTools.TypeByName("FourthAbilitySlotMod.FourthAbilityRuntime"); if (baseRuntimeType == null) { Log.LogError((object)"Could not find FourthAbilitySlotMod.FourthAbilityRuntime. Refusing to guess an unknown base implementation."); return; } baseInstallMidGamePointer = AccessTools.Method(baseRuntimeType, "InstallMidGamePointer", new Type[2] { typeof(MidGameAbilitySelect), typeof(RectTransform) }, (Type[])null); baseFourthBindingFor = AccessTools.Method(baseRuntimeType, "FourthBindingFor", new Type[1] { typeof(Player) }, (Type[])null); baseRawFourthInputHeld = AccessTools.Method(baseRuntimeType, "RawFourthInputHeld", new Type[1] { typeof(Player) }, (Type[])null); baseAppendFourthIndicator = AccessTools.Method(baseRuntimeType, "AppendFourthIndicator", new Type[2] { typeof(SlimeController), typeof(Sprite) }, (Type[])null); baseSlotsByBox = AccessTools.Field(baseRuntimeType, "SlotsByBox"); } internal static T GetField<T>(object instance, string name) { if (instance == null) { return default(T); } FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), name); if (fieldInfo == null) { return default(T); } object value = fieldInfo.GetValue(instance); if (value == null) { return default(T); } return (T)value; } internal static void SetField(object instance, string name, object value) { if (instance != null) { FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), name); if (fieldInfo != null) { fieldInfo.SetValue(instance, value); } } } internal static void CopyImageAppearance(Image source, Image target) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null)) { ((Graphic)target).color = ((Graphic)source).color; ((Graphic)target).material = ((Graphic)source).material; ((Behaviour)target).enabled = ((Behaviour)source).enabled; ((Graphic)target).canvasRenderer.SetAlpha(((Graphic)source).canvasRenderer.GetAlpha()); } } internal static void CopyUiTreeAppearance(Component sourceRoot, Component targetRoot, Image sourceAbilityImage, Image targetAbilityImage) { if ((Object)(object)sourceRoot == (Object)null || (Object)(object)targetRoot == (Object)null) { return; } Image[] componentsInChildren = sourceRoot.GetComponentsInChildren<Image>(true); Image[] componentsInChildren2 = targetRoot.GetComponentsInChildren<Image>(true); int num = Math.Min(componentsInChildren.Length, componentsInChildren2.Length); for (int i = 0; i < num; i++) { Image val = componentsInChildren[i]; Image val2 = componentsInChildren2[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null)) { Sprite sprite = val2.sprite; CopyImageAppearance(val, val2); if ((Object)(object)val2 == (Object)(object)targetAbilityImage || (Object)(object)val == (Object)(object)sourceAbilityImage) { val2.sprite = sprite; } } } } internal static void RemoveBrokenBaseUiHooks(Harmony harmony) { if (harmony != null) { UnpatchBase(harmony, typeof(MidGameAbilitySelect), "SetPlayer"); UnpatchBase(harmony, typeof(MidGameAbilitySelect), "TotalYOffset"); UnpatchBase(harmony, typeof(CharacterSelectBox), "SetSelected"); UnpatchBase(harmony, typeof(MidGameAbilitySelect), "Update"); UnpatchBase(harmony, typeof(AbilitySelectController), "UpdateAnimation"); Log.LogInfo((object)"Replaced only the broken v1.1.3 UI lifecycle hooks; gameplay, pickups, clones, keybind menu, online packets, and A4 navigation remain on the base mod."); } } private static void UnpatchBase(Harmony harmony, Type type, string methodName) { MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)0, "com.openai.boplbattle.fourthabilityslot"); } } internal static bool PatchBaseRawInput(Harmony harmony) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown if (harmony == null || baseRawFourthInputHeld == null) { return false; } MethodInfo methodInfo = AccessTools.Method(typeof(RepairRuntime), "RawFourthInputPrefix", (Type[])null, (Type[])null); if (methodInfo == null) { return false; } harmony.Patch((MethodBase)baseRawFourthInputHeld, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return true; } internal static bool PatchBaseIndicatorCreation(Harmony harmony) { //IL_005b: 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_006e: Expected O, but got Unknown //IL_006e: Expected O, but got Unknown if (harmony == null || baseAppendFourthIndicator == null) { return false; } MethodInfo methodInfo = AccessTools.Method(typeof(RepairRuntime), "AppendFourthIndicatorPrefix", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(RepairRuntime), "AppendFourthIndicatorPostfix", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { return false; } harmony.Patch((MethodBase)baseAppendFourthIndicator, new HarmonyMethod(methodInfo), new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return true; } internal static bool RawFourthInputPrefix(Player __0, ref bool __result) { if (__0 == null || __0.ignoreAllInputs || !__0.IsLocalPlayer) { return true; } InputControl val = ControlForPlayer(__0); ButtonControl val2 = (ButtonControl)(object)((val is ButtonControl) ? val : null); __result = val2 != null && val2.isPressed; if (__result && LoggedInputConfirmed.Add(__0.Id)) { Log.LogInfo((object)("A4 input confirmed for local player " + __0.Id + " via " + DescribeControl(val) + ".")); } return false; } private static InputControl ControlForPlayer(Player player) { if (player == null) { return null; } InputControl val = null; if (baseFourthBindingFor != null) { try { object? obj = baseFourthBindingFor.Invoke(null, new object[1] { player }); val = (InputControl)((obj is InputControl) ? obj : null); } catch { } } if (player.UsesKeyboardAndMouse) { if (val != null) { return val; } Mouse current = Mouse.current; if (current != null) { return (InputControl)(object)current.middleButton; } return null; } Gamepad val2 = ResolvePlayerGamepad(player); if (val2 != null) { if (val != null && (object)val.device == val2) { return val; } return (InputControl)(object)val2.rightTrigger; } return val; } private static Gamepad ResolvePlayerGamepad(Player player) { if (player == null) { return null; } InputDevice inputDevice = player.inputDevice; Gamepad val = (Gamepad)(object)((inputDevice is Gamepad) ? inputDevice : null); if (val != null) { return val; } InputControl[] customKeyBinding = player.CustomKeyBinding; if (customKeyBinding != null) { foreach (InputControl val2 in customKeyBinding) { if (val2 != null) { InputDevice device = val2.device; Gamepad val3 = (Gamepad)(object)((device is Gamepad) ? device : null); if (val3 != null) { return val3; } } } } return null; } private static string DescribeControl(InputControl control) { if (control == null) { return "no control"; } try { string text = ((control.device == null) ? "unknown device" : ((InputControl)control.device).displayName); return text + " " + control.path; } catch { return ((object)control).ToString(); } } internal static void AppendFourthIndicatorPrefix(SlimeController __0) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__0 == (Object)null) { return; } int instanceID = ((Object)__0).GetInstanceID(); IndicatorLayoutState component = ((Component)__0).GetComponent<IndicatorLayoutState>(); if ((!((Object)(object)component != (Object)null) || !component.Ready) && !PendingIndicatorOriginals.ContainsKey(instanceID)) { AbilityReadyIndicator[] field = GetField<AbilityReadyIndicator[]>(__0, "AbilityReadyIndicators"); if (field != null && field.Length >= 3 && !((Object)(object)field[0] == (Object)null) && !((Object)(object)field[1] == (Object)null) && !((Object)(object)field[2] == (Object)null)) { PendingIndicatorOriginals[instanceID] = (Vector3[])(object)new Vector3[3] { IndicatorOffset(field[0]), IndicatorOffset(field[1]), IndicatorOffset(field[2]) }; } } } internal static void AppendFourthIndicatorPostfix(SlimeController __0, Sprite __1) { AttachGameplayHud(__0); } internal static void BeforeMidGameSetPlayer(MidGameAbilitySelect selector, ref MidGameState state) { state = new MidGameState(); if ((Object)(object)selector != (Object)null) { LossSelectorLiftApplied.Remove(((Object)selector).GetInstanceID()); } try { Settings val = Settings.Get(); FieldInfo fieldInfo = (((Object)(object)val == (Object)null) ? null : AccessTools.Field(((object)val).GetType(), "numberOfAbilities")); if ((Object)(object)val != (Object)null && fieldInfo != null) { int num = (int)fieldInfo.GetValue(val); state.Settings = val; state.RawAbilityCountField = fieldInfo; state.RawAbilityCount = num; if (num > 3) { fieldInfo.SetValue(val, 3); state.ChangedRawAbilityCount = true; } } } catch (Exception ex) { Log.LogWarning((object)("Could not temporarily vanilla-size SetPlayer's raw ability count: " + ex.Message)); } RectTransform[] field = GetField<RectTransform[]>(selector, "Circles"); if (field != null && field.Length > 3) { state.FullCircles = field; RectTransform[] array = (RectTransform[])(object)new RectTransform[3]; for (int i = 0; i < 3; i++) { array[i] = field[i]; } if ((Object)(object)field[3] != (Object)null) { ((Component)field[3]).gameObject.SetActive(false); } SetField(selector, "Circles", array); } } internal static void RestoreMidGameSetPlayer(MidGameAbilitySelect selector, MidGameState state) { if (state == null) { return; } if (state.FullCircles != null) { SetField(selector, "Circles", state.FullCircles); } if (!state.ChangedRawAbilityCount || !((Object)(object)state.Settings != (Object)null) || !(state.RawAbilityCountField != null)) { return; } try { state.RawAbilityCountField.SetValue(state.Settings, state.RawAbilityCount); } catch (Exception ex) { Log.LogError((object)("Could not restore raw NumberOfAbilities after SetPlayer: " + ex.Message)); } } internal static void SetupSafeMidGameSelector(MidGameAbilitySelect selector) { //IL_00fa: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016a: 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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)selector == (Object)null) { return; } Player field = GetField<Player>(selector, "player"); if (field == null || field.Abilities == null || field.Abilities.Count < 4) { return; } RectTransform[] array = GetField<RectTransform[]>(selector, "Circles"); if (array == null || array.Length < 3 || (Object)(object)array[1] == (Object)null || (Object)(object)array[2] == (Object)null) { return; } RectTransform val = ((array.Length > 3) ? array[3] : null); if ((Object)(object)val == (Object)null) { GameObject val2 = Object.Instantiate<GameObject>(((Component)array[2]).gameObject, ((Transform)array[2]).parent); ((Object)val2).name = "Fourth Between-Round Ability Circle"; val2.transform.SetSiblingIndex(((Transform)array[2]).GetSiblingIndex() + 1); val = val2.GetComponent<RectTransform>(); if ((Object)(object)val == (Object)null) { Object.Destroy((Object)(object)val2); return; } RectTransform[] array2 = (RectTransform[])(object)new RectTransform[4]; for (int i = 0; i < 3; i++) { array2[i] = array[i]; } array2[3] = val; array = array2; SetField(selector, "Circles", array); } Vector2 val3 = array[2].anchoredPosition - array[1].anchoredPosition; if (((Vector2)(ref val3)).sqrMagnitude < 0.0001f) { float field2 = GetField<float>(selector, "circleDistance"); val3 = Vector2.down * ((Mathf.Abs(field2) > 0.01f) ? Mathf.Abs(field2) : 60f); } val.anchoredPosition = array[2].anchoredPosition + val3; ((Transform)val).localScale = ((Transform)array[2]).localScale; ((Component)val).gameObject.SetActive(((Component)array[2]).gameObject.activeSelf); if (baseInstallMidGamePointer != null) { try { baseInstallMidGamePointer.Invoke(null, new object[2] { selector, val }); } catch (Exception ex) { Log.LogWarning((object)("Could not install the proven v1.1.3 A4 loss-selector pointer: " + ex.Message)); } } PrepareSafeMidGameSelector(selector); AbilitySelectController componentInParent = ((Component)selector).GetComponentInParent<AbilitySelectController>(); EnsureAbilitySelectAnimationTargets(componentInParent); LiftLossSelectorSlightly(selector, componentInParent); Image[] field3 = GetField<Image[]>(selector, "CircleImages"); MidGameFourthFollower midGameFourthFollower = ((Component)selector).GetComponent<MidGameFourthFollower>(); if ((Object)(object)midGameFourthFollower == (Object)null) { midGameFourthFollower = ((Component)selector).gameObject.AddComponent<MidGameFourthFollower>(); } midGameFourthFollower.Third = array[2]; midGameFourthFollower.Fourth = array[3]; midGameFourthFollower.ThirdImage = ((field3 != null && field3.Length > 2) ? field3[2] : null); midGameFourthFollower.FourthImage = ((field3 != null && field3.Length > 3) ? field3[3] : null); int instanceID = ((Object)selector).GetInstanceID(); if (LoggedMidGameSelectors.Add(instanceID)) { Log.LogInfo((object)("Loss selector repaired for player " + field.Id + ": vanilla A1-A3 targets preserved; A4 appended after SetPlayer.")); } } private static void LayoutSafeMidGameRows(MidGameAbilitySelect selector, Vector2[] originals) { } private static void PrepareSafeMidGameSelector(MidGameAbilitySelect selector) { Player field = GetField<Player>(selector, "player"); RectTransform[] field2 = GetField<RectTransform[]>(selector, "Circles"); NamedSpriteList field3 = GetField<NamedSpriteList>(selector, "localAbilityIcons"); if (field != null && field.Abilities != null && field.Abilities.Count >= 4 && field2 != null && field2.Length >= 4 && !((Object)(object)field2[3] == (Object)null) && !((Object)(object)field3 == (Object)null)) { Image[] field4 = GetField<Image[]>(selector, "CircleImages"); int[] field5 = GetField<int[]>(selector, "XPos"); Image[] array = (Image[])(object)new Image[4]; int[] array2 = new int[4]; for (int i = 0; i < 3; i++) { array[i] = ((field4 != null && field4.Length > i) ? field4[i] : null); array2[i] = ((field5 == null || field5.Length <= i) ? 1 : field5[i]); } Image sourceImage = ((field4 != null && field4.Length > 2) ? field4[2] : null); array[3] = MatchingClonedCircleImage(field2[2], field2[3], sourceImage); int num = field3.IndexOf(((Object)field.Abilities[3]).name); if (num <= 0 || field3.sprites == null || num >= field3.sprites.Count) { num = 1; } array2[3] = num; if ((Object)(object)array[3] != (Object)null) { array[3].sprite = field3.GetSprite(num); } SetField(selector, "CircleImages", array); SetField(selector, "XPos", array2); selector.SyncArrowPositionToCurrentYPos(); } } private static Image MatchingClonedCircleImage(RectTransform sourceCircle, RectTransform cloneCircle, Image sourceImage) { if ((Object)(object)sourceCircle == (Object)null || (Object)(object)cloneCircle == (Object)null) { return null; } if (((Transform)cloneCircle).childCount > 0) { Image component = ((Component)((Transform)cloneCircle).GetChild(0)).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { return component; } } Image[] componentsInChildren = ((Component)sourceCircle).GetComponentsInChildren<Image>(true); Image[] componentsInChildren2 = ((Component)cloneCircle).GetComponentsInChildren<Image>(true); if ((Object)(object)sourceImage != (Object)null) { int num = Math.Min(componentsInChildren.Length, componentsInChildren2.Length); for (int i = 0; i < num; i++) { if ((Object)(object)componentsInChildren[i] == (Object)(object)sourceImage) { return componentsInChildren2[i]; } } } Image component2 = ((Component)cloneCircle).GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { return component2; } if (componentsInChildren2.Length != 0) { return componentsInChildren2[0]; } return null; } private static void LiftLossSelectorSlightly(MidGameAbilitySelect selector, AbilitySelectController owner) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)selector == (Object)null) { return; } int instanceID = ((Object)selector).GetInstanceID(); if (!LossSelectorLiftApplied.Add(instanceID)) { return; } RectTransform[] field = GetField<RectTransform[]>(selector, "Circles"); if (field != null) { for (int i = 0; i < field.Length; i++) { if (!((Object)(object)field[i] == (Object)null)) { Vector2 anchoredPosition = field[i].anchoredPosition; anchoredPosition.y += 34f; field[i].anchoredPosition = anchoredPosition; } } } if (!((Object)(object)owner != (Object)null)) { return; } Vector2[] field2 = GetField<Vector2[]>(owner, "abilityListOriginalPositions"); if (field2 != null) { for (int j = 0; j < field2.Length; j++) { ref Vector2 reference = ref field2[j]; reference.y += 34f; } SetField(owner, "abilityListOriginalPositions", field2); } } internal static void LiftOpenLossSelectorArrowOnly(AbilitySelectController controller) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } bool field = GetField<bool>(controller, "isOpen"); RectTransform field2 = GetField<RectTransform>(controller, "arrow"); MidGameAbilitySelect field3 = GetField<MidGameAbilitySelect>(controller, "abilityCirclesParent"); RectTransform[] array = (((Object)(object)field3 == (Object)null) ? null : GetField<RectTransform[]>(field3, "Circles")); LossArrowCounterLiftState lossArrowCounterLiftState = ((Component)controller).GetComponent<LossArrowCounterLiftState>(); if ((Object)(object)lossArrowCounterLiftState == (Object)null) { lossArrowCounterLiftState = ((Component)controller).gameObject.AddComponent<LossArrowCounterLiftState>(); } if ((Object)(object)field2 == (Object)null) { lossArrowCounterLiftState.Applied = false; lossArrowCounterLiftState.ArrowRoot = null; return; } Vector3[] array2 = null; if (array != null) { array2 = (Vector3[])(object)new Vector3[array.Length]; for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null) { ref Vector3 reference = ref array2[i]; reference = ((Transform)array[i]).position; } } } Vector2 anchoredPosition = field2.anchoredPosition; if (!field) { if (lossArrowCounterLiftState.Applied && (Object)(object)lossArrowCounterLiftState.ArrowRoot == (Object)(object)field2) { Vector2 val = anchoredPosition - lossArrowCounterLiftState.ArrowShifted; if (((Vector2)(ref val)).sqrMagnitude < 0.25f) { field2.anchoredPosition = lossArrowCounterLiftState.ArrowBase; } } if (array != null && array2 != null) { for (int j = 0; j < array.Length; j++) { if ((Object)(object)array[j] != (Object)null) { ((Transform)array[j]).position = array2[j]; } } } lossArrowCounterLiftState.Applied = false; lossArrowCounterLiftState.ArrowRoot = field2; return; } Vector2 val2 = anchoredPosition; if (lossArrowCounterLiftState.Applied && (Object)(object)lossArrowCounterLiftState.ArrowRoot == (Object)(object)field2) { Vector2 val3 = anchoredPosition - lossArrowCounterLiftState.ArrowShifted; if (((Vector2)(ref val3)).sqrMagnitude < 0.25f) { val2 = lossArrowCounterLiftState.ArrowBase; } } Vector2 val4 = val2; val4.y += 95f; field2.anchoredPosition = val4; if (array != null && array2 != null) { for (int k = 0; k < array.Length; k++) { if ((Object)(object)array[k] != (Object)null) { ((Transform)array[k]).position = array2[k]; } } } lossArrowCounterLiftState.ArrowRoot = field2; lossArrowCounterLiftState.ArrowBase = val2; lossArrowCounterLiftState.ArrowShifted = val4; lossArrowCounterLiftState.Applied = true; if (!lossArrowCounterLiftState.Logged && Log != null) { lossArrowCounterLiftState.Logged = true; Log.LogInfo((object)"Arrow +95px active; live ability circles are independently lifted +105px after vanilla animation."); } } internal static void LiftOpenLossAbilityCircles(AbilitySelectController controller) { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } bool field = GetField<bool>(controller, "isOpen"); MidGameAbilitySelect field2 = GetField<MidGameAbilitySelect>(controller, "abilityCirclesParent"); RectTransform[] array = (((Object)(object)field2 == (Object)null) ? null : GetField<RectTransform[]>(field2, "Circles")); LossAbilityVisualLiftState lossAbilityVisualLiftState = ((Component)controller).GetComponent<LossAbilityVisualLiftState>(); if ((Object)(object)lossAbilityVisualLiftState == (Object)null) { lossAbilityVisualLiftState = ((Component)controller).gameObject.AddComponent<LossAbilityVisualLiftState>(); } if (array == null || array.Length < 4) { lossAbilityVisualLiftState.Applied = false; lossAbilityVisualLiftState.Circles = array; return; } if (!field) { lossAbilityVisualLiftState.Applied = false; lossAbilityVisualLiftState.Circles = array; return; } if (lossAbilityVisualLiftState.Circles != array || lossAbilityVisualLiftState.BasePositions == null || lossAbilityVisualLiftState.ShiftedPositions == null || lossAbilityVisualLiftState.BasePositions.Length != array.Length || lossAbilityVisualLiftState.ShiftedPositions.Length != array.Length) { lossAbilityVisualLiftState.Circles = array; lossAbilityVisualLiftState.BasePositions = (Vector2[])(object)new Vector2[array.Length]; lossAbilityVisualLiftState.ShiftedPositions = (Vector2[])(object)new Vector2[array.Length]; lossAbilityVisualLiftState.Applied = false; } for (int i = 0; i < array.Length; i++) { RectTransform val = array[i]; if ((Object)(object)val == (Object)null) { continue; } Vector2 anchoredPosition = val.anchoredPosition; if (lossAbilityVisualLiftState.Applied) { Vector2 val2 = anchoredPosition - lossAbilityVisualLiftState.ShiftedPositions[i]; if (!(((Vector2)(ref val2)).sqrMagnitude > 0.25f)) { goto IL_0152; } } lossAbilityVisualLiftState.BasePositions[i] = anchoredPosition; goto IL_0152; IL_0152: Vector2 val3 = lossAbilityVisualLiftState.BasePositions[i]; val3.y += 105f; val.anchoredPosition = val3; lossAbilityVisualLiftState.ShiftedPositions[i] = val3; } lossAbilityVisualLiftState.Applied = true; if (!lossAbilityVisualLiftState.Logged && Log != null) { lossAbilityVisualLiftState.Logged = true; Log.LogInfo((object)"Loss-selector LIVE circles lifted +180px after vanilla animation; all four abilities should fully clear the losing-player portrait."); } } internal static void EnsureAbilitySelectAnimationTargets(AbilitySelectController controller) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_012e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } MidGameAbilitySelect field = GetField<MidGameAbilitySelect>(controller, "abilityCirclesParent"); RectTransform[] array = (((Object)(object)field == (Object)null) ? null : GetField<RectTransform[]>(field, "Circles")); if (array == null || array.Length < 4) { return; } Vector2[] field2 = GetField<Vector2[]>(controller, "abilityListOriginalPositions"); if (field2 != null && field2.Length >= array.Length) { return; } Vector2[] array2 = (Vector2[])(object)new Vector2[array.Length]; int num = ((field2 != null) ? Math.Min(field2.Length, array2.Length) : 0); for (int i = 0; i < num; i++) { ref Vector2 reference = ref array2[i]; reference = field2[i]; } for (int j = num; j < array2.Length; j++) { if (j >= 3 && j - 1 >= 0 && j - 2 >= 0) { Vector2 val = array2[j - 1]; Vector2 val2 = array2[j - 2]; Vector2 val3 = val - val2; if (((Vector2)(ref val3)).sqrMagnitude < 0.0001f && (Object)(object)array[j - 1] != (Object)null && (Object)(object)array[j - 2] != (Object)null) { val3 = array[j - 1].anchoredPosition - array[j - 2].anchoredPosition; } ref Vector2 reference2 = ref array2[j]; reference2 = val + val3; } else { ref Vector2 reference3 = ref array2[j]; reference3 = (((Object)(object)array[j] == (Object)null) ? Vector2.zero : array[j].anchoredPosition); } } SetField(controller, "abilityListOriginalPositions", array2); } internal static void MaintainCharacterFourth(CharacterSelectBox box) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)box == (Object)null || baseSlotsByBox == null || !(baseSlotsByBox.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(((Object)box).GetInstanceID())) { return; } object? obj = dictionary[((Object)box).GetInstanceID()]; SelectAbility val = (SelectAbility)((obj is SelectAbility) ? obj : null); if ((Object)(object)val == (Object)null) { return; } List<SelectableMonoBehaviour> field = GetField<List<SelectableMonoBehaviour>>(box, "selectables"); SelectAbility val2 = (SelectAbility)((field != null && field.Count > 4) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null) { return; } bool activeSelf = ((Component)val2).gameObject.activeSelf; if (((Component)val).gameObject.activeSelf != activeSelf) { ((Component)val).gameObject.SetActive(activeSelf); } if (!activeSelf) { return; } RectTransform component = ((Component)val2).GetComponent<RectTransform>(); RectTransform component2 = ((Component)val).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { float num = component2.anchoredPosition.y - component.anchoredPosition.y; float[] field2 = GetField<float[]>(box, "originalAbilitySelectPos"); if (field2 != null && field2.Length >= 3) { float num2 = (field2[2] - field2[0]) * 0.5f; num = num2 * 0.78f; } Vector2 anchoredPosition = component.anchoredPosition; anchoredPosition.y += num; component2.anchoredPosition = anchoredPosition; } CanvasGroup component3 = ((Component)val2).GetComponent<CanvasGroup>(); CanvasGroup component4 = ((Component)val).GetComponent<CanvasGroup>(); if ((Object)(object)component3 != (Object)null && (Object)(object)component4 != (Object)null) { component4.alpha = component3.alpha; component4.interactable = component3.interactable; component4.blocksRaycasts = component3.blocksRaycasts; } Image field3 = GetField<Image>(val2, "abilityIconRenderer"); Image field4 = GetField<Image>(val, "abilityIconRenderer"); if ((Object)(object)field3 != (Object)null && (Object)(object)field4 != (Object)null) { Sprite sprite = field4.sprite; CopyImageAppearance(field3, field4); field4.sprite = sprite; } Image field5 = GetField<Image>(val2, "BorderRenderer"); Image field6 = GetField<Image>(val, "BorderRenderer"); CopyImageAppearance(field5, field6); Image field7 = GetField<Image>(val2, "circlesRenderer"); Image field8 = GetField<Image>(val, "circlesRenderer"); CopyImageAppearance(field7, field8); } internal static void FixCharacterArrow(CharacterSelectBox box, int selectedIndex) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)box == (Object)null) { return; } List<SelectableMonoBehaviour> field = GetField<List<SelectableMonoBehaviour>>(box, "selectables"); if (field == null || selectedIndex < 0 || selectedIndex >= field.Count) { return; } SelectableMonoBehaviour obj = field[selectedIndex]; SelectAbility val = (SelectAbility)(object)((obj is SelectAbility) ? obj : null); if (!((Object)(object)val == (Object)null) && !(((Object)((Component)val).gameObject).name != "Fourth Ability Slot")) { RectTransform field2 = GetField<RectTransform>(box, "arrows"); RectTransform component = ((Component)val).GetComponent<RectTransform>(); if (!((Object)(object)field2 == (Object)null) && !((Object)(object)component == (Object)null)) { Vector2 anchoredPosition = field2.anchoredPosition; anchoredPosition.y = component.anchoredPosition.y; field2.anchoredPosition = anchoredPosition; } } } internal static Vector3 IndicatorOffset(AbilityReadyIndicator indicator) { //IL_0009: 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_0032: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)indicator == (Object)null) { return Vector3.zero; } FollowTransform component = ((Component)indicator).GetComponent<FollowTransform>(); if ((Object)(object)component != (Object)null && GetField<bool>(component, "initializedPosition")) { return GetField<Vector3>(component, "PositionOffset"); } return ((Component)indicator).transform.localPosition; } private static void SetIndicatorOffset(AbilityReadyIndicator indicator, SlimeController controller, Vector3 offset) { //IL_0019: 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) if (!((Object)(object)indicator == (Object)null) && !((Object)(object)controller == (Object)null)) { ((Component)indicator).transform.localPosition = offset; FollowTransform component = ((Component)indicator).GetComponent<FollowTransform>(); if ((Object)(object)component != (Object)null) { component.Leader = ((Component)controller).transform; SetField(component, "PositionOffset", offset); } } } internal static void AttachGameplayHud(SlimeController controller) { if ((Object)(object)controller == (Object)null) { return; } AbilityReadyIndicator[] field = GetField<AbilityReadyIndicator[]>(controller, "AbilityReadyIndicators"); if (field != null && field.Length >= 4 && !((Object)(object)field[0] == (Object)null) && !((Object)(object)field[1] == (Object)null) && !((Object)(object)field[2] == (Object)null) && !((Object)(object)field[3] == (Object)null)) { GameplayFourthVisualFollower gameplayFourthVisualFollower = ((Component)controller).GetComponent<GameplayFourthVisualFollower>(); if ((Object)(object)gameplayFourthVisualFollower == (Object)null) { gameplayFourthVisualFollower = ((Component)controller).gameObject.AddComponent<GameplayFourthVisualFollower>(); } gameplayFourthVisualFollower.Source = field[2]; gameplayFourthVisualFollower.Target = field[3]; gameplayFourthVisualFollower.SyncNow(); IndicatorLayoutState indicatorLayoutState = ((Component)controller).GetComponent<IndicatorLayoutState>(); if ((Object)(object)indicatorLayoutState == (Object)null) { indicatorLayoutState = ((Component)controller).gameObject.AddComponent<IndicatorLayoutState>(); } Vector3[] value = null; PendingIndicatorOriginals.TryGetValue(((Object)controller).GetInstanceID(), out value); indicatorLayoutState.Initialize(controller, value); PendingIndicatorOriginals.Remove(((Object)controller).GetInstanceID()); } } internal static void AttachGameplayHudForSession(GameSessionHandler handler) { if ((Object)(object)handler == (Object)null) { return; } SlimeController[] field = GetField<SlimeController[]>(handler, "slimeControllers"); if (field != null) { for (int i = 0; i < field.Length; i++) { AttachGameplayHud(field[i]); } } LogLocalInputRoutes(); } private static void LogLocalInputRoutes() { PlayerHandler val = PlayerHandler.Get(); List<Player> list = ((val == null) ? null : val.PlayerList()); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { Player val2 = list[i]; if (val2 != null && val2.IsLocalPlayer && LoggedInputRoutes.Add(val2.Id)) { InputControl control = ControlForPlayer(val2); Log.LogInfo((object)("A4 route for local player " + val2.Id + ": keyboardMouse=" + val2.UsesKeyboardAndMouse + ", inputDevice=" + ((val2.inputDevice == null) ? "null" : ((InputControl)val2.inputDevice).displayName) + ", control=" + DescribeControl(control) + ".")); } } } internal static void ApplyIndicatorLayout(IndicatorLayoutState state) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0076: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_0151: 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) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: 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_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: 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_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)state == (Object)null || !state.Ready || (Object)(object)state.Controller == (Object)null) { return; } AbilityReadyIndicator[] field = GetField<AbilityReadyIndicator[]>(state.Controller, "AbilityReadyIndicators"); if (field != null && field.Length >= 4 && !((Object)(object)field[0] == (Object)null) && !((Object)(object)field[1] == (Object)null) && !((Object)(object)field[2] == (Object)null) && !((Object)(object)field[3] == (Object)null)) { Vector3 val = state.First; Vector3 val2 = state.Second; Vector3 val3 = state.Third; Vector3 val4 = (val + val2) * 0.5f; float num = Mathf.Max(0.9f, Mathf.Abs(val2.x - val.x)); float num2 = Mathf.Max(0.38f, num * 0.25f); float num3 = ((val4.y >= val3.y) ? 1f : (-1f)); float num4 = Mathf.Max(0.7f, Mathf.Abs(val4.y - val3.y) * 0.92f); Vector3 offset; switch (CurrentLayout) { case 1: offset = val3 + Vector3.up * num3 * num4; break; case 2: val3 += Vector3.left * num2; offset = state.Third + Vector3.right * num2; break; case 3: offset = val3 - Vector3.up * num3 * num4; break; case 4: { Vector3 val5 = (val4 + val3) * 0.5f; float num5 = num * 0.4f; val = val5 + Vector3.left * num5 * 1.5f; offset = val5 + Vector3.left * num5 * 0.5f; val3 = val5 + Vector3.right * num5 * 0.5f; val2 = val5 + Vector3.right * num5 * 1.5f; break; } default: val3 += Vector3.right * num2; offset = state.Third + Vector3.left * num2; break; } SetIndicatorOffset(field[0], state.Controller, val); SetIndicatorOffset(field[1], state.Controller, val2); SetIndicatorOffset(field[2], state.Controller, val3); SetIndicatorOffset(field[3], state.Controller, offset); } } internal static void CycleLayout() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) int num = (CurrentLayout + 1) % 5; PlayerPrefs.SetInt("FourthAbilitySlot.LayoutPreset", num); PlayerPrefs.Save(); SlimeController[] array = Resources.FindObjectsOfTypeAll<SlimeController>(); int num2 = 0; foreach (SlimeController val in array) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { AttachGameplayHud(val); IndicatorLayoutState component = ((Component)val).GetComponent<IndicatorLayoutState>(); if ((Object)(object)component != (Object)null && component.Ready) { ApplyIndicatorLayout(component); num2++; } } } Log.LogInfo((object)("F6 detected from active gameplay poller. Fourth ability HUD layout " + (num + 1) + "/5: " + LayoutNames[num] + ". Applied to " + num2 + " live slime HUD(s).")); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(MidGameAbilitySelect), "SetPlayer")] internal static class SafeMidGameSetPlayerPatch { private static void Prefix(MidGameAbilitySelect __instance, ref MidGameState __state) { RepairRuntime.BeforeMidGameSetPlayer(__instance, ref __state); } private static void Postfix(MidGameAbilitySelect __instance, MidGameState __state) { RepairRuntime.RestoreMidGameSetPlayer(__instance, __state); RepairRuntime.SetupSafeMidGameSelector(__instance); } private static Exception Finalizer(MidGameAbilitySelect __instance, Exception __exception, MidGameState __state) { RepairRuntime.RestoreMidGameSetPlayer(__instance, __state); return __exception; } } [HarmonyPatch(typeof(AbilitySelectController), "UpdateAnimation")] [HarmonyPriority(800)] internal static class SafeAbilitySelectAnimationPatch { private static void Prefix(AbilitySelectController __instance) { RepairRuntime.EnsureAbilitySelectAnimationTargets(__instance); } } [HarmonyPriority(0)] [HarmonyPatch(typeof(AbilitySelectController), "UpdateAnimation")] internal static class LossArrowOnlyCounterLiftPatch { private static void Postfix(AbilitySelectController __instance) { RepairRuntime.LiftOpenLossAbilityCircles(__instance); RepairRuntime.LiftOpenLossSelectorArrowOnly(__instance); } } [HarmonyPatch(typeof(CharacterSelectBox), "LateUpdate")] [HarmonyPriority(0)] internal static class CharacterFourthLifecyclePatch { private static void Postfix(CharacterSelectBox __instance) { RepairRuntime.MaintainCharacterFourth(__instance); } } [HarmonyPatch(typeof(CharacterSelectBox), "SetSelected")] internal static class CharacterSelectArrowRepairPatch { private static void Postfix(CharacterSelectBox __instance, int __0) { RepairRuntime.FixCharacterArrow(__instance, __0); } } [HarmonyPriority(0)] [HarmonyPatch(typeof(Host), "CurrentInputAsPacket")] internal static class LayoutHotkeyGameplayTickPatch { private static void Postfix() { RepairRuntime.PollLayoutHotkey(); } } [HarmonyPriority(0)] [HarmonyPatch(typeof(GameSessionHandler), "SpawnPlayers")] internal static class GameplayHudRepairPatch { private static void Postfix(GameSessionHandler __instance) { RepairRuntime.AttachGameplayHudForSession(__instance); } } [HarmonyPriority(0)] [HarmonyPatch(typeof(SlimeController), "Init")] internal static class SlimeHudRepairPatch { private static void Postfix(SlimeController __instance) { RepairRuntime.AttachGameplayHud(__instance); } }