mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-19 15:51:48 +00:00
14 files changed
+258
-282
No files matched your search
+2
-2
@@ -2,12 +2,12 @@
|
||||
<ItemGroup>
|
||||
<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="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.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''">
|
||||
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(AmongUs)/BepInEx/plugins/" UseSymboliclinksIfPossible="true" />
|
||||
</Target>
|
||||
|
||||
@@ -30,4 +30,10 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
|
||||
/// Gets whether to show keybinds in the control mapper.
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -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<string, TaskFolder> folders = new();
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(nameof(TaskAdderGame.Begin))]
|
||||
public static void AddRolesFolder(TaskAdderGame __instance)
|
||||
@@ -60,46 +62,80 @@ internal static class TaskAdderPatches
|
||||
__instance.RoleButton.GetComponent<PassiveButton>().ClickMask = collider;
|
||||
__instance.RootFolderPrefab.GetComponent<PassiveButton>().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<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);
|
||||
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.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))
|
||||
{
|
||||
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<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();
|
||||
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,242 +206,74 @@ 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<DivertPowerTask>().TargetSystem;
|
||||
taskAddButton.Text.text = TranslationController.Instance.GetString(
|
||||
StringNames.DivertPowerTo,
|
||||
TranslationController.Instance.GetString(targetSystem));
|
||||
break;
|
||||
}
|
||||
{
|
||||
var targetSystem = task.Cast<DivertPowerTask>().TargetSystem;
|
||||
taskAddButton.Text.text = TranslationController.Instance.GetString(
|
||||
StringNames.DivertPowerTo,
|
||||
TranslationController.Instance.GetString(targetSystem));
|
||||
break;
|
||||
}
|
||||
case TaskTypes.FixWeatherNode:
|
||||
{
|
||||
var nodeId = taskAddButton.MyTask.Cast<WeatherNodeTask>().NodeId;
|
||||
taskAddButton.Text.text =
|
||||
TranslationController.Instance.GetString(
|
||||
StringNames.FixWeatherNode) + " " +
|
||||
TranslationController.Instance.GetString(
|
||||
WeatherSwitchGame.ControlNames[nodeId]);
|
||||
break;
|
||||
}
|
||||
{
|
||||
var nodeId = task.Cast<WeatherNodeTask>().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<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;
|
||||
}
|
||||
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)
|
||||
TaskAddButton roleAddButton = Object.Instantiate(__instance.RoleButton);
|
||||
roleAddButton.SafePositionWorld = __instance.SafePositionWorld;
|
||||
roleAddButton.Text.text = prettyEnabled ? role.NiceName : "Be_" + role.NiceName + ".exe";
|
||||
roleAddButton.Role = role;
|
||||
if (prettyEnabled)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
roleAddButton.Text.fontSizeMin = 1;
|
||||
roleAddButton.FileImage.sprite = role.IsImpostor
|
||||
? MiraAssets.ImpostorFile.LoadAsset()
|
||||
: MiraAssets.CrewmateFile.LoadAsset();
|
||||
}
|
||||
}
|
||||
|
||||
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 (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)
|
||||
{
|
||||
@@ -409,26 +283,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;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public static class RoleManagerPatches
|
||||
data.Role.Deinitialize(targetPlayer);
|
||||
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);
|
||||
targetPlayer.Data.Role = roleBehaviour;
|
||||
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;
|
||||
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
|
||||
/// </summary>
|
||||
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>
|
||||
/// Gets or sets the outline color for the KillButton if <see cref="UseVanillaKillButton"/> is true.
|
||||
/// </summary>
|
||||
|
||||
@@ -35,6 +35,11 @@ public static class CustomRoleManager
|
||||
public static readonly LoadableAsset<AudioClip> ImpostorIntroSound =
|
||||
CustomRoleUtils.GetIntroSound(RoleTypes.Impostor)!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of all roles from vanilla RoleManager.
|
||||
/// </summary>
|
||||
public static RoleBehaviour[] AllRoles => RoleManager.Instance.AllRoles.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of custom roles as RoleBehaviour objects.
|
||||
/// </summary>
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
/// <returns>The intro sound.</returns>
|
||||
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)
|
||||
{
|
||||
return customRole.Configuration.IntroSound;
|
||||
|
||||
@@ -105,6 +105,26 @@ public static class MiraAssets
|
||||
/// </summary>
|
||||
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>
|
||||
/// Gets the sprite used for timed modifier file in TaskAdderGame.
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user