mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
14 files changed
+257
-281
No files matched your search
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Reactor" Version="2.3.1" />
|
<PackageReference Include="Reactor" Version="2.3.1" />
|
||||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native" />
|
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native" />
|
||||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.4.15" PrivateAssets="all" />
|
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.9.9" PrivateAssets="all" />
|
||||||
|
|
||||||
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
|
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />
|
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />
|
||||||
|
|||||||
@@ -30,4 +30,10 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
|
|||||||
/// Gets whether to show keybinds in the control mapper.
|
/// Gets whether to show keybinds in the control mapper.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConfigEntry<bool> ShowKeybinds { get; private set; } = config.Bind("Keybinds", "Show Keybinds in Control Mapper", true);
|
public ConfigEntry<bool> ShowKeybinds { get; private set; } = config.Bind("Keybinds", "Show Keybinds in Control Mapper", true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether to apply cosmetic changes to the TaskAdder.
|
||||||
|
/// </summary>
|
||||||
|
[LocalToggleSetting]
|
||||||
|
public ConfigEntry<bool> PrettyTaskAdder { get; private set; } = config.Bind("Freeplay", "Pretty Task Laptop", true);
|
||||||
}
|
}
|
||||||
@@ -222,7 +222,7 @@ public static class CustomMurderRpc
|
|||||||
|
|
||||||
if (createDeadBody)
|
if (createDeadBody)
|
||||||
{
|
{
|
||||||
deadBody = Object.Instantiate(GameManager.Instance.DeadBodyPrefab);
|
deadBody = Object.Instantiate(GameManager.Instance.deadBodyPrefab[0]);
|
||||||
deadBody.enabled = false;
|
deadBody.enabled = false;
|
||||||
deadBody.ParentId = target.PlayerId;
|
deadBody.ParentId = target.PlayerId;
|
||||||
deadBody.bodyRenderers.ToList().ForEach(target.SetPlayerMaterialColors);
|
deadBody.bodyRenderers.ToList().ForEach(target.SetPlayerMaterialColors);
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AmongUs.GameOptions;
|
using System.Text;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using MiraAPI.LocalSettings;
|
||||||
using MiraAPI.Modifiers;
|
using MiraAPI.Modifiers;
|
||||||
using MiraAPI.Modifiers.Types;
|
using MiraAPI.Modifiers.Types;
|
||||||
using MiraAPI.PluginLoading;
|
using MiraAPI.PluginLoading;
|
||||||
using MiraAPI.Roles;
|
using MiraAPI.Roles;
|
||||||
using MiraAPI.Utilities;
|
|
||||||
using MiraAPI.Utilities.Assets;
|
using MiraAPI.Utilities.Assets;
|
||||||
using TMPro;
|
using Reactor.Utilities.Extensions;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@@ -21,6 +21,8 @@ namespace MiraAPI.Patches.Freeplay;
|
|||||||
internal static class TaskAdderPatches
|
internal static class TaskAdderPatches
|
||||||
{
|
{
|
||||||
private static Scroller _scroller = null!;
|
private static Scroller _scroller = null!;
|
||||||
|
private static Dictionary<string, TaskFolder> folders = new();
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(nameof(TaskAdderGame.Begin))]
|
[HarmonyPatch(nameof(TaskAdderGame.Begin))]
|
||||||
public static void AddRolesFolder(TaskAdderGame __instance)
|
public static void AddRolesFolder(TaskAdderGame __instance)
|
||||||
@@ -60,46 +62,80 @@ internal static class TaskAdderPatches
|
|||||||
__instance.RoleButton.GetComponent<PassiveButton>().ClickMask = collider;
|
__instance.RoleButton.GetComponent<PassiveButton>().ClickMask = collider;
|
||||||
__instance.RootFolderPrefab.GetComponent<PassiveButton>().ClickMask = collider;
|
__instance.RootFolderPrefab.GetComponent<PassiveButton>().ClickMask = collider;
|
||||||
__instance.RootFolderPrefab.gameObject.SetActive(false);
|
__instance.RootFolderPrefab.gameObject.SetActive(false);
|
||||||
|
|
||||||
__instance.TaskParent = inner.transform;
|
__instance.TaskParent = inner.transform;
|
||||||
|
|
||||||
var rolesFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner);
|
var crewmateFolder = __instance.Root.SubFolders.ToArray().FirstOrDefault(x => x.FolderName == "Crewmate")!;
|
||||||
rolesFolder.gameObject.SetActive(false);
|
var impostorFolder = __instance.Root.SubFolders.ToArray().FirstOrDefault(x => x.FolderName == "Impostor")!;
|
||||||
rolesFolder.FolderName = "Roles";
|
var neutralFolder = __instance.CreateFolder("Neutral", __instance.Root, 2, Color.gray);
|
||||||
rolesFolder.name = "RolesFolder";
|
var modifiersFolder = __instance.CreateFolder("Modifiers", __instance.Root, 0, Color.blue);
|
||||||
|
|
||||||
var modifiersFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner);
|
folders.Clear();
|
||||||
modifiersFolder.gameObject.SetActive(false);
|
folders.Add("Crewmate", crewmateFolder);
|
||||||
modifiersFolder.FolderName = "Modifiers";
|
folders.Add("Impostor", impostorFolder);
|
||||||
modifiersFolder.name = "ModifiersFolder";
|
folders.Add("Neutral", neutralFolder);
|
||||||
|
folders.Add("Modifiers", modifiersFolder);
|
||||||
|
|
||||||
|
int folderIdx = 3;
|
||||||
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins)
|
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins)
|
||||||
{
|
{
|
||||||
if (plugin.InternalRoles.Any(x => x.Value is ICustomRole { Configuration.ShowInFreeplay: true }))
|
var pluginFolders = new Dictionary<string, TaskFolder>();
|
||||||
|
|
||||||
|
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);
|
var customRole = role as ICustomRole;
|
||||||
newFolder.name = plugin.PluginId+":Roles";
|
var folderName = customRole!.Configuration.FreeplayFolder;
|
||||||
newFolder.FolderName = plugin.PluginInfo.Metadata.Name;
|
if (!folders.TryGetValue(folderName, out var teamFolder))
|
||||||
newFolder.gameObject.SetActive(false);
|
{
|
||||||
rolesFolder.SubFolders.Add(newFolder);
|
teamFolder = __instance.CreateFolder(folderName, __instance.Root, folderIdx++, customRole.IntroConfiguration?.IntroTeamColor ?? Color.gray);
|
||||||
|
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))
|
if (plugin.InternalModifiers.Exists(x => x.ShowInFreeplay))
|
||||||
{
|
{
|
||||||
var newFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner);
|
__instance.CreateFolder(plugin.PluginInfo.Metadata.Name, modifiersFolder)
|
||||||
newFolder.name = plugin.PluginId+":Modifiers";
|
.gameObject.name = plugin.PluginId;
|
||||||
newFolder.FolderName = plugin.PluginInfo.Metadata.Name;
|
|
||||||
newFolder.gameObject.SetActive(false);
|
|
||||||
modifiersFolder.SubFolders.Add(newFolder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__instance.Root.SubFolders.Add(rolesFolder);
|
// Modifier folder at the end
|
||||||
__instance.Root.SubFolders.Add(modifiersFolder);
|
__instance.Root.SubFolders.Insert(folderIdx, modifiersFolder);
|
||||||
|
|
||||||
__instance.GoToRoot();
|
__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(
|
private static void AddFileAsChildCustom(
|
||||||
this TaskAdderGame instance,
|
this TaskAdderGame instance,
|
||||||
TaskAddButton item,
|
TaskAddButton item,
|
||||||
@@ -122,40 +158,46 @@ internal static class TaskAdderPatches
|
|||||||
instance.ActiveItems.Add(item.transform);
|
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:
|
// yes it might be crazy patching the entire method, but i tried so many other methods and only this works :cry:
|
||||||
|
// true -chip
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(nameof(TaskAdderGame.ShowFolder))]
|
[HarmonyPatch(nameof(TaskAdderGame.ShowFolder))]
|
||||||
public static bool ShowPatch(TaskAdderGame __instance, TaskFolder taskFolder)
|
public static bool ShowPatch(TaskAdderGame __instance, TaskFolder taskFolder)
|
||||||
{
|
{
|
||||||
var stringBuilder = new Il2CppSystem.Text.StringBuilder(64);
|
StringBuilder stringBuilder = new StringBuilder(64);
|
||||||
__instance.Hierarchy.Add(taskFolder);
|
__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(t.FolderName);
|
||||||
stringBuilder.Append("\\");
|
stringBuilder.Append('\\');
|
||||||
}
|
}
|
||||||
|
|
||||||
__instance.PathText.text = stringBuilder.ToString();
|
__instance.PathText.text = stringBuilder.ToString();
|
||||||
for (var j = 0; j < __instance.ActiveItems.Count; j++)
|
var prettyEnabled = LocalSettingsTabSingleton<MiraApiSettings>.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.DestroyImmediate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__instance.ActiveItems.ToArray().Do(x => x.gameObject.Destroy());
|
||||||
__instance.ActiveItems.Clear();
|
__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.gameObject.SetActive(true);
|
||||||
taskFolder2.Parent = __instance;
|
taskFolder2.Parent = __instance;
|
||||||
|
taskFolder2.transform.localPosition = new Vector3(num, num2, 0f);
|
||||||
folderTransform.localPosition = new Vector3(num, num2, 0f);
|
taskFolder2.transform.localScale = Vector3.one;
|
||||||
folderTransform.localScale = Vector3.one;
|
num3 = Mathf.Max(num3, taskFolder2.Text.bounds.size.y + 1.1f);
|
||||||
num3 = Mathf.Max(num3, taskFolder2.Text.bounds.size.y + 1.3f);
|
|
||||||
num += __instance.folderWidth;
|
num += __instance.folderWidth;
|
||||||
if (num > __instance.lineWidth)
|
if (num > __instance.lineWidth)
|
||||||
{
|
{
|
||||||
@@ -164,242 +206,74 @@ internal static class TaskAdderPatches
|
|||||||
num3 = 0f;
|
num3 = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
__instance.ActiveItems.Add(folderTransform);
|
__instance.ActiveItems.Add(taskFolder2.transform);
|
||||||
if (!taskFolder2 || !taskFolder2.Button)
|
if (taskFolder2 != null && taskFolder2.Button != null)
|
||||||
{
|
{
|
||||||
continue;
|
ControllerManager.Instance.AddSelectableUiElement(taskFolder2.Button);
|
||||||
}
|
|
||||||
|
|
||||||
ControllerManager.Instance.AddSelectableUiElement(taskFolder2.Button);
|
|
||||||
if (!string.IsNullOrEmpty(__instance.restorePreviousSelectionByFolderName) &&
|
|
||||||
taskFolder2.FolderName.Equals(__instance.restorePreviousSelectionByFolderName, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
__instance.restorePreviousSelectionFound = taskFolder2.Button;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var flag = false;
|
var list = taskFolder.TaskChildren
|
||||||
var list = taskFolder.Children.ToArray().OrderBy(t => t.TaskType).ToList();
|
.ToArray()
|
||||||
|
.OrderBy(x => x.TaskType)
|
||||||
for (var l = 0; l < list.Count; l++)
|
.ToArray();
|
||||||
|
foreach (var task in list)
|
||||||
{
|
{
|
||||||
var taskAddButton = Object.Instantiate(__instance.TaskPrefab);
|
TaskAddButton taskAddButton = Object.Instantiate(__instance.TaskPrefab);
|
||||||
taskAddButton.MyTask = list.ToArray()[l];
|
taskAddButton.MyTask = task;
|
||||||
switch (taskAddButton.MyTask.TaskType)
|
switch (task.TaskType)
|
||||||
{
|
{
|
||||||
case TaskTypes.DivertPower:
|
case TaskTypes.DivertPower:
|
||||||
{
|
{
|
||||||
var targetSystem = taskAddButton.MyTask.Cast<DivertPowerTask>().TargetSystem;
|
var targetSystem = task.Cast<DivertPowerTask>().TargetSystem;
|
||||||
taskAddButton.Text.text = TranslationController.Instance.GetString(
|
taskAddButton.Text.text = TranslationController.Instance.GetString(
|
||||||
StringNames.DivertPowerTo,
|
StringNames.DivertPowerTo,
|
||||||
TranslationController.Instance.GetString(targetSystem));
|
TranslationController.Instance.GetString(targetSystem));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TaskTypes.FixWeatherNode:
|
case TaskTypes.FixWeatherNode:
|
||||||
{
|
{
|
||||||
var nodeId = taskAddButton.MyTask.Cast<WeatherNodeTask>().NodeId;
|
var nodeId = task.Cast<WeatherNodeTask>().NodeId;
|
||||||
taskAddButton.Text.text =
|
taskAddButton.Text.text =
|
||||||
TranslationController.Instance.GetString(
|
TranslationController.Instance.GetString(
|
||||||
StringNames.FixWeatherNode) + " " +
|
StringNames.FixWeatherNode) + " " +
|
||||||
TranslationController.Instance.GetString(
|
TranslationController.Instance.GetString(
|
||||||
WeatherSwitchGame.ControlNames[nodeId]);
|
WeatherSwitchGame.ControlNames[nodeId]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
taskAddButton.Text.text =
|
taskAddButton.Text.text =
|
||||||
TranslationController.Instance.GetString(taskAddButton.MyTask.TaskType);
|
TranslationController.Instance.GetString(task.TaskType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
__instance.AddFileAsChildCustom(taskAddButton, ref num, ref num2, ref num3);
|
__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, false);
|
||||||
}
|
|
||||||
|
|
||||||
ControllerManager.Instance.AddSelectableUiElement(taskAddButton.Button);
|
|
||||||
if (__instance.Hierarchy.Count == 1 || flag)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var component =
|
|
||||||
ControllerManager.Instance.CurrentUiState.CurrentSelection.GetComponent<TaskFolder>();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(':');
|
TaskAddButton roleAddButton = Object.Instantiate(__instance.RoleButton);
|
||||||
if (split.Length == 2)
|
roleAddButton.SafePositionWorld = __instance.SafePositionWorld;
|
||||||
|
roleAddButton.Text.text = prettyEnabled ? role.NiceName : "Be_" + role.NiceName + ".exe";
|
||||||
|
roleAddButton.Role = role;
|
||||||
|
if (prettyEnabled)
|
||||||
{
|
{
|
||||||
var pluginId = split[0];
|
roleAddButton.Text.fontSizeMin = 1;
|
||||||
var folderName = split[1];
|
roleAddButton.FileImage.sprite = role.IsImpostor
|
||||||
|
? MiraAssets.ImpostorFile.LoadAsset()
|
||||||
if (MiraPluginManager.GetPluginByGuid(pluginId) is { } plugin)
|
: MiraAssets.CrewmateFile.LoadAsset();
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (role is ICustomRole custom)
|
||||||
|
|
||||||
foreach (var chip in __instance.ActiveItems)
|
|
||||||
{
|
|
||||||
chip.GetComponentInChildren<TextMeshPro>().EnableStencilMasking();
|
|
||||||
chip.GetComponent<SpriteRenderer>().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)
|
|
||||||
{
|
{
|
||||||
|
if (prettyEnabled && custom.Team == ModdedRoleTeams.Custom) roleAddButton.FileImage.sprite = MiraAssets.CustomTeamFile.LoadAsset();
|
||||||
var customColor = custom.IntroConfiguration?.IntroTeamColor ?? Color.gray;
|
var customColor = custom.IntroConfiguration?.IntroTeamColor ?? Color.gray;
|
||||||
if (custom.Team is ModdedRoleTeams.Crewmate)
|
if (custom.Team is ModdedRoleTeams.Crewmate)
|
||||||
{
|
{
|
||||||
@@ -409,26 +283,84 @@ internal static class TaskAdderPatches
|
|||||||
{
|
{
|
||||||
customColor = Palette.ImpostorRed;
|
customColor = Palette.ImpostorRed;
|
||||||
}
|
}
|
||||||
taskAddButton2.FileImage.color = customColor;
|
roleAddButton.FileImage.color = customColor;
|
||||||
taskAddButton2.RolloverHandler.OutColor = 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(roleAddButton.Button);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ public static class RoleManagerPatches
|
|||||||
data.Role.Deinitialize(targetPlayer);
|
data.Role.Deinitialize(targetPlayer);
|
||||||
Object.Destroy(data.Role.gameObject);
|
Object.Destroy(data.Role.gameObject);
|
||||||
}
|
}
|
||||||
var roleBehaviour = Object.Instantiate<RoleBehaviour>(__instance.AllRoles.First(r => r.Role == roleType), data.gameObject.transform);
|
var roleBehaviour = Object.Instantiate<RoleBehaviour>(__instance.AllRoles.ToArray().First(r => r.Role == roleType), data.gameObject.transform);
|
||||||
roleBehaviour.Initialize(targetPlayer);
|
roleBehaviour.Initialize(targetPlayer);
|
||||||
targetPlayer.Data.Role = roleBehaviour;
|
targetPlayer.Data.Role = roleBehaviour;
|
||||||
targetPlayer.Data.RoleType = roleType;
|
targetPlayer.Data.RoleType = roleType;
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
@@ -32,6 +32,12 @@ public record struct CustomRoleConfiguration
|
|||||||
TasksCountForProgress = role.Team is ModdedRoleTeams.Crewmate;
|
TasksCountForProgress = role.Team is ModdedRoleTeams.Crewmate;
|
||||||
HideSettings = roleBehaviour?.IsDead == true;
|
HideSettings = roleBehaviour?.IsDead == true;
|
||||||
ShowInFreeplay = roleBehaviour?.IsDead == false;
|
ShowInFreeplay = roleBehaviour?.IsDead == false;
|
||||||
|
FreeplayFolder = role.Team switch
|
||||||
|
{
|
||||||
|
ModdedRoleTeams.Crewmate => "Crewmate",
|
||||||
|
ModdedRoleTeams.Impostor => "Impostor",
|
||||||
|
_ => "Neutral",
|
||||||
|
};
|
||||||
IntroSound = role.Team is ModdedRoleTeams.Crewmate
|
IntroSound = role.Team is ModdedRoleTeams.Crewmate
|
||||||
? CustomRoleManager.CrewmateIntroSound
|
? CustomRoleManager.CrewmateIntroSound
|
||||||
: CustomRoleManager.ImpostorIntroSound;
|
: CustomRoleManager.ImpostorIntroSound;
|
||||||
@@ -112,6 +118,11 @@ public record struct CustomRoleConfiguration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShowInFreeplay { get; set; }
|
public bool ShowInFreeplay { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a freeplay folder this role belongs to. Defaults to team folder.
|
||||||
|
/// </summary>
|
||||||
|
public string FreeplayFolder { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the outline color for the KillButton if <see cref="UseVanillaKillButton"/> is true.
|
/// Gets or sets the outline color for the KillButton if <see cref="UseVanillaKillButton"/> is true.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ public static class CustomRoleManager
|
|||||||
public static readonly LoadableAsset<AudioClip> ImpostorIntroSound =
|
public static readonly LoadableAsset<AudioClip> ImpostorIntroSound =
|
||||||
CustomRoleUtils.GetIntroSound(RoleTypes.Impostor)!;
|
CustomRoleUtils.GetIntroSound(RoleTypes.Impostor)!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of all roles from vanilla RoleManager.
|
||||||
|
/// </summary>
|
||||||
|
public static RoleBehaviour[] AllRoles => RoleManager.Instance.AllRoles.ToArray();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the list of custom roles as RoleBehaviour objects.
|
/// Gets the list of custom roles as RoleBehaviour objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -57,7 +62,10 @@ public static class CustomRoleManager
|
|||||||
|
|
||||||
internal static void RegisterInRoleManager()
|
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))
|
foreach (var role in CustomRoles.Values.Where(x => x.IsDead))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using AmongUs.GameOptions;
|
using AmongUs.GameOptions;
|
||||||
using MiraAPI.Utilities.Assets;
|
using MiraAPI.Utilities.Assets;
|
||||||
using Reactor.Utilities;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MiraAPI.Roles;
|
namespace MiraAPI.Roles;
|
||||||
@@ -56,7 +55,7 @@ public static class CustomRoleUtils
|
|||||||
/// <returns>The intro sound.</returns>
|
/// <returns>The intro sound.</returns>
|
||||||
public static LoadableAsset<AudioClip>? GetIntroSound(RoleTypes roleType)
|
public static LoadableAsset<AudioClip>? 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)
|
if (role is ICustomRole customRole)
|
||||||
{
|
{
|
||||||
return customRole.Configuration.IntroSound;
|
return customRole.Configuration.IntroSound;
|
||||||
|
|||||||
@@ -105,6 +105,26 @@ public static class MiraAssets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LoadableResourceAsset KeybindButton { get; } = new("MiraAPI.Resources.KeybindButton.png");
|
public static LoadableResourceAsset KeybindButton { get; } = new("MiraAPI.Resources.KeybindButton.png");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sprite used for crewmate role files in TaskAdderGame.
|
||||||
|
/// </summary>
|
||||||
|
public static LoadableResourceAsset CrewmateFile { get; } = new("MiraAPI.Resources.CrewmateFile.png");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sprite used for impostor role files in TaskAdderGame.
|
||||||
|
/// </summary>
|
||||||
|
public static LoadableResourceAsset ImpostorFile { get; } = new("MiraAPI.Resources.ImpostorFile.png");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sprite used for custom team role files in TaskAdderGame.
|
||||||
|
/// </summary>
|
||||||
|
public static LoadableResourceAsset CustomTeamFile { get; } = new("MiraAPI.Resources.CustomFile.png");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sprite used for modifier file in TaskAdderGame.
|
||||||
|
/// </summary>
|
||||||
|
public static LoadableResourceAsset ModifierFile { get; } = new("MiraAPI.Resources.ModifierFile.png");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the sprite used for timed modifier file in TaskAdderGame.
|
/// Gets the sprite used for timed modifier file in TaskAdderGame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in new issue
Block a user