mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-19 15:51:48 +00:00
Make everything more attribute-based, WIP
This commit is contained in:
1 parent
5f29175235
commit
658e3659c5
25 files changed
+604
-82
No files matched your search
@@ -0,0 +1,15 @@
|
|||||||
|
using MiraAPI.Roles;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MiraAPI.Example
|
||||||
|
{
|
||||||
|
[RegisterCustomRole(ExamplePlugin.Id)]
|
||||||
|
public class CustomRole : CrewmateRole, ICustomRole
|
||||||
|
{
|
||||||
|
public string RoleName => "Sussy Baka";
|
||||||
|
public string RoleDescription => "Role decs?";
|
||||||
|
public string RoleLongDescription => "Extra role decs?";
|
||||||
|
public Color RoleColor => Palette.Orange;
|
||||||
|
public RoleTeamTypes Team => RoleTeamTypes.Crewmate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using MiraAPI.API.GameOptions;
|
||||||
|
using MiraAPI.GameOptions;
|
||||||
|
using MiraAPI.GameOptions.Attributes;
|
||||||
|
using MiraAPI.Utilities;
|
||||||
|
using MiraAPI.Utilities.Assets;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MiraAPI.Example
|
||||||
|
{
|
||||||
|
[RegisterCustomOptions(ExamplePlugin.Id)]
|
||||||
|
public class ExampleOptions : IModOptions
|
||||||
|
{
|
||||||
|
public LoadableAsset<Sprite> OptionsTabIcon => MiraAssets.Empty;
|
||||||
|
public static CustomToggleOption YeOrNa = new CustomToggleOption("Ye or Na", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using BepInEx;
|
||||||
|
using BepInEx.Unity.IL2CPP;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Reactor;
|
||||||
|
using Reactor.Networking;
|
||||||
|
using Reactor.Networking.Attributes;
|
||||||
|
|
||||||
|
namespace MiraAPI.Example;
|
||||||
|
|
||||||
|
[BepInAutoPlugin("mira.example", "MiraAPIExample")]
|
||||||
|
[BepInProcess("Among Us.exe")]
|
||||||
|
[BepInDependency(ReactorPlugin.Id)]
|
||||||
|
[ReactorModFlags(ModFlags.RequireOnAllClients)]
|
||||||
|
public partial class ExamplePlugin : BasePlugin
|
||||||
|
{
|
||||||
|
public Harmony Harmony { get; } = new(Id);
|
||||||
|
public static ExamplePlugin Instance { get; private set; }
|
||||||
|
public override void Load()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
Harmony.PatchAll();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
|
||||||
|
<VersionPrefix>1.0.0</VersionPrefix>
|
||||||
|
<VersionSuffix>dev</VersionSuffix>
|
||||||
|
<Description>Simple and easy to use Among Us modding API.</Description>
|
||||||
|
<Authors>Angxl, XtraCube</Authors>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<GamePlatform Condition="'$(GamePlatform)' == ''">Steam</GamePlatform>
|
||||||
|
<GameVersion Condition="'$(GamePlatform)' == 'Steam'">2024.3.5</GameVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Reactor" Version="2.2.0" />
|
||||||
|
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.688" Private="false" ExcludeAssets="runtime;native" />
|
||||||
|
<PackageReference Include="Iced" Version="1.20.0" />
|
||||||
|
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2024.3.5" 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">
|
||||||
|
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MiraAPI\MiraAPI.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''">
|
||||||
|
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(AmongUs)/BepInEx/plugins/" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
+13
-1
@@ -1,6 +1,11 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiraAPI", "MiraAPI\MiraAPI.csproj", "{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}"
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.9.34622.214
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiraAPI", "MiraAPI\MiraAPI.csproj", "{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiraAPI.Example", "MiraAPI.Example\MiraAPI.Example.csproj", "{19B76855-16CC-43CC-A0A6-5A7FFB43F077}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -12,5 +17,12 @@ Global
|
|||||||
{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.Build.0 = Release|Any CPU
|
{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using MiraAPI.Roles;
|
using BepInEx;
|
||||||
|
using MiraAPI.Roles;
|
||||||
using Reactor.Localization.Utilities;
|
using Reactor.Localization.Utilities;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ public abstract class AbstractGameOption
|
|||||||
public CustomOptionGroup Group { get; set; }
|
public CustomOptionGroup Group { get; set; }
|
||||||
public Func<bool> Hidden { get; set; }
|
public Func<bool> Hidden { get; set; }
|
||||||
public OptionBehaviour OptionBehaviour { get; protected set; }
|
public OptionBehaviour OptionBehaviour { get; protected set; }
|
||||||
|
public PluginInfo ParentMod { get; set; }
|
||||||
public void ValueChanged(OptionBehaviour optionBehaviour)
|
public void ValueChanged(OptionBehaviour optionBehaviour)
|
||||||
{
|
{
|
||||||
OnValueChanged(optionBehaviour);
|
OnValueChanged(optionBehaviour);
|
||||||
@@ -33,6 +35,5 @@ public abstract class AbstractGameOption
|
|||||||
|
|
||||||
Save = save;
|
Save = save;
|
||||||
Hidden = () => false;
|
Hidden = () => false;
|
||||||
CustomOptionsManager.CustomOptions.Add(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace MiraAPI.GameOptions.Attributes
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Field)]
|
||||||
|
public class RegisterCustomOptionAttribute : Attribute
|
||||||
|
{
|
||||||
|
private static readonly HashSet<Assembly> RegisteredAssemblies = [];
|
||||||
|
public string ModId { get; }
|
||||||
|
|
||||||
|
public RegisterCustomOptionAttribute(string modId)
|
||||||
|
{
|
||||||
|
ModId = modId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using BepInEx.Unity.IL2CPP;
|
||||||
|
using MiraAPI.API.GameOptions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace MiraAPI.GameOptions.Attributes
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class RegisterCustomOptionsAttribute : Attribute
|
||||||
|
{
|
||||||
|
private static readonly HashSet<Assembly> RegisteredAssemblies = [];
|
||||||
|
public string ModId { get; }
|
||||||
|
public List<FieldInfo> Options;
|
||||||
|
|
||||||
|
public RegisterCustomOptionsAttribute(string modId)
|
||||||
|
{
|
||||||
|
ModId = modId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
IL2CPPChainloader.Instance.PluginLoad += (_, assembly, plugin) => Register(assembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Register(Assembly assembly)
|
||||||
|
{
|
||||||
|
if (!RegisteredAssemblies.Add(assembly)) return;
|
||||||
|
|
||||||
|
foreach (var type in assembly.GetTypes())
|
||||||
|
{
|
||||||
|
var attribute = type.GetCustomAttribute<RegisterCustomOptionsAttribute>();
|
||||||
|
if (attribute != null)
|
||||||
|
{
|
||||||
|
attribute.Options = type.GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||||
|
.Where(fi => fi.FieldType.BaseType == typeof(AbstractGameOption) || fi.FieldType.BaseType == typeof(CustomOptionGroup)).ToList();
|
||||||
|
CustomOptionsManager.RegisterOptionsForMod(type, attribute.Options, attribute.ModId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,8 +42,6 @@ public class CustomNumberOption : AbstractGameOption
|
|||||||
Logger<MiraAPIPlugin>.Warning(e.ToString());
|
Logger<MiraAPIPlugin>.Warning(e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomOptionsManager.CustomNumberOptions.Add(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(float newValue)
|
public void SetValue(float newValue)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using MiraAPI.Roles;
|
using BepInEx;
|
||||||
|
using MiraAPI.Roles;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -11,6 +12,7 @@ public class CustomOptionGroup
|
|||||||
|
|
||||||
public GameObject Header;
|
public GameObject Header;
|
||||||
public Type AdvancedRole { get; set; }
|
public Type AdvancedRole { get; set; }
|
||||||
|
public PluginInfo ParentMod { get; set; }
|
||||||
|
|
||||||
public readonly List<AbstractGameOption> Options = [];
|
public readonly List<AbstractGameOption> Options = [];
|
||||||
public readonly List<CustomNumberOption> CustomNumberOptions;
|
public readonly List<CustomNumberOption> CustomNumberOptions;
|
||||||
@@ -40,7 +42,5 @@ public class CustomOptionGroup
|
|||||||
{
|
{
|
||||||
option.Group = this;
|
option.Group = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomOptionsManager.CustomGroups.Add(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,14 @@
|
|||||||
using MiraAPI.Networking.Options;
|
using BepInEx;
|
||||||
|
using BepInEx.Unity.IL2CPP;
|
||||||
|
using MiraAPI.GameOptions;
|
||||||
|
using MiraAPI.Networking.Options;
|
||||||
using Reactor.Networking.Rpc;
|
using Reactor.Networking.Rpc;
|
||||||
using Reactor.Utilities;
|
using Reactor.Utilities;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MiraAPI.API.GameOptions;
|
namespace MiraAPI.API.GameOptions;
|
||||||
|
|
||||||
@@ -13,6 +19,56 @@ public static class CustomOptionsManager
|
|||||||
public static readonly List<CustomToggleOption> CustomToggleOptions = [];
|
public static readonly List<CustomToggleOption> CustomToggleOptions = [];
|
||||||
public static readonly List<CustomStringOption> CustomStringOptions = [];
|
public static readonly List<CustomStringOption> CustomStringOptions = [];
|
||||||
public static readonly List<CustomOptionGroup> CustomGroups = [];
|
public static readonly List<CustomOptionGroup> CustomGroups = [];
|
||||||
|
public static readonly List<PluginInfo> RegisteredMods = [];
|
||||||
|
|
||||||
|
public static void RegisterOptionsForMod(Type type, List<FieldInfo> fields, string modId)
|
||||||
|
{
|
||||||
|
if (!typeof(IModOptions).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
Debug.LogError($"Cannot register options for {modId}! Missing IModOptions interface.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PluginInfo info = IL2CPPChainloader.Instance.Plugins[modId];
|
||||||
|
|
||||||
|
if (info == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"Registering Options for {modId}");
|
||||||
|
|
||||||
|
RegisteredMods.Add(info);
|
||||||
|
foreach (FieldInfo field in fields)
|
||||||
|
{
|
||||||
|
AbstractGameOption option = (AbstractGameOption)field.GetValue(null);
|
||||||
|
if (option == null)
|
||||||
|
{
|
||||||
|
CustomOptionGroup group = (CustomOptionGroup)field.GetValue(null);
|
||||||
|
group.ParentMod = info;
|
||||||
|
CustomGroups.Add(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
option.ParentMod = info;
|
||||||
|
|
||||||
|
CustomOptions.Add(option);
|
||||||
|
switch (field.FieldType.Name)
|
||||||
|
{
|
||||||
|
case nameof(CustomNumberOption):
|
||||||
|
CustomNumberOptions.Add((CustomNumberOption)option);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(CustomToggleOption):
|
||||||
|
CustomToggleOptions.Add((CustomToggleOption)option);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(CustomStringOption):
|
||||||
|
CustomStringOptions.Add((CustomStringOption)option);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void SyncOptions()
|
public static void SyncOptions()
|
||||||
{
|
{
|
||||||
if (!AmongUsClient.Instance.AmHost)
|
if (!AmongUsClient.Instance.AmHost)
|
||||||
|
|||||||
@@ -1,38 +1,40 @@
|
|||||||
using Reactor.Utilities.Extensions;
|
using Reactor.Utilities.Extensions;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace MiraAPI.API.GameOptions;
|
namespace MiraAPI.API.GameOptions;
|
||||||
public static class CustomOptionsTab
|
public static class CustomOptionsTab
|
||||||
{
|
{
|
||||||
public static GameObject CustomTab;
|
public static List<GameObject> CustomTabs;
|
||||||
public static GameObject CustomScreen;
|
public static List<GameObject> CustomScreens;
|
||||||
public static SpriteRenderer Rend;
|
public static SpriteRenderer Rend;
|
||||||
|
|
||||||
public static GameObject Initialize(GameSettingMenu __instance)
|
public static GameObject Initialize(GameSettingMenu __instance)
|
||||||
{
|
{
|
||||||
var gameBtn = __instance.transform.FindChild("Header/Tabs/GameTab").gameObject;
|
var gameBtn = __instance.transform.FindChild("Header/Tabs/GameTab").gameObject;
|
||||||
var roleBtn = __instance.transform.FindChild("Header/Tabs/RoleTab").gameObject;
|
var roleBtn = __instance.transform.FindChild("Header/Tabs/RoleTab").gameObject;
|
||||||
|
var screen = CreateNewMenu(__instance);
|
||||||
|
var tab = CreateCustomTab(__instance, screen, gameBtn, roleBtn);
|
||||||
|
|
||||||
CustomScreen = CreateNewMenu(__instance);
|
CustomScreens.Add(screen);
|
||||||
CustomTab = CreateCustomTab(__instance, CustomScreen, gameBtn, roleBtn);
|
CustomTabs.Add(tab);
|
||||||
|
|
||||||
Rend = CustomTab.transform.FindChild("LaunchpadBtn/Tab Background").GetComponent<SpriteRenderer>();
|
Rend = tab.transform.FindChild("Btn/Tab Background").GetComponent<SpriteRenderer>();
|
||||||
Rend.enabled = false;
|
Rend.enabled = false;
|
||||||
|
|
||||||
UpdateListeners(__instance, gameBtn.GetComponentInChildren<PassiveButton>(), roleBtn.GetComponentInChildren<PassiveButton>(), Rend);
|
UpdateListeners(__instance, gameBtn.GetComponentInChildren<PassiveButton>(), roleBtn.GetComponentInChildren<PassiveButton>(), Rend);
|
||||||
|
|
||||||
var container = CustomScreen.transform.FindChild("GameGroup/SliderInner");
|
var container = screen.transform.FindChild("GameGroup/SliderInner");
|
||||||
container.DestroyChildren();
|
container.DestroyChildren();
|
||||||
CreateNewResetButton(__instance, container);
|
//CreateNewResetButton(__instance, container);
|
||||||
|
|
||||||
return container.gameObject;
|
return container.gameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateNewResetButton(GameSettingMenu __instance, Transform container)
|
/*private static void CreateNewResetButton(GameSettingMenu __instance, Transform container)
|
||||||
{
|
{
|
||||||
var resetBtn = __instance.RegularGameSettings.transform.FindChild("GameGroup/SliderInner/ResetToDefault");
|
var resetBtn = __instance.RegularGameSettings.transform.FindChild("GameGroup/SliderInner/ResetToDefault");
|
||||||
var newResetBtn = Object.Instantiate(resetBtn.gameObject, container);
|
var newResetBtn = Object.Instantiate(resetBtn.gameObject, container);
|
||||||
@@ -54,12 +56,12 @@ public static class CustomOptionsTab
|
|||||||
toggle.OnClick.AddListener((UnityAction)(() => { CustomOptionsManager.ResetToDefault(); }));
|
toggle.OnClick.AddListener((UnityAction)(() => { CustomOptionsManager.ResetToDefault(); }));
|
||||||
toggle.OnMouseOver.AddListener((UnityAction)(() => { tmp.text = "<b>Reset Options</b>"; }));
|
toggle.OnMouseOver.AddListener((UnityAction)(() => { tmp.text = "<b>Reset Options</b>"; }));
|
||||||
toggle.OnMouseOut.AddListener((UnityAction)(() => { tmp.text = "Reset Options"; }));
|
toggle.OnMouseOut.AddListener((UnityAction)(() => { tmp.text = "Reset Options"; }));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private static void UpdateListeners(GameSettingMenu __instance, PassiveButton gameB, PassiveButton roleB, SpriteRenderer rend)
|
private static void UpdateListeners(GameSettingMenu __instance, PassiveButton gameB, PassiveButton roleB, SpriteRenderer rend)
|
||||||
{
|
{
|
||||||
gameB.OnClick.RemoveAllListeners();
|
gameB.OnClick.RemoveAllListeners();
|
||||||
gameB.OnClick.AddListener((UnityAction)(() =>
|
/* gameB.OnClick.AddListener((UnityAction)(() =>
|
||||||
{
|
{
|
||||||
__instance.RegularGameSettings.SetActive(true);
|
__instance.RegularGameSettings.SetActive(true);
|
||||||
__instance.RolesSettings.gameObject.SetActive(false);
|
__instance.RolesSettings.gameObject.SetActive(false);
|
||||||
@@ -82,7 +84,7 @@ public static class CustomOptionsTab
|
|||||||
|
|
||||||
__instance.GameSettingsHightlight.enabled = false;
|
__instance.GameSettingsHightlight.enabled = false;
|
||||||
__instance.RolesSettingsHightlight.enabled = true;
|
__instance.RolesSettingsHightlight.enabled = true;
|
||||||
}));
|
}));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GameObject CreateHeader(ToggleOption toggleOpt, Transform container, string title)
|
public static GameObject CreateHeader(ToggleOption toggleOpt, Transform container, string title)
|
||||||
@@ -113,11 +115,11 @@ public static class CustomOptionsTab
|
|||||||
GameObject gameTab, GameObject roleTab)
|
GameObject gameTab, GameObject roleTab)
|
||||||
{
|
{
|
||||||
var newTab = Object.Instantiate(gameTab, gameTab.transform.parent);
|
var newTab = Object.Instantiate(gameTab, gameTab.transform.parent);
|
||||||
newTab.name = "LaunchpadTab";
|
newTab.name = "Tab";
|
||||||
gameTab.transform.position += new Vector3(-1, 0, 0);
|
gameTab.transform.position += new Vector3(-1, 0, 0);
|
||||||
|
|
||||||
var inside = newTab.transform.FindChild("ColorButton");
|
var inside = newTab.transform.FindChild("ColorButton");
|
||||||
inside.name = "LaunchpadBtn";
|
inside.name = "Btn";
|
||||||
|
|
||||||
var btn = inside.GetComponentInChildren<PassiveButton>();
|
var btn = inside.GetComponentInChildren<PassiveButton>();
|
||||||
|
|
||||||
@@ -135,6 +137,12 @@ public static class CustomOptionsTab
|
|||||||
{
|
{
|
||||||
__instance.RegularGameSettings.SetActive(false);
|
__instance.RegularGameSettings.SetActive(false);
|
||||||
__instance.RolesSettings.gameObject.SetActive(false);
|
__instance.RolesSettings.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
foreach (var screen in CustomScreens)
|
||||||
|
{
|
||||||
|
screen.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
newSettings.gameObject.SetActive(true);
|
newSettings.gameObject.SetActive(true);
|
||||||
|
|
||||||
var rend = inside.transform.FindChild("Tab Background").GetComponent<SpriteRenderer>();
|
var rend = inside.transform.FindChild("Tab Background").GetComponent<SpriteRenderer>();
|
||||||
@@ -142,6 +150,11 @@ public static class CustomOptionsTab
|
|||||||
|
|
||||||
gameTab.transform.FindChild("ColorButton/Tab Background").gameObject.GetComponent<SpriteRenderer>().enabled = false;
|
gameTab.transform.FindChild("ColorButton/Tab Background").gameObject.GetComponent<SpriteRenderer>().enabled = false;
|
||||||
roleTab.transform.FindChild("Hat Button/Tab Background").gameObject.GetComponent<SpriteRenderer>().enabled = false;
|
roleTab.transform.FindChild("Hat Button/Tab Background").gameObject.GetComponent<SpriteRenderer>().enabled = false;
|
||||||
|
|
||||||
|
foreach (var tab in CustomTabs)
|
||||||
|
{
|
||||||
|
tab.transform.FindChild("Btn/Tab Background").gameObject.GetComponent<SpriteRenderer>().enabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,13 +162,13 @@ public static class CustomOptionsTab
|
|||||||
{
|
{
|
||||||
var gameSettings = __instance.RegularGameSettings;
|
var gameSettings = __instance.RegularGameSettings;
|
||||||
var newSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent);
|
var newSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent);
|
||||||
newSettings.name = "Launchpad Settings";
|
newSettings.name = "Settings";
|
||||||
newSettings.SetActive(false);
|
newSettings.SetActive(false);
|
||||||
|
|
||||||
var launchpadGroup = newSettings.transform.FindChild("GameGroup").gameObject;
|
var launchpadGroup = newSettings.transform.FindChild("GameGroup").gameObject;
|
||||||
var text = launchpadGroup.transform.FindChild("Text").gameObject.GetComponent<TextMeshPro>();
|
var text = launchpadGroup.transform.FindChild("Text").gameObject.GetComponent<TextMeshPro>();
|
||||||
text.gameObject.GetComponent<TextTranslatorTMP>().Destroy();
|
text.gameObject.GetComponent<TextTranslatorTMP>().Destroy();
|
||||||
text.text = "Launchpad Settings";
|
text.text = "Settings";
|
||||||
|
|
||||||
return newSettings;
|
return newSettings;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ public class CustomStringOption : AbstractGameOption
|
|||||||
Options = options;
|
Options = options;
|
||||||
Default = defaultValue;
|
Default = defaultValue;
|
||||||
|
|
||||||
CustomOptionsManager.CustomStringOptions.Add(this);
|
|
||||||
if (Save)
|
if (Save)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ public class CustomToggleOption : AbstractGameOption
|
|||||||
Logger<MiraAPIPlugin>.Warning(e.ToString());
|
Logger<MiraAPIPlugin>.Warning(e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CustomOptionsManager.CustomToggleOptions.Add(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(bool newValue)
|
public void SetValue(bool newValue)
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using MiraAPI.Utilities;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MiraAPI.GameOptions
|
||||||
|
{
|
||||||
|
public interface IModOptions
|
||||||
|
{
|
||||||
|
LoadableAsset<Sprite> OptionsTabIcon { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using MiraAPI.GameModes;
|
using MiraAPI.GameModes;
|
||||||
|
using MiraAPI.GameOptions.Attributes;
|
||||||
using MiraAPI.Hud;
|
using MiraAPI.Hud;
|
||||||
using MiraAPI.Roles;
|
using MiraAPI.Roles;
|
||||||
using Reactor;
|
using Reactor;
|
||||||
@@ -11,7 +12,7 @@ using System.Reflection;
|
|||||||
|
|
||||||
namespace MiraAPI;
|
namespace MiraAPI;
|
||||||
|
|
||||||
[BepInAutoPlugin("dev.xtracube.launchpad", "MiraAPI")]
|
[BepInAutoPlugin("mira.api", "MiraAPI")]
|
||||||
[BepInProcess("Among Us.exe")]
|
[BepInProcess("Among Us.exe")]
|
||||||
[BepInDependency(ReactorPlugin.Id)]
|
[BepInDependency(ReactorPlugin.Id)]
|
||||||
[ReactorModFlags(ModFlags.RequireOnAllClients)]
|
[ReactorModFlags(ModFlags.RequireOnAllClients)]
|
||||||
@@ -25,8 +26,10 @@ public partial class MiraAPIPlugin : BasePlugin
|
|||||||
Instance = this;
|
Instance = this;
|
||||||
Harmony.PatchAll();
|
Harmony.PatchAll();
|
||||||
|
|
||||||
RegisterGameModeAttribute.Register(Assembly.GetExecutingAssembly());
|
RegisterCustomRoleAttribute.Initialize();
|
||||||
RegisterCustomRoleAttribute.Register(Assembly.GetExecutingAssembly());
|
RegisterCustomOptionsAttribute.Initialize();
|
||||||
|
|
||||||
|
RegisterGameModeAttribute.Register(Assembly.GetCallingAssembly());
|
||||||
RegisterButtonAttribute.Register(Assembly.GetExecutingAssembly());
|
RegisterButtonAttribute.Register(Assembly.GetExecutingAssembly());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using InnerNet;
|
||||||
|
using MiraAPI.API.GameOptions;
|
||||||
|
using MiraAPI.Hud;
|
||||||
|
using MiraAPI.Patches.Options;
|
||||||
|
using MiraAPI.Roles;
|
||||||
|
using Reactor.Utilities.Extensions;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MiraAPI.Patches
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(HudManager))]
|
||||||
|
public static class HudManagerPatches
|
||||||
|
{
|
||||||
|
/// Custom buttons parent
|
||||||
|
private static GameObject _bottomLeft;
|
||||||
|
|
||||||
|
/// Custom role tab
|
||||||
|
private static TaskPanelBehaviour _roleTab;
|
||||||
|
|
||||||
|
/// Scrolling increment
|
||||||
|
private const float Increment = 0.3f;
|
||||||
|
|
||||||
|
/// Bounds for scrolling
|
||||||
|
private static FloatRange _bounds = new FloatRange(2.9f, 4.6f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add options scrolling (on the hud text)
|
||||||
|
/// </summary>
|
||||||
|
public static void OptionsScrollingLogic(HudManager __instance)
|
||||||
|
{
|
||||||
|
if (Input.GetKeyDown(KeyCode.Tab))
|
||||||
|
{
|
||||||
|
if (ToHudStringPatch.CurrentPage >= CustomOptionsManager.RegisteredMods.Count)
|
||||||
|
{
|
||||||
|
ToHudStringPatch.CurrentPage = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ToHudStringPatch.CurrentPage += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var numPlayers = GameData.Instance ? GameData.Instance.PlayerCount : 10;
|
||||||
|
HudManager.Instance.GameSettings.text = GameOptionsManager.Instance.CurrentGameOptions.ToHudString(numPlayers);
|
||||||
|
var pos = __instance.GameSettings.transform.localPosition;
|
||||||
|
|
||||||
|
if (!PlayerControl.LocalPlayer.CanMove)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ToHudStringPatch.CurrentPage == 0)
|
||||||
|
{
|
||||||
|
__instance.GameSettings.transform.localPosition = new Vector3(pos.x, _bounds.min, pos.z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_bounds.max = __instance.GameSettings.rectTransform.sizeDelta.y + _bounds.min;
|
||||||
|
|
||||||
|
var delta = Input.mouseScrollDelta.y switch
|
||||||
|
{
|
||||||
|
> 0f => -Increment,
|
||||||
|
< 0f => Increment,
|
||||||
|
_ => 0f
|
||||||
|
};
|
||||||
|
|
||||||
|
pos = new Vector3(pos.x, Mathf.Clamp(pos.y + delta, _bounds.min, _bounds.max), pos.z);
|
||||||
|
|
||||||
|
__instance.GameSettings.transform.localPosition = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix, HarmonyPatch("Update")]
|
||||||
|
public static void UpdatePostfix(HudManager __instance)
|
||||||
|
{
|
||||||
|
var local = PlayerControl.LocalPlayer;
|
||||||
|
if (LobbyBehaviour.Instance)
|
||||||
|
{
|
||||||
|
OptionsScrollingLogic(__instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started && !ShipStatus.Instance)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//CustomGameModeManager.ActiveMode.HudUpdate(__instance);
|
||||||
|
|
||||||
|
if (local.Data.Role is ICustomRole customRole)
|
||||||
|
{
|
||||||
|
customRole.HudUpdate(__instance);
|
||||||
|
|
||||||
|
if (customRole.SetTabText() != null)
|
||||||
|
{
|
||||||
|
if (_roleTab == null)
|
||||||
|
{
|
||||||
|
_roleTab = CustomRoleManager.CreateRoleTab(customRole);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CustomRoleManager.UpdateRoleTab(_roleTab, customRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (customRole.SetTabText() == null && _roleTab)
|
||||||
|
{
|
||||||
|
_roleTab.gameObject.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_roleTab)
|
||||||
|
{
|
||||||
|
_roleTab.gameObject.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* /// <summary>
|
||||||
|
/// Trigger hudstart on current custom gamemode
|
||||||
|
/// </summary>
|
||||||
|
[HarmonyPostfix, HarmonyPatch("OnGameStart")]
|
||||||
|
public static void GameStartPatch(HudManager __instance)
|
||||||
|
{
|
||||||
|
CustomGameModeManager.ActiveMode.HudStart(__instance);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create custom buttons parent
|
||||||
|
/// </summary>
|
||||||
|
[HarmonyPostfix, HarmonyPatch("Start")]
|
||||||
|
public static void StartPostfix(HudManager __instance)
|
||||||
|
{
|
||||||
|
if (!_bottomLeft)
|
||||||
|
{
|
||||||
|
var buttons = __instance.transform.Find("Buttons");
|
||||||
|
_bottomLeft = UnityEngine.Object.Instantiate(buttons.Find("BottomRight").gameObject, buttons);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var t in _bottomLeft.GetComponentsInChildren<ActionButton>(true))
|
||||||
|
{
|
||||||
|
t.gameObject.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
var gridArrange = _bottomLeft.GetComponent<GridArrange>();
|
||||||
|
var aspectPosition = _bottomLeft.GetComponent<AspectPosition>();
|
||||||
|
|
||||||
|
_bottomLeft.name = "BottomLeft";
|
||||||
|
gridArrange.Alignment = GridArrange.StartAlign.Right;
|
||||||
|
aspectPosition.Alignment = AspectPosition.EdgeAlignments.LeftBottom;
|
||||||
|
|
||||||
|
foreach (var button in CustomButtonManager.CustomButtons)
|
||||||
|
{
|
||||||
|
button.CreateButton(_bottomLeft.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
gridArrange.Start();
|
||||||
|
gridArrange.ArrangeChilds();
|
||||||
|
|
||||||
|
aspectPosition.AdjustPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make sure all launchpad hud elements are inactive/active when appropriate
|
||||||
|
/// </summary>
|
||||||
|
[HarmonyPostfix, HarmonyPatch("SetHudActive", typeof(PlayerControl), typeof(RoleBehaviour), typeof(bool))]
|
||||||
|
public static void SetHudActivePostfix(HudManager __instance, [HarmonyArgument(0)] PlayerControl player, [HarmonyArgument(1)] RoleBehaviour roleBehaviour, [HarmonyArgument(2)] bool isActive)
|
||||||
|
{
|
||||||
|
if (player.Data == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_roleTab)
|
||||||
|
{
|
||||||
|
_roleTab.gameObject.SetActive(isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var button in CustomButtonManager.CustomButtons)
|
||||||
|
button.SetActive(isActive, roleBehaviour);
|
||||||
|
|
||||||
|
if (roleBehaviour is ICustomRole role)
|
||||||
|
{
|
||||||
|
__instance.ImpostorVentButton.gameObject.SetActive(isActive && role.CanUseVent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,11 +18,13 @@ public static class GameSettingsMenuPatches
|
|||||||
[HarmonyPrefix, HarmonyPatch("Start")]
|
[HarmonyPrefix, HarmonyPatch("Start")]
|
||||||
public static void StartPrefix(GameSettingMenu __instance)
|
public static void StartPrefix(GameSettingMenu __instance)
|
||||||
{
|
{
|
||||||
if (CustomOptionsTab.CustomTab)
|
if (CustomOptionsTab.CustomTabs != null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomOptionsTab.CustomTabs = new();
|
||||||
|
|
||||||
__instance.Tabs.transform.position += new Vector3(0.5f, 0, 0);
|
__instance.Tabs.transform.position += new Vector3(0.5f, 0, 0);
|
||||||
_gameBtn = __instance.transform.FindChild("Header/Tabs/GameTab").gameObject;
|
_gameBtn = __instance.transform.FindChild("Header/Tabs/GameTab").gameObject;
|
||||||
_roleBtn = __instance.transform.FindChild("Header/Tabs/RoleTab").gameObject;
|
_roleBtn = __instance.transform.FindChild("Header/Tabs/RoleTab").gameObject;
|
||||||
@@ -81,7 +83,7 @@ public static class GameSettingsMenuPatches
|
|||||||
__instance.RegularGameSettings.SetActive(false);
|
__instance.RegularGameSettings.SetActive(false);
|
||||||
__instance.RolesSettings.gameObject.SetActive(false);
|
__instance.RolesSettings.gameObject.SetActive(false);
|
||||||
|
|
||||||
CustomOptionsTab.CustomScreen.gameObject.SetActive(true);
|
//CustomOptionsTab.CustomScreen.gameObject.SetActive(true);
|
||||||
CustomOptionsTab.Rend.enabled = true;
|
CustomOptionsTab.Rend.enabled = true;
|
||||||
|
|
||||||
__instance.GameSettingsHightlight.enabled = false;
|
__instance.GameSettingsHightlight.enabled = false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using AmongUs.GameOptions;
|
using AmongUs.GameOptions;
|
||||||
|
using BepInEx;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using MiraAPI.API.GameOptions;
|
using MiraAPI.API.GameOptions;
|
||||||
using MiraAPI.GameModes;
|
|
||||||
using MiraAPI.Roles;
|
using MiraAPI.Roles;
|
||||||
using MiraAPI.Utilities;
|
using MiraAPI.Utilities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -13,11 +13,7 @@ namespace MiraAPI.Patches.Options;
|
|||||||
[HarmonyPatch(typeof(IGameOptionsExtensions), "ToHudString")]
|
[HarmonyPatch(typeof(IGameOptionsExtensions), "ToHudString")]
|
||||||
public static class ToHudStringPatch
|
public static class ToHudStringPatch
|
||||||
{
|
{
|
||||||
/// <summary>
|
public static int CurrentPage = 0;
|
||||||
/// Show custom Launchpad options or vanilla game options
|
|
||||||
/// </summary>
|
|
||||||
public static bool ShowCustom = false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generic method to add options
|
/// Generic method to add options
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -82,28 +78,32 @@ public static class ToHudStringPatch
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var role in CustomRoleManager.CustomRoles.Values)
|
foreach (var pair in CustomRoleManager.CustomRoles)
|
||||||
{
|
{
|
||||||
var customRole = role as ICustomRole;
|
var customRole = pair.Value as ICustomRole;
|
||||||
if (customRole.IsGhostRole)
|
if (customRole.IsGhostRole)
|
||||||
{
|
{
|
||||||
role.Role = (RoleTypes)customRole.RoleId;
|
pair.Value.Role = (RoleTypes)pair.Key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShowCustom || !CustomGameModeManager.ActiveMode.CanAccessSettingsTab())
|
if (CurrentPage != 0)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder("<size=180%><b>Launchpad Options:</b></size>\n<size=130%>");
|
PluginInfo currentPlugin = CustomOptionsManager.RegisteredMods[CurrentPage - 1];
|
||||||
var groupsWithRoles = CustomOptionsManager.CustomGroups.Where(group => group.AdvancedRole != null);
|
if (currentPlugin == null)
|
||||||
var groupsWithoutRoles = CustomOptionsManager.CustomGroups.Where(group => group.AdvancedRole == null);
|
{
|
||||||
|
CurrentPage = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var suffix = CustomGameModeManager.ActiveMode.CanAccessSettingsTab() ? "\nPress <b>Tab</b> to view Normal Options" :
|
var sb = new StringBuilder($"<size=180%><b>{currentPlugin.Metadata.Name} Options:</b></size>\n<size=130%>");
|
||||||
$"\n<b>You can not access Normal Options on {CustomGameModeManager.ActiveMode.Name} mode.</b>";
|
var groupsWithRoles = CustomOptionsManager.CustomGroups.Where(group => group.AdvancedRole != null && group.ParentMod == currentPlugin);
|
||||||
|
var groupsWithoutRoles = CustomOptionsManager.CustomGroups.Where(group => group.AdvancedRole == null && group.ParentMod == currentPlugin);
|
||||||
|
|
||||||
AddOptions(sb,
|
AddOptions(sb,
|
||||||
CustomOptionsManager.CustomNumberOptions.Where(option => option.Group == null && !option.Hidden()),
|
CustomOptionsManager.CustomNumberOptions.Where(option => option.Group == null && option.ParentMod == currentPlugin && !option.Hidden()),
|
||||||
CustomOptionsManager.CustomStringOptions.Where(option => option.Group == null && !option.Hidden()),
|
CustomOptionsManager.CustomStringOptions.Where(option => option.Group == null && option.ParentMod == currentPlugin && !option.Hidden()),
|
||||||
CustomOptionsManager.CustomToggleOptions.Where(option => option.Group == null && !option.Hidden())
|
CustomOptionsManager.CustomToggleOptions.Where(option => option.Group == null && option.ParentMod == currentPlugin && !option.Hidden())
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (var group in groupsWithoutRoles)
|
foreach (var group in groupsWithoutRoles)
|
||||||
@@ -117,14 +117,8 @@ public static class ToHudStringPatch
|
|||||||
AddOptions(sb, group.CustomNumberOptions, group.CustomStringOptions, group.CustomToggleOptions);
|
AddOptions(sb, group.CustomNumberOptions, group.CustomStringOptions, group.CustomToggleOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameManager.Instance.IsHideAndSeek())
|
|
||||||
{
|
|
||||||
__result = sb + suffix;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var customOptionGroups = groupsWithRoles as CustomOptionGroup[] ?? groupsWithRoles.ToArray();
|
var customOptionGroups = groupsWithRoles as CustomOptionGroup[] ?? groupsWithRoles.ToArray();
|
||||||
if (customOptionGroups.Any() && CustomGameModeManager.ActiveMode.CanAccessRolesTab())
|
if (customOptionGroups.Any())
|
||||||
{
|
{
|
||||||
sb.AppendLine("\n<size=160%><b>Roles</b></size>");
|
sb.AppendLine("\n<size=160%><b>Roles</b></size>");
|
||||||
|
|
||||||
@@ -141,10 +135,13 @@ public static class ToHudStringPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__result = sb + suffix;
|
__result = sb.ToString();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__result = "<size=160%><b>Normal Options:</b></size>\n<size=130%>" + __result + "\nPress <b>Tab</b> to view Launchpad Options</size>";
|
if (CurrentPage == 0)
|
||||||
|
{
|
||||||
|
__result = "<size=160%><b>Normal Options:</b></size>\n<size=130%>" + __result;
|
||||||
|
}
|
||||||
|
__result += $"\nUse <b>TAB</b> to switch pages (Page {CurrentPage}/{CustomOptionsManager.RegisteredMods.Count})</size>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ public static class RolesSettingsMenuPatches
|
|||||||
|
|
||||||
if (AmongUsClient.Instance.AmHost)
|
if (AmongUsClient.Instance.AmHost)
|
||||||
{
|
{
|
||||||
Rpc<SyncRoleOptionsRpc>.Instance.Send(new SyncRoleOptionsRpc.Data(role.RoleId, numEntry.Value, chanceEntry.Value));
|
Rpc<SyncRoleOptionsRpc>.Instance.Send(new SyncRoleOptionsRpc.Data((ushort)roleSetting.Role.Role, numEntry.Value, chanceEntry.Value));
|
||||||
}
|
}
|
||||||
GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.CurrentGameOptions;
|
GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.CurrentGameOptions;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace MiraAPI.Patches.Roles;
|
|||||||
public static class TaskAdderPatch
|
public static class TaskAdderPatch
|
||||||
{
|
{
|
||||||
public static TaskFolder RolesFolder;
|
public static TaskFolder RolesFolder;
|
||||||
|
public static System.Collections.Generic.Dictionary<string, string> ModsFolders = new System.Collections.Generic.Dictionary<string, string>();
|
||||||
|
|
||||||
[HarmonyPostfix, HarmonyPatch(typeof(TaskAdderGame), nameof(TaskAdderGame.Begin))]
|
[HarmonyPostfix, HarmonyPatch(typeof(TaskAdderGame), nameof(TaskAdderGame.Begin))]
|
||||||
public static void AddRolesFolder(TaskAdderGame __instance)
|
public static void AddRolesFolder(TaskAdderGame __instance)
|
||||||
@@ -21,7 +22,22 @@ public static class TaskAdderPatch
|
|||||||
RolesFolder.gameObject.SetActive(false);
|
RolesFolder.gameObject.SetActive(false);
|
||||||
RolesFolder.FolderName = "Roles";
|
RolesFolder.FolderName = "Roles";
|
||||||
RolesFolder.name = "RolesFolder";
|
RolesFolder.name = "RolesFolder";
|
||||||
|
foreach (var pair in CustomRoleManager.ModRoles)
|
||||||
|
{
|
||||||
|
var newFolder = Object.Instantiate(__instance.RootFolderPrefab, __instance.transform);
|
||||||
|
newFolder.FolderName = pair.Key.Metadata.Name;
|
||||||
|
newFolder.name = pair.Key.Metadata.Name;
|
||||||
|
newFolder.gameObject.SetActive(false);
|
||||||
|
RolesFolder.SubFolders.Add(newFolder);
|
||||||
|
|
||||||
|
if (!ModsFolders.ContainsKey(pair.Key.Metadata.Name))
|
||||||
|
{
|
||||||
|
ModsFolders.Add(pair.Key.Metadata.Name, pair.Key.Metadata.GUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
__instance.Root.SubFolders.Add(RolesFolder);
|
__instance.Root.SubFolders.Add(RolesFolder);
|
||||||
|
|
||||||
__instance.GoToRoot();
|
__instance.GoToRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,11 +150,11 @@ public static class TaskAdderPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taskFolder.FolderName == "Roles") // idk why only this works???
|
if (ModsFolders.TryGetValue(taskFolder.FolderName, out string guid))
|
||||||
{
|
{
|
||||||
for (var m = 0; m < DestroyableSingleton<RoleManager>.Instance.AllRoles.Length; m++)
|
for (var m = 0; m < CustomRoleManager.GetRolesRegistered(guid).Count; m++)
|
||||||
{
|
{
|
||||||
var roleBehaviour = DestroyableSingleton<RoleManager>.Instance.AllRoles[m];
|
var roleBehaviour = CustomRoleManager.GetRolesRegistered(guid)[m];
|
||||||
if (roleBehaviour.Role != RoleTypes.ImpostorGhost && roleBehaviour.Role != RoleTypes.CrewmateGhost && !roleBehaviour.IsDead)
|
if (roleBehaviour.Role != RoleTypes.ImpostorGhost && roleBehaviour.Role != RoleTypes.CrewmateGhost && !roleBehaviour.IsDead)
|
||||||
{
|
{
|
||||||
var taskAddButton2 = Object.Instantiate(__instance.RoleButton);
|
var taskAddButton2 = Object.Instantiate(__instance.RoleButton);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using AmongUs.GameOptions;
|
using AmongUs.GameOptions;
|
||||||
|
using BepInEx;
|
||||||
|
using BepInEx.Unity.IL2CPP;
|
||||||
using Il2CppInterop.Runtime;
|
using Il2CppInterop.Runtime;
|
||||||
using MiraAPI.Networking.Options;
|
using MiraAPI.Networking.Options;
|
||||||
using Reactor.Localization.Utilities;
|
using Reactor.Localization.Utilities;
|
||||||
@@ -17,14 +19,21 @@ namespace MiraAPI.Roles;
|
|||||||
public static class CustomRoleManager
|
public static class CustomRoleManager
|
||||||
{
|
{
|
||||||
public static readonly Dictionary<ushort, RoleBehaviour> CustomRoles = [];
|
public static readonly Dictionary<ushort, RoleBehaviour> CustomRoles = [];
|
||||||
|
public static readonly Dictionary<PluginInfo, List<RoleBehaviour>> ModRoles = [];
|
||||||
|
|
||||||
public static void RegisterInRoleManager()
|
public static void RegisterInRoleManager()
|
||||||
{
|
{
|
||||||
RoleManager.Instance.AllRoles = RoleManager.Instance.AllRoles.Concat(CustomRoles.Values).ToArray();
|
RoleManager.Instance.AllRoles = RoleManager.Instance.AllRoles.Concat(CustomRoles.Values).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void RegisterRole(Type roleType)
|
internal static void RegisterRole(Type roleType, ushort roleId, string modId)
|
||||||
{
|
{
|
||||||
|
if (!IL2CPPChainloader.Instance.Plugins.TryGetValue(modId, out PluginInfo info))
|
||||||
|
{
|
||||||
|
Debug.LogError($"{modId} is not a valid mod!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(typeof(RoleBehaviour).IsAssignableFrom(roleType) && typeof(ICustomRole).IsAssignableFrom(roleType)))
|
if (!(typeof(RoleBehaviour).IsAssignableFrom(roleType) && typeof(ICustomRole).IsAssignableFrom(roleType)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -42,7 +51,13 @@ public static class CustomRoleManager
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
roleBehaviour.Role = (RoleTypes)customRole.RoleId;
|
if (CustomRoles.ContainsKey(roleId))
|
||||||
|
{
|
||||||
|
Debug.LogError($"Role ID conflict for {customRole.RoleName}. Use a different ID.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
roleBehaviour.Role = (RoleTypes)roleId;
|
||||||
roleBehaviour.TeamType = customRole.Team;
|
roleBehaviour.TeamType = customRole.Team;
|
||||||
roleBehaviour.NameColor = customRole.RoleColor;
|
roleBehaviour.NameColor = customRole.RoleColor;
|
||||||
roleBehaviour.StringName = CustomStringName.CreateAndRegister(customRole.RoleName);
|
roleBehaviour.StringName = CustomStringName.CreateAndRegister(customRole.RoleName);
|
||||||
@@ -61,7 +76,16 @@ public static class CustomRoleManager
|
|||||||
RoleManager.GhostRoles.Add(roleBehaviour.Role);
|
RoleManager.GhostRoles.Add(roleBehaviour.Role);
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomRoles.Add(customRole.RoleId, roleBehaviour);
|
if (ModRoles.TryGetValue(info, out List<RoleBehaviour> roles))
|
||||||
|
{
|
||||||
|
roles.Add(roleBehaviour);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ModRoles.TryAdd(info, new List<RoleBehaviour>() { roleBehaviour });
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomRoles.Add(roleId, roleBehaviour);
|
||||||
|
|
||||||
if (customRole.HideSettings)
|
if (customRole.HideSettings)
|
||||||
{
|
{
|
||||||
@@ -74,6 +98,19 @@ public static class CustomRoleManager
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<RoleBehaviour> GetRolesRegistered(string modId)
|
||||||
|
{
|
||||||
|
PluginInfo info = ModRoles.Keys.First(key => key.Metadata.GUID == modId);
|
||||||
|
if (ModRoles.TryGetValue(info, out List<RoleBehaviour> roles))
|
||||||
|
{
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"{modId} has no roles registered.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
public static bool GetCustomRoleBehaviour(RoleTypes roleType, out ICustomRole result)
|
public static bool GetCustomRoleBehaviour(RoleTypes roleType, out ICustomRole result)
|
||||||
{
|
{
|
||||||
CustomRoles.TryGetValue((ushort)roleType, out var temp);
|
CustomRoles.TryGetValue((ushort)roleType, out var temp);
|
||||||
@@ -123,33 +160,35 @@ public static class CustomRoleManager
|
|||||||
|
|
||||||
public static void SyncRoleSettings()
|
public static void SyncRoleSettings()
|
||||||
{
|
{
|
||||||
foreach (var role in CustomRoles.Values.Select(x => (ICustomRole)x))
|
foreach (var role in CustomRoles.Values)
|
||||||
{
|
{
|
||||||
if (role.HideSettings)
|
ICustomRole customRole = role as ICustomRole;
|
||||||
|
if (customRole.HideSettings)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(role.NumConfigDefinition, out var numEntry);
|
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(customRole.NumConfigDefinition, out var numEntry);
|
||||||
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(role.ChanceConfigDefinition, out var chanceEntry);
|
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(customRole.ChanceConfigDefinition, out var chanceEntry);
|
||||||
|
|
||||||
Rpc<SyncRoleOptionsRpc>.Instance.Send(new SyncRoleOptionsRpc.Data(role.RoleId, numEntry.Value, chanceEntry.Value));
|
Rpc<SyncRoleOptionsRpc>.Instance.Send(new SyncRoleOptionsRpc.Data((ushort)role.Role, numEntry.Value, chanceEntry.Value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SyncRoleSettings(int targetId)
|
public static void SyncRoleSettings(int targetId)
|
||||||
{
|
{
|
||||||
foreach (var role in CustomRoles.Values.Select(x => (ICustomRole)x))
|
foreach (var role in CustomRoles.Values)
|
||||||
{
|
{
|
||||||
if (role.HideSettings)
|
ICustomRole customRole = role as ICustomRole;
|
||||||
|
if (customRole.HideSettings)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(role.NumConfigDefinition, out var numEntry);
|
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(customRole.NumConfigDefinition, out var numEntry);
|
||||||
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(role.ChanceConfigDefinition, out var chanceEntry);
|
PluginSingleton<MiraAPIPlugin>.Instance.Config.TryGetEntry<int>(customRole.ChanceConfigDefinition, out var chanceEntry);
|
||||||
|
|
||||||
Rpc<SyncRoleOptionsRpc>.Instance.SendTo(targetId, new SyncRoleOptionsRpc.Data(role.RoleId, numEntry.Value, chanceEntry.Value));
|
Rpc<SyncRoleOptionsRpc>.Instance.SendTo(targetId, new SyncRoleOptionsRpc.Data((ushort)role.Role, numEntry.Value, chanceEntry.Value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,8 +11,6 @@ public interface ICustomRole
|
|||||||
{
|
{
|
||||||
string RoleName { get; }
|
string RoleName { get; }
|
||||||
|
|
||||||
ushort RoleId { get; }
|
|
||||||
|
|
||||||
string RoleDescription { get; }
|
string RoleDescription { get; }
|
||||||
|
|
||||||
string RoleLongDescription { get; }
|
string RoleLongDescription { get; }
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using BepInEx.Unity.IL2CPP;
|
||||||
|
using MiraAPI.Utilities;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
@@ -8,6 +10,24 @@ namespace MiraAPI.Roles;
|
|||||||
public class RegisterCustomRoleAttribute : Attribute
|
public class RegisterCustomRoleAttribute : Attribute
|
||||||
{
|
{
|
||||||
private static readonly HashSet<Assembly> RegisteredAssemblies = [];
|
private static readonly HashSet<Assembly> RegisteredAssemblies = [];
|
||||||
|
public ushort RoleId { get; }
|
||||||
|
public string ModId { get; }
|
||||||
|
|
||||||
|
public RegisterCustomRoleAttribute(string modId)
|
||||||
|
{
|
||||||
|
ModId = modId;
|
||||||
|
RoleId = (ushort)(20 + CustomRoleManager.CustomRoles.Count);
|
||||||
|
}
|
||||||
|
public RegisterCustomRoleAttribute(string modId, ushort roleId)
|
||||||
|
{
|
||||||
|
ModId = modId;
|
||||||
|
RoleId = roleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
IL2CPPChainloader.Instance.PluginLoad += (_, assembly, plugin) => Register(assembly);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Register(Assembly assembly)
|
public static void Register(Assembly assembly)
|
||||||
{
|
{
|
||||||
@@ -18,7 +38,8 @@ public class RegisterCustomRoleAttribute : Attribute
|
|||||||
var attribute = type.GetCustomAttribute<RegisterCustomRoleAttribute>();
|
var attribute = type.GetCustomAttribute<RegisterCustomRoleAttribute>();
|
||||||
if (attribute != null)
|
if (attribute != null)
|
||||||
{
|
{
|
||||||
CustomRoleManager.RegisterRole(type);
|
Helpers.RegisterType(type);
|
||||||
|
CustomRoleManager.RegisterRole(type, attribute.RoleId, attribute.ModId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using MiraAPI.Roles;
|
using HarmonyLib;
|
||||||
|
using Il2CppInterop.Runtime.Injection;
|
||||||
|
using MiraAPI.Roles;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -14,6 +17,24 @@ namespace MiraAPI.Utilities
|
|||||||
return ShipStatus.Instance.AllRooms.ToList().Find(room => room.roomArea.OverlapPoint(pos));
|
return ShipStatus.Instance.AllRooms.ToList().Find(room => room.roomArea.OverlapPoint(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RegisterType(Type type)
|
||||||
|
{
|
||||||
|
if (ClassInjector.IsTypeRegisteredInIl2Cpp(type))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ClassInjector.RegisterTypeInIl2Cpp(type);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Failed to register {type.FullDescription()}: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static string GetSuffix(NumberSuffixes suffix)
|
public static string GetSuffix(NumberSuffixes suffix)
|
||||||
{
|
{
|
||||||
return suffix switch
|
return suffix switch
|
||||||
|
|||||||
Reference in new issue
Block a user