Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Skeleton Selector v1.2.1
BepInEx/plugins/SkeletonSelector/SkeletonSelector.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SkeletonSelector")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.1.0")] [assembly: AssemblyInformationalVersion("1.2.1")] [assembly: AssemblyProduct("SkeletonSelector")] [assembly: AssemblyTitle("SkeletonSelector")] [assembly: AssemblyVersion("1.2.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SkeletonSelector { public enum SkeletonKind { Random, Warrior, Archer, ShieldWarrior } [BepInPlugin("local.valheim.skeletonselector", "Skeleton Selector", "1.2.1")] [DefaultExecutionOrder(-1000)] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "TakeInput")] private static class InputPatch { private static void Postfix(Player __instance, ref bool __result) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && BlocksInput) { __result = false; } } } [HarmonyPatch(typeof(Player), "SetMouseLook")] private static class LookPatch { private static bool Prefix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { return !BlocksInput; } return true; } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] private static class CursorPatch { private static bool Prefix() { if (!MenuOpen) { return true; } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); return false; } } public const string Id = "local.valheim.skeletonselector"; internal static Plugin Instance; internal ConfigEntry<SkeletonKind> Choice; private ConfigEntry<KeyCode> menuKey; private ConfigEntry<bool> showHint; private ConfigEntry<UiLanguage> language; private Harmony harmony; private RadialMenu menu; private bool open; private bool capturingKey; private bool waitForMouseRelease; private int blockUntilFrame = -1; private int captureAfterFrame; private static readonly KeyCode[] Keys = (KeyCode[])Enum.GetValues(typeof(KeyCode)); internal static bool BlocksInput { get { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Instance) && ((Behaviour)Instance).enabled) { if (!Instance.open && Time.frameCount > Instance.blockUntilFrame && !Instance.waitForMouseRelease) { if (HasSkullEquipped() && !OtherUI()) { return Input.GetKeyDown(Instance.menuKey.Value); } return false; } return true; } return false; } } internal static bool MenuOpen { get { if (Object.op_Implicit((Object)(object)Instance)) { return Instance.open; } return false; } } internal bool CapturingKey => capturingKey; internal string KeyLabel => KeyName(menuKey.Value); internal string LanguageLabel { get { if (language.Value != UiLanguage.Auto) { if (language.Value != UiLanguage.Russian) { return "English"; } return "Русский"; } return UiText.Get(TextId.Auto); } } internal int Selected => Mathf.Clamp((int)Choice.Value, 0, 3); private void Awake() { //IL_00ea: 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_00ca: Invalid comparison between Unknown and I4 //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown //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) Instance = this; Choice = ((BaseUnityPlugin)this).Config.Bind<SkeletonKind>("Summoning", "SelectedType", SkeletonKind.Random, "Random, Warrior, Archer, ShieldWarrior. Applies to future Dead Raiser summons."); menuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Interface", "MenuKey", (KeyCode)327, "Hold to open; release over a sector to select. Mouse4 = front side button, Mouse3 = rear side, Mouse2 = middle. Requires equipped Dead Raiser."); showHint = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowStaffHint", true, "Show the selected type and menu key while holding the Dead Raiser."); language = ((BaseUnityPlugin)this).Config.Bind<UiLanguage>("Interface", "Language", UiLanguage.Auto, "Auto follows Valheim: Russian for Russian, English for other languages. Or force English / Russian."); UpdateLanguage(); ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("Interface", "SettingsVersion", 0, "Internal settings migration version."); if (val.Value < 110) { if ((int)menuKey.Value == 289) { menuKey.Value = (KeyCode)327; } val.Value = 110; } if (!CanBind(menuKey.Value)) { menuKey.Value = (KeyCode)327; } ((BaseUnityPlugin)this).Config.Save(); harmony = new Harmony("local.valheim.skeletonselector"); try { harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Skeleton Selector 1.2.1 loaded. Hold/release radial menu: " + ((object)menuKey.Value/*cast due to .constrained prefix*/).ToString() + ". Requires equipped StaffSkeleton.")); } catch (Exception ex) { harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)("Patches could not be installed; selector disabled: " + ex)); ((Behaviour)this).enabled = false; } } internal static bool HasSkullEquipped() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead()) { return false; } ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon(); if (currentWeapon != null && Object.op_Implicit((Object)(object)currentWeapon.m_dropPrefab)) { return ((Object)currentWeapon.m_dropPrefab).name == "StaffSkeleton"; } return false; } private static bool OtherUI() { if (!Console.IsVisible() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.IsChatDialogWindowVisible()) && !InventoryGui.IsVisible() && !Menu.IsVisible() && !TextInput.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible()) { return Hud.InRadial(); } return true; } private void Update() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: 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_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_0141: 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) UpdateLanguage(); if (waitForMouseRelease && !Input.GetMouseButton(0) && !Input.GetMouseButton(1) && !Input.GetMouseButton(2) && !Input.GetKey(menuKey.Value)) { waitForMouseRelease = false; } if (!HasSkullEquipped() || !Application.isFocused || OtherUI()) { Close(); menu?.SetHint(visible: false, ""); return; } if (menu == null) { if (!Object.op_Implicit((Object)(object)EventSystem.current)) { return; } try { menu = new RadialMenu(this); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Radial UI initialization failed: " + ex)); ((Behaviour)this).enabled = false; return; } } menu.SetHint(showHint.Value && !open, string.Format(UiText.Get(TextId.SummonHint), UiText.Label(Selected), KeyLabel)); if (capturingKey) { if (Time.frameCount <= captureAfterFrame) { return; } if (Input.GetKeyDown((KeyCode)27)) { Close(); return; } KeyCode[] keys = Keys; foreach (KeyCode val in keys) { if (CanBind(val) && Input.GetKeyDown(val)) { menuKey.Value = val; ((BaseUnityPlugin)this).Config.Save(); Close(); break; } } } else if (open) { if (Input.GetKeyDown((KeyCode)27) || Input.GetMouseButtonDown(1)) { Close(); } else if (!Input.GetKey(menuKey.Value)) { int hoveredIndex = menu.GetHoveredIndex(); if (hoveredIndex >= 0) { Choose(hoveredIndex); } else { Close(); } } else { menu.Refresh(); } } else if (Input.GetKeyDown(menuKey.Value)) { open = true; menu.SetOpen(value: true); menu.SetHint(visible: false, ""); ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } } private void UpdateLanguage() { UiLanguage value = language.Value; Localization instance = Localization.instance; UiText.UseRussian = UiText.ResolveRussian(value, (instance != null) ? instance.GetSelectedLanguage() : null); } internal void CycleLanguage() { if (open && !capturingKey) { language.Value = (UiLanguage)((int)(language.Value + 1) % 3); ((BaseUnityPlugin)this).Config.Save(); UpdateLanguage(); menu.Refresh(); } } internal void Choose(int index) { if (open && !capturingKey && HasSkullEquipped() && !OtherUI() && index >= 0 && index <= 3) { Choice.Value = (SkeletonKind)index; ((BaseUnityPlugin)this).Config.Save(); Close(); } } internal void BeginRebind() { if (open && !capturingKey) { capturingKey = true; captureAfterFrame = Time.frameCount + 1; menu.Refresh(); } } internal void Close() { if (open) { open = false; capturingKey = false; blockUntilFrame = Time.frameCount + 2; waitForMouseRelease = true; menu?.SetOpen(value: false); } } private static bool CanBind(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if ((int)key != 0 && (int)key != 27 && (int)key != 323 && (int)key != 324) { if ((int)key >= 330) { return (int)key >= 670; } return true; } return false; } private unsafe static string KeyName(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected I4, but got Unknown return (key - 325) switch { 2 => UiText.Get(TextId.MouseForward), 1 => UiText.Get(TextId.MouseBack), 0 => UiText.Get(TextId.MouseMiddle), _ => ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(), }; } private void OnApplicationFocus(bool focused) { if (!focused) { Close(); } } private void OnDisable() { Close(); menu?.SetHint(visible: false, ""); } private void OnDestroy() { Close(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } menu?.Dispose(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } internal void Warn(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false); } } } internal static class SummonSelection { private sealed class Selection { internal SkeletonKind Kind; } [HarmonyPatch(typeof(SpawnAbility), "Setup")] private static class CaptureSelection { private static void Prefix(SpawnAbility __instance, Character __0) { Choices.Remove(__instance); if (Object.op_Implicit((Object)(object)Plugin.Instance) && Object.op_Implicit((Object)(object)__0) && (Object)(object)__0 == (Object)(object)Player.m_localPlayer) { Choices.Add(__instance, new Selection { Kind = Plugin.Instance.Choice.Value }); } } } [HarmonyPatch(typeof(SpawnAbility), "Spawn")] private static class SpawnScope { private static void Postfix(SpawnAbility __instance, ref IEnumerator __result) { if (Choices.TryGetValue(__instance, out var value) && value.Kind != SkeletonKind.Random) { __result = Scoped(__result, value.Kind); } } } [HarmonyPatch(typeof(Humanoid), "Awake")] private static class SkeletonSeed { private static void Postfix(Humanoid __instance) { if (activeKind == SkeletonKind.Random || !Object.op_Implicit((Object)(object)__instance) || ((Object)((Component)__instance).gameObject).name != "Skeleton_Friendly(Clone)") { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner()) { return; } try { SelectSeed(__instance, component, activeKind); } catch (Exception ex) { Plugin.Instance.Warn(UiText.Get(TextId.SelectionFailed) + ex.Message); } } } private static readonly ConditionalWeakTable<SpawnAbility, Selection> Choices = new ConditionalWeakTable<SpawnAbility, Selection>(); [ThreadStatic] private static SkeletonKind activeKind; private static readonly FieldInfo SeedField = AccessTools.Field(typeof(Humanoid), "m_seed"); private static readonly FieldInfo WeaponsField = AccessTools.Field(typeof(Humanoid), "m_randomWeapon"); private static readonly FieldInfo ShieldsField = AccessTools.Field(typeof(Humanoid), "m_randomShield"); private static readonly FieldInfo SetsField = AccessTools.Field(typeof(Humanoid), "m_randomSets"); private static readonly FieldInfo ItemsField = AccessTools.Field(typeof(Humanoid), "m_randomItems"); private static IEnumerator Scoped(IEnumerator original, SkeletonKind kind) { try { while (true) { SkeletonKind skeletonKind = activeKind; bool flag; try { activeKind = kind; flag = original.MoveNext(); } finally { activeKind = skeletonKind; } if (flag) { yield return original.Current; continue; } break; } } finally { (original as IDisposable)?.Dispose(); } } private static void SelectSeed(Humanoid skeleton, ZNetView view, SkeletonKind kind) { //IL_017b: 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_006b: Unknown result type (might be due to invalid IL or missing references) GameObject[] array = (GameObject[])WeaponsField.GetValue(skeleton); GameObject[] array2 = (GameObject[])ShieldsField.GetValue(skeleton); if (((Array)SetsField.GetValue(skeleton)).Length != 0 || ((Array)ItemsField.GetValue(skeleton)).Length != 0 || array.Length == 0) { Plugin.Instance.Warn(UiText.Get(TextId.EquipmentModified)); return; } State state = Random.state; int num = (int)SeedField.GetValue(skeleton); int num2 = 0; bool flag = false; try { for (int i = 0; i < 8192; i++) { int num3 = num + i; if (num3 == 0) { continue; } Random.InitState(num3); GameObject val = ((array2.Length == 0) ? null : array2[Random.Range(0, array2.Length)]); GameObject val2 = array[Random.Range(0, array.Length)]; bool flag2 = Object.op_Implicit((Object)(object)val2) && (((Object)val2).name == "skeleton_bow2" || ((Object)val2).name == "skeleton_bow"); bool flag3 = Object.op_Implicit((Object)(object)val2) && (((Object)val2).name == "skeleton_sword2" || ((Object)val2).name == "skeleton_sword"); bool num4; switch (kind) { default: if (!(kind == SkeletonKind.Warrior && flag3)) { continue; } num4 = !Object.op_Implicit((Object)(object)val); break; case SkeletonKind.ShieldWarrior: if (!flag3) { continue; } num4 = Object.op_Implicit((Object)(object)val); break; case SkeletonKind.Archer: num4 = flag2; break; } if (num4) { num2 = num3; flag = true; break; } } } finally { Random.state = state; } if (!flag) { Plugin.Instance.Warn(UiText.Get(TextId.EquipmentUnavailable)); return; } view.GetZDO().Set("seed", num2); SeedField.SetValue(skeleton, num2); } } public enum UiLanguage { Auto, English, Russian } internal enum TextId { Random, Warrior, Archer, ShieldWarrior, RandomDescription, WarriorDescription, ArcherDescription, ShieldDescription, Title, Subtitle, Selected, Release, NewKey, PressKey, Cancel, Instructions, EquipmentHint, KeyCapture, KeyChange, SummonHint, MouseForward, MouseBack, MouseMiddle, Language, Auto, SelectionFailed, EquipmentModified, EquipmentUnavailable } internal static class UiText { internal static bool UseRussian; private static readonly Dictionary<TextId, string[]> Strings = new Dictionary<TextId, string[]> { { TextId.Random, new string[2] { "Random", "Случайный" } }, { TextId.Warrior, new string[2] { "Warrior", "Воин" } }, { TextId.Archer, new string[2] { "Archer", "Лучник" } }, { TextId.ShieldWarrior, new string[2] { "Shield Warrior", "Воин со щитом" } }, { TextId.RandomDescription, new string[2] { "Vanilla random choice", "Обычный выбор игры" } }, { TextId.WarriorDescription, new string[2] { "Sword, no shield", "Меч, без щита" } }, { TextId.ArcherDescription, new string[2] { "Bow and arrows", "Лук и стрелы" } }, { TextId.ShieldDescription, new string[2] { "Sword and shield", "Меч и щит" } }, { TextId.Title, new string[2] { "SUMMON SKELETONS", "ПРИЗЫВ СКЕЛЕТОВ" } }, { TextId.Subtitle, new string[2] { "Choose your next summoned companion", "Выберите спутника для следующего призыва" } }, { TextId.Selected, new string[2] { "SELECTED", "ВЫБРАН" } }, { TextId.Release, new string[2] { "RELEASE TO SELECT", "ОТПУСТИТЕ КНОПКУ" } }, { TextId.NewKey, new string[2] { "NEW BINDING", "НОВАЯ КНОПКА" } }, { TextId.PressKey, new string[2] { "Press a\nkey", "Нажмите\nкнопку" } }, { TextId.Cancel, new string[2] { "Esc to cancel", "Esc — отмена" } }, { TextId.Instructions, new string[2] { "Release the menu key to select · RMB / Esc to cancel", "Отпустите кнопку круга — выбрать · ПКМ / Esc — отменить" } }, { TextId.EquipmentHint, new string[2] { "Available only while the Dead Raiser is equipped", "Меню доступно только с черепом в руках" } }, { TextId.KeyCapture, new string[2] { "Press a key or mouse button (except LMB / RMB)", "Клавиша или кнопка мыши (кроме ЛКМ / ПКМ)" } }, { TextId.KeyChange, new string[2] { "Key: {0} · Change", "Кнопка: {0} · Изменить" } }, { TextId.SummonHint, new string[2] { "Summon: {0} · Hold {1}", "Призыв: {0} · Удерживайте {1}" } }, { TextId.MouseForward, new string[2] { "Forward side button (Mouse4)", "Боковая вперёд (Mouse4)" } }, { TextId.MouseBack, new string[2] { "Back side button (Mouse3)", "Боковая назад (Mouse3)" } }, { TextId.MouseMiddle, new string[2] { "Middle mouse button", "Средняя кнопка мыши" } }, { TextId.Language, new string[2] { "Language: {0} · Change", "Язык: {0} · Изменить" } }, { TextId.Auto, new string[2] { "Auto", "Авто" } }, { TextId.SelectionFailed, new string[2] { "Could not select skeleton type: ", "Не удалось выбрать тип скелета: " } }, { TextId.EquipmentModified, new string[2] { "Another mod changed skeleton equipment; using vanilla selection.", "Снаряжение скелета изменено другим модом; оставлен штатный выбор." } }, { TextId.EquipmentUnavailable, new string[2] { "Selected equipment is unavailable; using vanilla selection.", "Выбранное снаряжение недоступно; оставлен штатный выбор." } } }; internal static string Get(TextId id) { return Strings[id][UseRussian ? 1u : 0u]; } internal static string Label(int index) { return Get((TextId)Math.Max(0, Math.Min(3, index))); } internal static string Description(int index) { return Get((TextId)(4 + Math.Max(0, Math.Min(3, index)))); } internal static bool ResolveRussian(UiLanguage setting, string gameLanguage) { return setting switch { UiLanguage.Auto => string.Equals(gameLanguage, "Russian", StringComparison.OrdinalIgnoreCase), UiLanguage.Russian => true, _ => false, }; } } public sealed class RingSlice : MaskableGraphic { internal int Index = -1; internal float Inner = 104f; internal float Outer = 278f; internal Color Rim = new Color(0.51f, 0.43f, 0.27f, 1f); protected override void OnPopulateMesh(VertexHelper vh) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) vh.Clear(); float start = ((Index < 0) ? 0f : ((float)(Index * 90) - 43f)); float end = ((Index < 0) ? 360f : ((float)(Index * 90) + 43f)); int steps = ((Index < 0) ? 96 : 32); AddBand(vh, Inner, Outer, start, end, steps, ((Graphic)this).color); AddBand(vh, Outer - 1.5f, Outer, start, end, steps, Rim); if (Inner > 0f) { AddBand(vh, Inner, Inner + 1f, start, end, steps, Rim); } } private static void AddBand(VertexHelper vh, float inner, float outer, float start, float end, int steps, Color color) { //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) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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) for (int i = 0; i < steps; i++) { float num = Mathf.Lerp(start, end, (float)i / (float)steps) * ((float)Math.PI / 180f); float num2 = Mathf.Lerp(start, end, (float)(i + 1) / (float)steps) * ((float)Math.PI / 180f); int currentVertCount = vh.currentVertCount; vh.AddVert(new Vector3(Mathf.Sin(num) * inner, Mathf.Cos(num) * inner), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero)); vh.AddVert(new Vector3(Mathf.Sin(num) * outer, Mathf.Cos(num) * outer), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero)); vh.AddVert(new Vector3(Mathf.Sin(num2) * outer, Mathf.Cos(num2) * outer), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero)); vh.AddVert(new Vector3(Mathf.Sin(num2) * inner, Mathf.Cos(num2) * inner), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero)); vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2); vh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3); } } public override bool Raycast(Vector2 screenPoint, Camera eventCamera) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!((MaskableGraphic)this).Raycast(screenPoint, eventCamera)) { return false; } Vector2 val = default(Vector2); if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(((Graphic)this).rectTransform, screenPoint, eventCamera, ref val)) { return false; } if (Index >= 0) { return RadialGeometry.HitIndex(val.x, val.y) == Index; } return ((Vector2)(ref val)).sqrMagnitude <= Outer * Outer; } } internal sealed class RadialMenu : IDisposable { private readonly Plugin plugin; private readonly GameObject root; private readonly GameObject overlay; private readonly RectTransform wheel; private readonly TMP_FontAsset font; private readonly bool ownsFont; private readonly List<Texture2D> textures = new List<Texture2D>(); private readonly RingSlice[] slices = new RingSlice[4]; private readonly Button[] choices = (Button[])(object)new Button[4]; private readonly TextMeshProUGUI[] labels = (TextMeshProUGUI[])(object)new TextMeshProUGUI[4]; private readonly TextMeshProUGUI centerTitle; private readonly TextMeshProUGUI centerName; private readonly TextMeshProUGUI centerDescription; private readonly TextMeshProUGUI keyText; private readonly TextMeshProUGUI hintText; private readonly Button rebind; private readonly Button languageButton; private readonly TextMeshProUGUI languageText; private readonly Dictionary<TextMeshProUGUI, TextId> localized = new Dictionary<TextMeshProUGUI, TextId>(); private static readonly Color Gold = new Color(0.94f, 0.79f, 0.47f); private static readonly Color Normal = new Color(0.055f, 0.085f, 0.09f, 0.98f); private static readonly Color Selected = new Color(0.085f, 0.23f, 0.2f, 0.99f); private static readonly Color Hovered = new Color(0.28f, 0.22f, 0.12f, 0.99f); internal RadialMenu(Plugin plugin) { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0202: 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_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_051f: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) //IL_0529: Unknown result type (might be due to invalid IL or missing references) //IL_0557: Unknown result type (might be due to invalid IL or missing references) //IL_055c: Unknown result type (might be due to invalid IL or missing references) //IL_059f: Unknown result type (might be due to invalid IL or missing references) //IL_05c6: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Unknown result type (might be due to invalid IL or missing references) //IL_05da: Unknown result type (might be due to invalid IL or missing references) //IL_0603: Unknown result type (might be due to invalid IL or missing references) //IL_0612: Unknown result type (might be due to invalid IL or missing references) //IL_0617: Unknown result type (might be due to invalid IL or missing references) //IL_0640: Unknown result type (might be due to invalid IL or missing references) //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_0663: Unknown result type (might be due to invalid IL or missing references) //IL_068c: Unknown result type (might be due to invalid IL or missing references) //IL_069b: Unknown result type (might be due to invalid IL or missing references) //IL_06a0: Unknown result type (might be due to invalid IL or missing references) //IL_06c0: Unknown result type (might be due to invalid IL or missing references) //IL_06cf: Unknown result type (might be due to invalid IL or missing references) //IL_06ff: Unknown result type (might be due to invalid IL or missing references) //IL_0730: Unknown result type (might be due to invalid IL or missing references) //IL_073e: Unknown result type (might be due to invalid IL or missing references) //IL_0757: Unknown result type (might be due to invalid IL or missing references) //IL_0761: Expected O, but got Unknown //IL_077b: Unknown result type (might be due to invalid IL or missing references) //IL_0780: Unknown result type (might be due to invalid IL or missing references) //IL_0785: Unknown result type (might be due to invalid IL or missing references) //IL_07ae: Unknown result type (might be due to invalid IL or missing references) //IL_07bd: Unknown result type (might be due to invalid IL or missing references) //IL_07d1: Unknown result type (might be due to invalid IL or missing references) //IL_07f1: Unknown result type (might be due to invalid IL or missing references) //IL_0800: Unknown result type (might be due to invalid IL or missing references) //IL_0830: Unknown result type (might be due to invalid IL or missing references) //IL_0861: Unknown result type (might be due to invalid IL or missing references) //IL_086f: Unknown result type (might be due to invalid IL or missing references) //IL_0888: Unknown result type (might be due to invalid IL or missing references) //IL_0892: Expected O, but got Unknown //IL_08ac: Unknown result type (might be due to invalid IL or missing references) //IL_08b1: Unknown result type (might be due to invalid IL or missing references) //IL_08b6: Unknown result type (might be due to invalid IL or missing references) this.plugin = plugin; TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (Object.op_Implicit((Object)(object)val) && val.HasCharacter('П', false, false) && val.HasCharacter('р', false, false) && val.HasCharacter('ы', false, false) && val.HasCharacter('A', false, false) && val.HasCharacter('a', false, false)) { font = val; break; } } if (!Object.op_Implicit((Object)(object)font)) { font = TMP_FontAsset.CreateFontAsset(Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf")); ownsFont = true; } if (!Object.op_Implicit((Object)(object)font)) { throw new InvalidOperationException("No font available for radial menu."); } root = new GameObject("SkeletonSelectorCanvas", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); root.transform.SetParent(((Component)plugin).transform, false); try { Canvas component = root.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 31000; CanvasScaler component2 = root.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1280f, 900f); component2.screenMatchMode = (ScreenMatchMode)1; hintText = Text(root.transform, "StaffHint", "", 17, new Vector2(700f, 36f), Vector2.zero, Gold); RectTransform rectTransform = ((TMP_Text)hintText).rectTransform; Vector2 anchorMin = (((TMP_Text)hintText).rectTransform.anchorMax = new Vector2(0.5f, 0f)); rectTransform.anchorMin = anchorMin; ((TMP_Text)hintText).rectTransform.anchoredPosition = new Vector2(0f, 100f); ((Component)hintText).gameObject.SetActive(false); overlay = ((Component)Rect(root.transform, "RadialOverlay", Vector2.zero, Vector2.zero)).gameObject; RectTransform val3 = (RectTransform)overlay.transform; val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.sizeDelta = Vector2.zero; Image obj = overlay.AddComponent<Image>(); ((Graphic)obj).color = new Color(0.015f, 0.025f, 0.035f, 0.72f); ((Graphic)obj).raycastTarget = true; wheel = Rect(overlay.transform, "Wheel", new Vector2(880f, 850f), Vector2.zero); LocalizedText((Transform)(object)wheel, "Title", TextId.Title, 30, new Vector2(650f, 46f), new Vector2(0f, 352f), Gold); LocalizedText((Transform)(object)wheel, "Subtitle", TextId.Subtitle, 17, new Vector2(700f, 34f), new Vector2(0f, 315f), Color.white); string[] array2 = new string[4] { "random", "warrior", "archer", "shield" }; Navigation navigation; for (int j = 0; j < 4; j++) { RectTransform val4 = Rect((Transform)(object)wheel, "Sector" + j, new Vector2(560f, 560f), Vector2.zero); slices[j] = ((Component)val4).gameObject.AddComponent<RingSlice>(); slices[j].Index = j; ((Graphic)slices[j]).color = Normal; ((Graphic)slices[j]).raycastTarget = true; choices[j] = ((Component)val4).gameObject.AddComponent<Button>(); ((Selectable)choices[j]).targetGraphic = (Graphic)(object)slices[j]; ((Selectable)choices[j]).transition = (Transition)0; Button obj2 = choices[j]; navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)obj2).navigation = navigation; float num = (float)(j * 90) * ((float)Math.PI / 180f); Vector2 val5 = new Vector2(Mathf.Sin(num), Mathf.Cos(num)) * 190f; RawImage obj3 = ((Component)Rect((Transform)(object)val4, "Portrait", new Vector2(108f, 108f), val5 + new Vector2(0f, 9f))).gameObject.AddComponent<RawImage>(); obj3.texture = (Texture)(object)LoadIcon(array2[j]); ((Graphic)obj3).raycastTarget = false; labels[j] = Text((Transform)(object)val4, "Label", UiText.Label(j), 18, new Vector2(174f, 34f), val5 + new Vector2(0f, -61f), Color.white); } RectTransform val6 = Rect((Transform)(object)wheel, "Center", new Vector2(208f, 208f), Vector2.zero); RingSlice ringSlice = ((Component)val6).gameObject.AddComponent<RingSlice>(); ringSlice.Inner = 0f; ringSlice.Outer = 100f; ((Graphic)ringSlice).color = new Color(0.035f, 0.055f, 0.06f, 1f); ((Graphic)ringSlice).raycastTarget = false; centerTitle = LocalizedText((Transform)(object)val6, "State", TextId.Selected, 12, new Vector2(170f, 24f), new Vector2(0f, 50f), Gold); centerName = Text((Transform)(object)val6, "Name", "", 22, new Vector2(176f, 62f), new Vector2(0f, 10f), Color.white); centerDescription = Text((Transform)(object)val6, "Description", "", 13, new Vector2(164f, 42f), new Vector2(0f, -42f), new Color(0.71f, 0.77f, 0.76f)); LocalizedText((Transform)(object)wheel, "Instructions", TextId.Instructions, 16, new Vector2(800f, 28f), new Vector2(0f, -308f), Color.white); RectTransform val7 = Rect((Transform)(object)wheel, "ChangeKey", new Vector2(540f, 48f), new Vector2(0f, -352f)); Image val8 = ((Component)val7).gameObject.AddComponent<Image>(); ((Graphic)val8).color = new Color(0.11f, 0.15f, 0.16f, 1f); rebind = ((Component)val7).gameObject.AddComponent<Button>(); ((Selectable)rebind).targetGraphic = (Graphic)(object)val8; Button obj4 = rebind; navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)obj4).navigation = navigation; ((UnityEvent)rebind.onClick).AddListener(new UnityAction(plugin.BeginRebind)); keyText = Text((Transform)(object)val7, "KeyLabel", "", 16, new Vector2(518f, 44f), Vector2.zero, Gold); LocalizedText((Transform)(object)wheel, "EquipmentHint", TextId.EquipmentHint, 14, new Vector2(700f, 26f), new Vector2(0f, -431f), new Color(0.67f, 0.74f, 0.73f)); RectTransform val9 = Rect((Transform)(object)wheel, "Language", new Vector2(420f, 36f), new Vector2(0f, -397f)); Image val10 = ((Component)val9).gameObject.AddComponent<Image>(); ((Graphic)val10).color = new Color(0.08f, 0.12f, 0.13f, 1f); languageButton = ((Component)val9).gameObject.AddComponent<Button>(); ((Selectable)languageButton).targetGraphic = (Graphic)(object)val10; Button obj5 = languageButton; navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)obj5).navigation = navigation; ((UnityEvent)languageButton.onClick).AddListener(new UnityAction(plugin.CycleLanguage)); languageText = Text((Transform)(object)val9, "Label", "", 15, new Vector2(406f, 34f), Vector2.zero, Gold); overlay.SetActive(false); Refresh(); } catch { Dispose(); throw; } } internal void SetHint(bool visible, string text) { ((Component)hintText).gameObject.SetActive(visible); if (visible && ((TMP_Text)hintText).text != text) { ((TMP_Text)hintText).text = text; } } internal void SetOpen(bool value) { overlay.SetActive(value); if (value) { Refresh(); } } internal int GetHoveredIndex() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); if (overlay.activeSelf && !plugin.CapturingKey && RectTransformUtility.ScreenPointToLocalPointInRectangle(wheel, Vector2.op_Implicit(Input.mousePosition), (Camera)null, ref val)) { return RadialGeometry.HitIndex(val.x, val.y); } return -1; } internal void Refresh() { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<TextMeshProUGUI, TextId> item in localized) { ((TMP_Text)item.Key).text = UiText.Get(item.Value); } ((Selectable)languageButton).interactable = !plugin.CapturingKey; ((TMP_Text)languageText).text = string.Format(UiText.Get(TextId.Language), plugin.LanguageLabel); int hoveredIndex = GetHoveredIndex(); for (int i = 0; i < 4; i++) { ((Selectable)choices[i]).interactable = !plugin.CapturingKey; ((Graphic)slices[i]).color = ((hoveredIndex == i) ? Hovered : ((plugin.Selected == i) ? Selected : Normal)); ((TMP_Text)labels[i]).text = UiText.Label(i); ((Graphic)labels[i]).color = ((plugin.Selected == i) ? Gold : Color.white); } int index = ((hoveredIndex >= 0) ? hoveredIndex : plugin.Selected); ((TMP_Text)centerTitle).text = (plugin.CapturingKey ? UiText.Get(TextId.NewKey) : ((hoveredIndex >= 0) ? UiText.Get(TextId.Release) : UiText.Get(TextId.Selected))); ((TMP_Text)centerName).text = (plugin.CapturingKey ? UiText.Get(TextId.PressKey) : UiText.Label(index)); ((TMP_Text)centerDescription).text = (plugin.CapturingKey ? UiText.Get(TextId.Cancel) : UiText.Description(index)); ((Selectable)rebind).interactable = !plugin.CapturingKey; ((TMP_Text)keyText).text = (plugin.CapturingKey ? UiText.Get(TextId.KeyCapture) : string.Format(UiText.Get(TextId.KeyChange), plugin.KeyLabel)); } private Texture2D LoadIcon(string name) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SkeletonSelector.Icons." + name + ".png"); if (stream == null) { throw new InvalidOperationException("Missing embedded icon: " + name); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true); textures.Add(val); if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), false)) { throw new InvalidOperationException("Invalid icon: " + name); } val.Apply(true, true); ((Texture)val).filterMode = (FilterMode)2; ((Texture)val).wrapMode = (TextureWrapMode)1; return val; } private TextMeshProUGUI LocalizedText(Transform parent, string name, TextId id, int size, Vector2 dimensions, Vector2 position, Color color) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = Text(parent, name, UiText.Get(id), size, dimensions, position, color); localized.Add(val, id); return val; } private TextMeshProUGUI Text(Transform parent, string name, string value, int size, Vector2 dimensions, Vector2 position, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI obj = ((Component)Rect(parent, name, dimensions, position)).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)obj).font = font; ((TMP_Text)obj).fontSize = size; ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((Graphic)obj).color = color; ((TMP_Text)obj).text = value; ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).overflowMode = (TextOverflowModes)0; return obj; } private static RectTransform Rect(Transform parent, string name, Vector2 size, Vector2 position) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(parent, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); val.pivot = val2; Vector2 anchorMin = (val.anchorMax = val2); val.anchorMin = anchorMin; val.sizeDelta = size; val.anchoredPosition = position; return val; } public void Dispose() { if (Object.op_Implicit((Object)(object)root)) { Object.Destroy((Object)(object)root); } foreach (Texture2D texture in textures) { if (Object.op_Implicit((Object)(object)texture)) { Object.Destroy((Object)(object)texture); } } if (!ownsFont || !Object.op_Implicit((Object)(object)font)) { return; } Texture2D[] atlasTextures = font.atlasTextures; foreach (Texture2D val in atlasTextures) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } } if (Object.op_Implicit((Object)(object)((TMP_Asset)font).material)) { Object.Destroy((Object)(object)((TMP_Asset)font).material); } Object.Destroy((Object)(object)font); } } public static class RadialGeometry { public const float Inner = 104f; public const float Outer = 278f; public const float HalfAngle = 43f; public static int HitIndex(float x, float y) { double num = (double)x * (double)x + (double)y * (double)y; if (num < 10816.0 || num > 77284.0) { return -1; } double num2 = (Math.Atan2(x, y) * 180.0 / Math.PI + 360.0) % 360.0; int num3 = (int)((num2 + 45.0) / 90.0) % 4; if (!(Math.Abs((num2 - (double)(num3 * 90) + 540.0) % 360.0 - 180.0) <= 43.0)) { return -1; } return num3; } } }