From 03a37339662c3243363301708096f8e612bf85c3 Mon Sep 17 00:00:00 2001 From: xChipseq Date: Tue, 9 Sep 2025 22:57:19 +0200 Subject: [PATCH 1/6] fix body prefab --- MiraAPI/Networking/CustomMurderRpc.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MiraAPI/Networking/CustomMurderRpc.cs b/MiraAPI/Networking/CustomMurderRpc.cs index 209afcd..e3005c9 100644 --- a/MiraAPI/Networking/CustomMurderRpc.cs +++ b/MiraAPI/Networking/CustomMurderRpc.cs @@ -222,7 +222,7 @@ public static class CustomMurderRpc if (createDeadBody) { - deadBody = Object.Instantiate(GameManager.Instance.DeadBodyPrefab); + deadBody = Object.Instantiate(GameManager.Instance.deadBodyPrefab[0]); deadBody.enabled = false; deadBody.ParentId = target.PlayerId; deadBody.bodyRenderers.ToList().ForEach(target.SetPlayerMaterialColors); From 70f63f8b16aa08d60152f95126933b6db8b4947b Mon Sep 17 00:00:00 2001 From: xChipseq Date: Tue, 9 Sep 2025 22:58:02 +0200 Subject: [PATCH 2/6] custom role fixes --- MiraAPI/Patches/Roles/RoleManagerPatches.cs | 2 +- MiraAPI/Roles/CustomRoleManager.cs | 10 +++++++++- MiraAPI/Roles/CustomRoleUtils.cs | 3 +-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/MiraAPI/Patches/Roles/RoleManagerPatches.cs b/MiraAPI/Patches/Roles/RoleManagerPatches.cs index fa0cb5a..93daa82 100644 --- a/MiraAPI/Patches/Roles/RoleManagerPatches.cs +++ b/MiraAPI/Patches/Roles/RoleManagerPatches.cs @@ -33,7 +33,7 @@ public static class RoleManagerPatches data.Role.Deinitialize(targetPlayer); Object.Destroy(data.Role.gameObject); } - var roleBehaviour = Object.Instantiate(__instance.AllRoles.First(r => r.Role == roleType), data.gameObject.transform); + var roleBehaviour = Object.Instantiate(__instance.AllRoles.ToArray().First(r => r.Role == roleType), data.gameObject.transform); roleBehaviour.Initialize(targetPlayer); targetPlayer.Data.Role = roleBehaviour; targetPlayer.Data.RoleType = roleType; diff --git a/MiraAPI/Roles/CustomRoleManager.cs b/MiraAPI/Roles/CustomRoleManager.cs index 5e1c3ae..d16153b 100644 --- a/MiraAPI/Roles/CustomRoleManager.cs +++ b/MiraAPI/Roles/CustomRoleManager.cs @@ -35,6 +35,11 @@ public static class CustomRoleManager public static readonly LoadableAsset ImpostorIntroSound = CustomRoleUtils.GetIntroSound(RoleTypes.Impostor)!; + /// + /// Gets the list of all roles from vanilla RoleManager. + /// + public static RoleBehaviour[] AllRoles => RoleManager.Instance.AllRoles.ToArray(); + /// /// Gets the list of custom roles as RoleBehaviour objects. /// @@ -57,7 +62,10 @@ public static class CustomRoleManager internal static void RegisterInRoleManager() { - RoleManager.Instance.AllRoles = RoleManager.Instance.AllRoles.Concat(CustomRoles.Values).ToArray(); + foreach (var role in CustomRoles.Values) + { + RoleManager.Instance.AllRoles.Add(role); + } foreach (var role in CustomRoles.Values.Where(x => x.IsDead)) { diff --git a/MiraAPI/Roles/CustomRoleUtils.cs b/MiraAPI/Roles/CustomRoleUtils.cs index 01b402d..cb4dbfb 100644 --- a/MiraAPI/Roles/CustomRoleUtils.cs +++ b/MiraAPI/Roles/CustomRoleUtils.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text; using AmongUs.GameOptions; using MiraAPI.Utilities.Assets; -using Reactor.Utilities; using UnityEngine; namespace MiraAPI.Roles; @@ -56,7 +55,7 @@ public static class CustomRoleUtils /// The intro sound. public static LoadableAsset? GetIntroSound(RoleTypes roleType) { - var role = RoleManager.Instance.AllRoles.FirstOrDefault(role => role.Role == roleType); + var role = CustomRoleManager.AllRoles.FirstOrDefault(role => role.Role == roleType); if (role is ICustomRole customRole) { return customRole.Configuration.IntroSound; From 2c0042e6a84e9fdd121c4880efb26abfddaeb23e Mon Sep 17 00:00:00 2001 From: xChipseq Date: Tue, 9 Sep 2025 22:58:18 +0200 Subject: [PATCH 3/6] bump to 2025.9.9 --- AmongUs.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AmongUs.props b/AmongUs.props index e0d7f3c..6f6e0f9 100644 --- a/AmongUs.props +++ b/AmongUs.props @@ -2,12 +2,12 @@ - + - + From dfa8b2971087baa3ee31c864c910ba4f8194684b Mon Sep 17 00:00:00 2001 From: xChipseq Date: Wed, 10 Sep 2025 22:07:47 +0200 Subject: [PATCH 4/6] update task adder (and improvements) --- MiraAPI/MiraApiSettings.cs | 6 + MiraAPI/Patches/Freeplay/TaskAdderPatches.cs | 480 ++++++++----------- MiraAPI/Resources/ModifierFile.png | Bin 0 -> 4664 bytes MiraAPI/Resources/RoleFile.png | Bin 0 -> 6070 bytes MiraAPI/Resources/TimedModifierFile.png | Bin 5246 -> 5220 bytes MiraAPI/Roles/CustomRoleConfiguration.cs | 11 + MiraAPI/Utilities/Assets/MiraAssets.cs | 10 + 7 files changed, 230 insertions(+), 277 deletions(-) create mode 100644 MiraAPI/Resources/ModifierFile.png create mode 100644 MiraAPI/Resources/RoleFile.png diff --git a/MiraAPI/MiraApiSettings.cs b/MiraAPI/MiraApiSettings.cs index aa4b29c..574212c 100644 --- a/MiraAPI/MiraApiSettings.cs +++ b/MiraAPI/MiraApiSettings.cs @@ -30,4 +30,10 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config) /// Gets whether to show keybinds in the control mapper. /// public ConfigEntry ShowKeybinds { get; private set; } = config.Bind("Keybinds", "Show Keybinds in Control Mapper", true); + + /// + /// Gets whether to apply cosmetic changes to the TaskAdder. + /// + [LocalToggleSetting] + public ConfigEntry PrettyTaskAdder { get; private set; } = config.Bind("Freeplay", "Pretty Task Laptop", true); } diff --git a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs index 7f6a8b5..c96c609 100644 --- a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs +++ b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs @@ -1,15 +1,15 @@ -using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; -using AmongUs.GameOptions; +using System.Text; using HarmonyLib; +using MiraAPI.LocalSettings; using MiraAPI.Modifiers; using MiraAPI.Modifiers.Types; using MiraAPI.PluginLoading; using MiraAPI.Roles; -using MiraAPI.Utilities; using MiraAPI.Utilities.Assets; -using TMPro; +using Reactor.Utilities.Extensions; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; @@ -21,6 +21,8 @@ namespace MiraAPI.Patches.Freeplay; internal static class TaskAdderPatches { private static Scroller _scroller = null!; + private static Dictionary folders = new(); + [HarmonyPostfix] [HarmonyPatch(nameof(TaskAdderGame.Begin))] public static void AddRolesFolder(TaskAdderGame __instance) @@ -60,46 +62,80 @@ internal static class TaskAdderPatches __instance.RoleButton.GetComponent().ClickMask = collider; __instance.RootFolderPrefab.GetComponent().ClickMask = collider; __instance.RootFolderPrefab.gameObject.SetActive(false); - __instance.TaskParent = inner.transform; - var rolesFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner); - rolesFolder.gameObject.SetActive(false); - rolesFolder.FolderName = "Roles"; - rolesFolder.name = "RolesFolder"; + var crewmateFolder = __instance.Root.SubFolders.ToArray().FirstOrDefault(x => x.FolderName == "Crewmate")!; + var impostorFolder = __instance.Root.SubFolders.ToArray().FirstOrDefault(x => x.FolderName == "Impostor")!; + var neutralFolder = __instance.CreateFolder("Neutral", __instance.Root, 2, Color.gray); + var modifiersFolder = __instance.CreateFolder("Modifiers", __instance.Root, 0, Color.blue); - var modifiersFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner); - modifiersFolder.gameObject.SetActive(false); - modifiersFolder.FolderName = "Modifiers"; - modifiersFolder.name = "ModifiersFolder"; + folders.Clear(); + folders.Add("Crewmate", crewmateFolder); + folders.Add("Impostor", impostorFolder); + folders.Add("Neutral", neutralFolder); + folders.Add("Modifiers", modifiersFolder); + int folderIdx = 3; foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins) { - if (plugin.InternalRoles.Any(x => x.Value is ICustomRole { Configuration.ShowInFreeplay: true })) + var pluginFolders = new Dictionary(); + + foreach (var role in plugin.InternalRoles + .Where(x => x.Value is ICustomRole { Configuration.ShowInFreeplay: true }) + .Select(x => x.Value)) { - var newFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner); - newFolder.name = plugin.PluginId+":Roles"; - newFolder.FolderName = plugin.PluginInfo.Metadata.Name; - newFolder.gameObject.SetActive(false); - rolesFolder.SubFolders.Add(newFolder); + var customRole = role as ICustomRole; + var folderName = customRole!.Configuration.FreeplayFolder; + if (!folders.TryGetValue(folderName, out var teamFolder)) + { + teamFolder = __instance.CreateFolder(folderName, __instance.Root, folderIdx++, customRole.RoleColor); + folders.Add(folderName, teamFolder); + } + + if (!pluginFolders.TryGetValue(folderName, out var pluginFolder)) + { + pluginFolder = __instance.CreateFolder(plugin.PluginInfo.Metadata.Name, teamFolder); + pluginFolders.Add(folderName, teamFolder); + } + + pluginFolder.RoleChildren.Add(role); } if (plugin.InternalModifiers.Exists(x => x.ShowInFreeplay)) { - var newFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner); - newFolder.name = plugin.PluginId+":Modifiers"; - newFolder.FolderName = plugin.PluginInfo.Metadata.Name; - newFolder.gameObject.SetActive(false); - modifiersFolder.SubFolders.Add(newFolder); + __instance.CreateFolder(plugin.PluginInfo.Metadata.Name, modifiersFolder) + .gameObject.name = plugin.PluginId; } } - __instance.Root.SubFolders.Add(rolesFolder); - __instance.Root.SubFolders.Add(modifiersFolder); + // Modifier folder at the end + __instance.Root.SubFolders.Insert(folderIdx, modifiersFolder); __instance.GoToRoot(); } + private static TaskFolder CreateFolder(this TaskAdderGame instance, string name, TaskFolder parent, int idx = -1, Color? color = null) + { + var folder = Object.Instantiate(instance.RootFolderPrefab, instance.transform); + folder.gameObject.SetActive(false); + folder.FolderName = name; + folder.SetCustomColor(color ?? new Color(0.937f, 0.811f, 0.592f)); + folder.name = name + "Folder"; + if (idx == -1) + parent.SubFolders.Add(folder); + else if (idx > 0) + parent.SubFolders.Insert(idx, folder); + return folder; + } + + private static void SetCustomColor(this TaskFolder folder, Color color) + { + folder.currentFolderColor = color; + folder.folderSpriteRenderer.color = color; + folder.buttonRolloverHandler.OutColor = color; + folder.buttonRolloverHandler.UnselectedColor = color; + } + private static void AddFileAsChildCustom( this TaskAdderGame instance, TaskAddButton item, @@ -122,40 +158,46 @@ internal static class TaskAdderPatches instance.ActiveItems.Add(item.transform); } + private static bool IsChildOf(this TaskFolder child, TaskFolder parent) => parent.SubFolders + .ToArray() + .Any(x => x.FolderName == child.FolderName); + // yes it might be crazy patching the entire method, but i tried so many other methods and only this works :cry: + // true -chip [HarmonyPrefix] [HarmonyPatch(nameof(TaskAdderGame.ShowFolder))] public static bool ShowPatch(TaskAdderGame __instance, TaskFolder taskFolder) { - var stringBuilder = new Il2CppSystem.Text.StringBuilder(64); + StringBuilder stringBuilder = new StringBuilder(64); __instance.Hierarchy.Add(taskFolder); - for (var i = 0; i < __instance.Hierarchy.Count; i++) + foreach (var t in __instance.Hierarchy) { - stringBuilder.Append(__instance.Hierarchy.ToArray()[i].FolderName); - stringBuilder.Append("\\"); + stringBuilder.Append(t.FolderName); + stringBuilder.Append('\\'); } - __instance.PathText.text = stringBuilder.ToString(); - for (var j = 0; j < __instance.ActiveItems.Count; j++) + var prettyEnabled = LocalSettingsTabSingleton.Instance.PrettyTaskAdder.Value; + if (prettyEnabled) { - Object.Destroy(__instance.ActiveItems.ToArray()[j].gameObject); + __instance.PathText.fontSizeMin = 3; + __instance.PathText.fontSizeMax = 3; + __instance.transform.FindChild("TitleText_TMP").gameObject.SetActive(false); } + __instance.ActiveItems.ToArray().Do(x => x.gameObject.Destroy()); __instance.ActiveItems.Clear(); - var num = 0f; - var num2 = 0f; - var num3 = 0f; - for (var k = 0; k < taskFolder.SubFolders.Count; k++) - { - var taskFolder2 = Object.Instantiate(taskFolder.SubFolders.ToArray()[k], __instance.TaskParent); - var folderTransform = taskFolder2.transform; + float num = 0f; + float num2 = 0f; + float num3 = 0f; + foreach (var t in taskFolder.SubFolders) + { + TaskFolder taskFolder2 = Object.Instantiate(t, __instance.TaskParent); taskFolder2.gameObject.SetActive(true); taskFolder2.Parent = __instance; - - folderTransform.localPosition = new Vector3(num, num2, 0f); - folderTransform.localScale = Vector3.one; - num3 = Mathf.Max(num3, taskFolder2.Text.bounds.size.y + 1.3f); + taskFolder2.transform.localPosition = new Vector3(num, num2, 0f); + taskFolder2.transform.localScale = Vector3.one; + num3 = Mathf.Max(num3, taskFolder2.Text.bounds.size.y + 1.1f); num += __instance.folderWidth; if (num > __instance.lineWidth) { @@ -164,241 +206,67 @@ internal static class TaskAdderPatches num3 = 0f; } - __instance.ActiveItems.Add(folderTransform); - if (!taskFolder2 || !taskFolder2.Button) + __instance.ActiveItems.Add(taskFolder2.transform); + if (taskFolder2 != null && taskFolder2.Button != null) { - continue; - } - - ControllerManager.Instance.AddSelectableUiElement(taskFolder2.Button); - if (!string.IsNullOrEmpty(__instance.restorePreviousSelectionByFolderName) && - taskFolder2.FolderName.Equals(__instance.restorePreviousSelectionByFolderName, StringComparison.Ordinal)) - { - __instance.restorePreviousSelectionFound = taskFolder2.Button; + ControllerManager.Instance.AddSelectableUiElement(taskFolder2.Button); } } - var flag = false; - var list = taskFolder.Children.ToArray().OrderBy(t => t.TaskType).ToList(); - - for (var l = 0; l < list.Count; l++) + var list = taskFolder.TaskChildren + .ToArray() + .OrderBy(x => x.TaskType) + .ToArray(); + foreach (var task in list) { - var taskAddButton = Object.Instantiate(__instance.TaskPrefab); - taskAddButton.MyTask = list.ToArray()[l]; - switch (taskAddButton.MyTask.TaskType) + TaskAddButton taskAddButton = Object.Instantiate(__instance.TaskPrefab); + taskAddButton.MyTask = task; + switch (task.TaskType) { case TaskTypes.DivertPower: - { - var targetSystem = taskAddButton.MyTask.Cast().TargetSystem; - taskAddButton.Text.text = TranslationController.Instance.GetString( - StringNames.DivertPowerTo, - TranslationController.Instance.GetString(targetSystem)); - break; - } + { + var targetSystem = task.Cast().TargetSystem; + taskAddButton.Text.text = TranslationController.Instance.GetString( + StringNames.DivertPowerTo, + TranslationController.Instance.GetString(targetSystem)); + break; + } case TaskTypes.FixWeatherNode: - { - var nodeId = taskAddButton.MyTask.Cast().NodeId; - taskAddButton.Text.text = - TranslationController.Instance.GetString( - StringNames.FixWeatherNode) + " " + - TranslationController.Instance.GetString( - WeatherSwitchGame.ControlNames[nodeId]); - break; - } + { + var nodeId = task.Cast().NodeId; + taskAddButton.Text.text = + TranslationController.Instance.GetString( + StringNames.FixWeatherNode) + " " + + TranslationController.Instance.GetString( + WeatherSwitchGame.ControlNames[nodeId]); + break; + } default: taskAddButton.Text.text = - TranslationController.Instance.GetString(taskAddButton.MyTask.TaskType); + TranslationController.Instance.GetString(task.TaskType); break; } __instance.AddFileAsChildCustom(taskAddButton, ref num, ref num2, ref num3); - if (taskAddButton.Button == null) + if (taskAddButton != null && taskAddButton.Button != null) { - continue; - } - - ControllerManager.Instance.AddSelectableUiElement(taskAddButton.Button); - if (__instance.Hierarchy.Count == 1 || flag) - { - continue; - } - - var component = - ControllerManager.Instance.CurrentUiState.CurrentSelection.GetComponent(); - if (component != null) - { - __instance.restorePreviousSelectionByFolderName = component.FolderName; - } - - ControllerManager.Instance.SetDefaultSelection(taskAddButton.Button); - flag = true; - } - - if (taskFolder.FolderName == "Roles") - { - for (var m = 0; m < RoleManager.Instance.AllRoles.Length; m++) - { - var roleBehaviour = RoleManager.Instance.AllRoles[m]; - if (roleBehaviour.Role == RoleTypes.ImpostorGhost || roleBehaviour.Role == RoleTypes.CrewmateGhost || - CustomRoleManager.CustomRoles.ContainsKey((ushort)roleBehaviour.Role)) - { - continue; - } - - var taskAddButton2 = Object.Instantiate(__instance.RoleButton); - taskAddButton2.SafePositionWorld = __instance.SafePositionWorld; - taskAddButton2.Text.text = "Be_" + roleBehaviour.NiceName + ".exe"; - __instance.AddFileAsChildCustom(taskAddButton2, ref num, ref num2, ref num3); - taskAddButton2.Role = roleBehaviour; - - if (taskAddButton2.Button == null) - { - continue; - } - - ControllerManager.Instance.AddSelectableUiElement(taskAddButton2.Button); - switch (m) - { - case 0 when __instance.restorePreviousSelectionFound != null: - ControllerManager.Instance.SetDefaultSelection(__instance.restorePreviousSelectionFound); - __instance.restorePreviousSelectionByFolderName = string.Empty; - __instance.restorePreviousSelectionFound = null; - break; - case 0: - ControllerManager.Instance.SetDefaultSelection(taskAddButton2.Button); - break; - } + ControllerManager.Instance.AddSelectableUiElement(taskAddButton.Button, false); } } - if (taskFolder) + var roleChildren = taskFolder.RoleChildren + .ToArray() + .Where(x => !(taskFolder.IsChildOf(__instance.Root) && x is ICustomRole)) + .ToArray(); + foreach (var role in roleChildren) { - var split = taskFolder.name.Split(':'); - if (split.Length == 2) - { - var pluginId = split[0]; - var folderName = split[1]; - - if (MiraPluginManager.GetPluginByGuid(pluginId) is { } plugin) - { - if (folderName == "Roles(Clone)") - { - PluginRoles(__instance, plugin, ref num, ref num2, ref num3); - } - else if (folderName == "Modifiers(Clone)") - { - PluginModifiers(__instance, plugin, ref num, ref num2, ref num3); - } - } - } - } - - foreach (var chip in __instance.ActiveItems) - { - chip.GetComponentInChildren().EnableStencilMasking(); - chip.GetComponent().maskInteraction = SpriteMaskInteraction.VisibleInsideMask; - } - - if (_scroller) - { - _scroller.CalculateAndSetYBounds(__instance.ActiveItems.Count, 6, 4.5f, 1.65f); - _scroller.SetYBoundsMin(0.0f); - _scroller.ScrollToTop(); - } - - if (__instance.Hierarchy.Count == 1) - { - ControllerManager.Instance.SetBackButton(__instance.BackButton); - return false; - } - - ControllerManager.Instance.SetBackButton(__instance.FolderBackButton); - return false; - } - - private static void PluginModifiers( - TaskAdderGame instance, - MiraPluginInfo plugin, - ref float num, - ref float num2, - ref float num3) - { - for (var m = 0; m < plugin.InternalModifiers.Count; m++) - { - var modifier = plugin.InternalModifiers[m]; - if (!modifier.ShowInFreeplay) - { - continue; - } - - var taskAddButton = Object.Instantiate(instance.RoleButton); - taskAddButton.name = modifier.TypeId.ToString(NumberFormatInfo.InvariantInfo); - taskAddButton.role = null; - taskAddButton.MyTask = null; - taskAddButton.SafePositionWorld = instance.SafePositionWorld; - taskAddButton.Text.text = modifier.ModifierName; - taskAddButton.Text.fontSizeMin = 1; - taskAddButton.Text.EnableMasking(); - taskAddButton.FileImage.color = modifier.FreeplayFileColor; - taskAddButton.RolloverHandler.OutColor = modifier.FreeplayFileColor; - taskAddButton.Button.OnClick = new Button.ButtonClickedEvent(); - taskAddButton.Button.OnClick.AddListener((UnityEngine.Events.UnityAction)(() => - { - var id = modifier.TypeId; - if (PlayerControl.LocalPlayer.HasModifier(id)) - { - PlayerControl.LocalPlayer.RemoveModifier(id); - taskAddButton.Overlay.enabled = false; - } - else - { - PlayerControl.LocalPlayer.AddModifier(id); - taskAddButton.Overlay.enabled = true; - } - })); - - if (modifier is TimedModifier timed) - { - taskAddButton.FileImage.sprite = MiraAssets.TimedModifierFile.LoadAsset(); - taskAddButton.Text.text += $"({timed.Duration}s)"; - } - - instance.AddFileAsChildCustom(taskAddButton, ref num, ref num2, ref num3); - - ControllerManager.Instance.AddSelectableUiElement(taskAddButton.Button); - switch (m) - { - case 0 when instance.restorePreviousSelectionFound != null: - ControllerManager.Instance.SetDefaultSelection(instance.restorePreviousSelectionFound); - instance.restorePreviousSelectionByFolderName = string.Empty; - instance.restorePreviousSelectionFound = null; - break; - case 0: - ControllerManager.Instance.SetDefaultSelection(taskAddButton.Button); - break; - } - } - } - - private static void PluginRoles(TaskAdderGame instance, MiraPluginInfo plugin, ref float num, ref float num2, ref float num3) - { - for (var m = 0; m < plugin.InternalRoles.Count; m++) - { - var roleBehaviour = plugin.InternalRoles.ElementAt(m).Value; - if (roleBehaviour.Role == RoleTypes.ImpostorGhost || roleBehaviour.Role == RoleTypes.CrewmateGhost || - roleBehaviour is ICustomRole { Configuration.ShowInFreeplay: false }) - { - continue; - } - - var taskAddButton2 = Object.Instantiate(instance.RoleButton); - taskAddButton2.SafePositionWorld = instance.SafePositionWorld; - taskAddButton2.Text.text = "Be_" + roleBehaviour.NiceName + ".exe"; - taskAddButton2.Text.EnableMasking(); - - instance.AddFileAsChildCustom(taskAddButton2, ref num, ref num2, ref num3); - taskAddButton2.Role = roleBehaviour; - if (roleBehaviour is ICustomRole custom) + TaskAddButton roleAddButton = Object.Instantiate(__instance.RoleButton); + roleAddButton.SafePositionWorld = __instance.SafePositionWorld; + roleAddButton.Text.text = prettyEnabled ? role.NiceName : "Be_" + role.NiceName + ".exe"; + roleAddButton.Text.fontSizeMin = 1; + roleAddButton.Role = role; + if (prettyEnabled) roleAddButton.FileImage.sprite = MiraAssets.RoleFile.LoadAsset(); + if (role is ICustomRole custom) { var customColor = custom.IntroConfiguration?.IntroTeamColor ?? Color.gray; if (custom.Team is ModdedRoleTeams.Crewmate) @@ -409,26 +277,84 @@ internal static class TaskAdderPatches { customColor = Palette.ImpostorRed; } - taskAddButton2.FileImage.color = customColor; - taskAddButton2.RolloverHandler.OutColor = customColor; + roleAddButton.FileImage.color = customColor; + roleAddButton.RolloverHandler.OutColor = customColor; } - if (taskAddButton2.Button == null) + __instance.AddFileAsChildCustom(roleAddButton, ref num, ref num2, ref num3); + if (roleAddButton != null && roleAddButton.Button != null) { - continue; - } - - ControllerManager.Instance.AddSelectableUiElement(taskAddButton2.Button); - switch (m) - { - case 0 when instance.restorePreviousSelectionFound != null: - ControllerManager.Instance.SetDefaultSelection(instance.restorePreviousSelectionFound); - instance.restorePreviousSelectionByFolderName = string.Empty; - instance.restorePreviousSelectionFound = null; - break; - case 0: - ControllerManager.Instance.SetDefaultSelection(taskAddButton2.Button); - break; + ControllerManager.Instance.AddSelectableUiElement(roleAddButton.Button); } } + + if (folders.TryGetValue("Modifiers", out var modifiersFolder) && taskFolder.IsChildOf(modifiersFolder)) + { + var plugin = MiraPluginManager.GetPluginByGuid(taskFolder.gameObject.name.Replace("(Clone)", string.Empty)); + if (plugin != null) + { + foreach (var modifier in plugin.InternalModifiers) + { + if (!modifier.ShowInFreeplay) + { + continue; + } + + var taskAddButton = Object.Instantiate(__instance.RoleButton); + taskAddButton.name = modifier.TypeId.ToString(NumberFormatInfo.InvariantInfo); + taskAddButton.role = null; + taskAddButton.MyTask = null; + taskAddButton.SafePositionWorld = __instance.SafePositionWorld; + taskAddButton.Text.text = modifier.ModifierName; + taskAddButton.Text.fontSizeMin = 1; + taskAddButton.Text.EnableMasking(); + taskAddButton.FileImage.color = modifier.FreeplayFileColor; + taskAddButton.RolloverHandler.OutColor = modifier.FreeplayFileColor; + if (modifier is TimedModifier timed) + { + taskAddButton.FileImage.sprite = MiraAssets.TimedModifierFile.LoadAsset(); + taskAddButton.Text.text += $" ({timed.Duration}s)"; + } + else + { + taskAddButton.FileImage.sprite = MiraAssets.ModifierFile.LoadAsset(); + } + + taskAddButton.Button.OnClick = new Button.ButtonClickedEvent(); + var m = modifier; + taskAddButton.Button.OnClick.AddListener((UnityAction)(() => + { + var id = m.TypeId; + if (PlayerControl.LocalPlayer.HasModifier(id)) + { + PlayerControl.LocalPlayer.RemoveModifier(id); + taskAddButton.Overlay.enabled = false; + } + else + { + PlayerControl.LocalPlayer.AddModifier(id); + taskAddButton.Overlay.enabled = true; + } + })); + + __instance.AddFileAsChildCustom(taskAddButton, ref num, ref num2, ref num3); + + ControllerManager.Instance.AddSelectableUiElement(taskAddButton.Button); + } + } + } + + if (_scroller) + { + _scroller.CalculateAndSetYBounds(__instance.ActiveItems.Count, 6, 4.5f, 1.65f); + _scroller.SetYBoundsMin(0.0f); + _scroller.ScrollToTop(); + } + + ControllerManager.Instance.SetBackButton(__instance.Hierarchy.Count == 1 + ? __instance.BackButton + : __instance.FolderBackButton); + + __instance.SetPreviousControllerSelection(taskFolder.FolderName); + return false; } } diff --git a/MiraAPI/Resources/ModifierFile.png b/MiraAPI/Resources/ModifierFile.png new file mode 100644 index 0000000000000000000000000000000000000000..8d5b78d47a57e55be95822216f9bf6c9226f4b75 GIT binary patch literal 4664 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 O`$J1jPqkJV9`!%7oVh~) literal 0 HcmV?d00001 diff --git a/MiraAPI/Resources/RoleFile.png b/MiraAPI/Resources/RoleFile.png new file mode 100644 index 0000000000000000000000000000000000000000..534d6b7a91437ae3eec9307eafdac42a23fc8d46 GIT binary patch literal 6070 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 delta 4614 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 diff --git a/MiraAPI/Roles/CustomRoleConfiguration.cs b/MiraAPI/Roles/CustomRoleConfiguration.cs index 5b0158d..3974665 100644 --- a/MiraAPI/Roles/CustomRoleConfiguration.cs +++ b/MiraAPI/Roles/CustomRoleConfiguration.cs @@ -32,6 +32,12 @@ public record struct CustomRoleConfiguration TasksCountForProgress = role.Team is ModdedRoleTeams.Crewmate; HideSettings = roleBehaviour?.IsDead == true; ShowInFreeplay = roleBehaviour?.IsDead == false; + FreeplayFolder = role.Team switch + { + ModdedRoleTeams.Crewmate => "Crewmate", + ModdedRoleTeams.Impostor => "Impostor", + _ => "Neutral", + }; IntroSound = role.Team is ModdedRoleTeams.Crewmate ? CustomRoleManager.CrewmateIntroSound : CustomRoleManager.ImpostorIntroSound; @@ -112,6 +118,11 @@ public record struct CustomRoleConfiguration /// public bool ShowInFreeplay { get; set; } + /// + /// Gets or sets a freeplay folder this role belongs to. Defaults to team folder. + /// + public string FreeplayFolder { get; set; } + /// /// Gets or sets the outline color for the KillButton if is true. /// diff --git a/MiraAPI/Utilities/Assets/MiraAssets.cs b/MiraAPI/Utilities/Assets/MiraAssets.cs index 1e39c28..19c633b 100644 --- a/MiraAPI/Utilities/Assets/MiraAssets.cs +++ b/MiraAPI/Utilities/Assets/MiraAssets.cs @@ -105,6 +105,16 @@ public static class MiraAssets /// public static LoadableResourceAsset KeybindButton { get; } = new("MiraAPI.Resources.KeybindButton.png"); + /// + /// Gets the sprite used for role file in TaskAdderGame. + /// + public static LoadableResourceAsset RoleFile { get; } = new("MiraAPI.Resources.RoleFile.png"); + + /// + /// Gets the sprite used for modifier file in TaskAdderGame. + /// + public static LoadableResourceAsset ModifierFile { get; } = new("MiraAPI.Resources.ModifierFile.png"); + /// /// Gets the sprite used for timed modifier file in TaskAdderGame. /// From 790b37e8d35d2a61e39b0b2174a943f9c767bac5 Mon Sep 17 00:00:00 2001 From: xChipseq Date: Wed, 10 Sep 2025 22:40:09 +0200 Subject: [PATCH 5/6] cool role file icons --- MiraAPI/Patches/Freeplay/TaskAdderPatches.cs | 12 +++++++++--- MiraAPI/Resources/CrewmateFile.png | Bin 0 -> 5123 bytes MiraAPI/Resources/CustomFile.png | Bin 0 -> 5274 bytes MiraAPI/Resources/ImpostorFile.png | Bin 0 -> 6323 bytes MiraAPI/Resources/RoleFile.png | Bin 6070 -> 0 bytes MiraAPI/Utilities/Assets/MiraAssets.cs | 14 ++++++++++++-- 6 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 MiraAPI/Resources/CrewmateFile.png create mode 100644 MiraAPI/Resources/CustomFile.png create mode 100644 MiraAPI/Resources/ImpostorFile.png delete mode 100644 MiraAPI/Resources/RoleFile.png diff --git a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs index c96c609..77dc106 100644 --- a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs +++ b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs @@ -88,7 +88,7 @@ internal static class TaskAdderPatches var folderName = customRole!.Configuration.FreeplayFolder; if (!folders.TryGetValue(folderName, out var teamFolder)) { - teamFolder = __instance.CreateFolder(folderName, __instance.Root, folderIdx++, customRole.RoleColor); + teamFolder = __instance.CreateFolder(folderName, __instance.Root, folderIdx++, customRole.IntroConfiguration?.IntroTeamColor ?? Color.gray); folders.Add(folderName, teamFolder); } @@ -263,11 +263,17 @@ internal static class TaskAdderPatches TaskAddButton roleAddButton = Object.Instantiate(__instance.RoleButton); roleAddButton.SafePositionWorld = __instance.SafePositionWorld; roleAddButton.Text.text = prettyEnabled ? role.NiceName : "Be_" + role.NiceName + ".exe"; - roleAddButton.Text.fontSizeMin = 1; roleAddButton.Role = role; - if (prettyEnabled) roleAddButton.FileImage.sprite = MiraAssets.RoleFile.LoadAsset(); + if (prettyEnabled) + { + roleAddButton.Text.fontSizeMin = 1; + roleAddButton.FileImage.sprite = role.IsImpostor + ? MiraAssets.ImpostorFile.LoadAsset() + : MiraAssets.CrewmateFile.LoadAsset(); + } if (role is ICustomRole custom) { + if (prettyEnabled && custom.Team == ModdedRoleTeams.Custom) roleAddButton.FileImage.sprite = MiraAssets.CustomTeamFile.LoadAsset(); var customColor = custom.IntroConfiguration?.IntroTeamColor ?? Color.gray; if (custom.Team is ModdedRoleTeams.Crewmate) { diff --git a/MiraAPI/Resources/CrewmateFile.png b/MiraAPI/Resources/CrewmateFile.png new file mode 100644 index 0000000000000000000000000000000000000000..7cf1e743989ec861d38c58dee91c820b6191981e GIT binary patch literal 5123 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 - /// Gets the sprite used for role file in TaskAdderGame. + /// Gets the sprite used for crewmate role files in TaskAdderGame. /// - public static LoadableResourceAsset RoleFile { get; } = new("MiraAPI.Resources.RoleFile.png"); + public static LoadableResourceAsset CrewmateFile { get; } = new("MiraAPI.Resources.CrewmateFile.png"); + + /// + /// Gets the sprite used for impostor role files in TaskAdderGame. + /// + public static LoadableResourceAsset ImpostorFile { get; } = new("MiraAPI.Resources.ImpostorFile.png"); + + /// + /// Gets the sprite used for custom team role files in TaskAdderGame. + /// + public static LoadableResourceAsset CustomTeamFile { get; } = new("MiraAPI.Resources.CustomFile.png"); /// /// Gets the sprite used for modifier file in TaskAdderGame. From 834d1d878e4f20219cccc21dbfc29d6c415d6017 Mon Sep 17 00:00:00 2001 From: xChipseq Date: Wed, 10 Sep 2025 22:45:48 +0200 Subject: [PATCH 6/6] fix --- MiraAPI/Patches/Freeplay/TaskAdderPatches.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs index 77dc106..59d87dd 100644 --- a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs +++ b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs @@ -181,7 +181,7 @@ internal static class TaskAdderPatches { __instance.PathText.fontSizeMin = 3; __instance.PathText.fontSizeMax = 3; - __instance.transform.FindChild("TitleText_TMP").gameObject.SetActive(false); + __instance.transform.FindChild("TitleText_TMP")?.gameObject.DestroyImmediate(); } __instance.ActiveItems.ToArray().Do(x => x.gameObject.Destroy());