diff --git a/MiraAPI.Example/Options/ExampleOptions.cs b/MiraAPI.Example/Options/ExampleOptions.cs index 480b357..13a7dd7 100644 --- a/MiraAPI.Example/Options/ExampleOptions.cs +++ b/MiraAPI.Example/Options/ExampleOptions.cs @@ -22,13 +22,13 @@ public class ExampleOptions : AbstractOptionGroup [ModdedStringOption("String Opt", ["Hello", "Hey", "Bye"])] public int StringOpt { get; set; } = 2; - [ModdedEnumOption("Enum Opt", typeof(TestEnum))] - public TestEnum EnumOpt { get; set; } = TestEnum.Mira; + [ModdedEnumOption("Best API", typeof(BestApiEnum), ["Mira API", "Mitochondria", "Reactor"])] + public BestApiEnum EnumOpt { get; set; } = BestApiEnum.MiraAPI; } -public enum TestEnum +public enum BestApiEnum { - Welcome, - To, - Mira + MiraAPI, + Mitochondria, + Reactor } \ No newline at end of file diff --git a/MiraAPI.Example/Roles/FreezerRole.cs b/MiraAPI.Example/Roles/FreezerRole.cs index 7415dd6..e649b1a 100644 --- a/MiraAPI.Example/Roles/FreezerRole.cs +++ b/MiraAPI.Example/Roles/FreezerRole.cs @@ -13,5 +13,5 @@ public class FreezerRole : ImpostorRole, ICustomRole public Color RoleColor => Palette.Blue; public ModdedRoleTeams Team => ModdedRoleTeams.Impostor; public LoadableAsset OptionsScreenshot => ExampleAssets.Banner; - + public int MaxPlayers => 2; } \ No newline at end of file diff --git a/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs b/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs index 8225c7e..cc861dd 100644 --- a/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs +++ b/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs @@ -4,12 +4,12 @@ using System.Reflection; namespace MiraAPI.GameOptions.Attributes; -public class ModdedEnumOptionAttribute(string title, Type enumType, Type roleType = null) +public class ModdedEnumOptionAttribute(string title, Type enumType, string[] values = null, Type roleType = null) : ModdedOptionAttribute(title, roleType) { internal override IModdedOption CreateOption(object value, PropertyInfo property) { - var opt = new ModdedEnumOption(Title, (int)value, enumType, RoleType); + var opt = new ModdedEnumOption(Title, (int)value, enumType, values, RoleType); return opt; } diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs index 1e43a2b..0be085f 100644 --- a/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs +++ b/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs @@ -1,7 +1,7 @@ -using Reactor.Localization.Utilities; +using MiraAPI.Networking; +using Reactor.Localization.Utilities; using System; using System.Linq; -using MiraAPI.Networking; using UnityEngine; using Object = UnityEngine.Object; @@ -11,15 +11,18 @@ public class ModdedEnumOption : ModdedOption { public string[] Values { get; } - public ModdedEnumOption(string title, int defaultValue, Type enumType, Type roleType=null) : base(title, defaultValue, roleType) + public ModdedEnumOption(string title, int defaultValue, Type enumType, string[] values = null, Type roleType = null) : base(title, defaultValue, roleType) { - Values = Enum.GetNames(enumType); + Values = values is null ? Enum.GetNames(enumType) : values; Data = ScriptableObject.CreateInstance(); var data = (StringGameSetting)Data; - + data.Title = StringName; data.Type = global::OptionTypes.String; - data.Values = Values.Select(CustomStringName.CreateAndRegister).ToArray(); + data.Values = values is null ? + Enum.GetNames(enumType).Select(CustomStringName.CreateAndRegister).ToArray() + : values.Select(CustomStringName.CreateAndRegister).ToArray(); + data.Index = Value; } @@ -29,7 +32,7 @@ public class ModdedEnumOption : ModdedOption stringOption.SetUpFromData(Data, 20); stringOption.OnValueChanged = (Il2CppSystem.Action)ValueChanged; - + // SetUpFromData method doesnt work correctly so we must set the values manually stringOption.Title = StringName; stringOption.Values = ((StringGameSetting)Data).Values; diff --git a/MiraAPI/Hud/CustomActionButton.cs b/MiraAPI/Hud/CustomActionButton.cs index c24f5ea..e571134 100644 --- a/MiraAPI/Hud/CustomActionButton.cs +++ b/MiraAPI/Hud/CustomActionButton.cs @@ -1,5 +1,4 @@ #nullable enable -using MiraAPI.Utilities; using MiraAPI.Utilities.Assets; using UnityEngine; using UnityEngine.Events; @@ -55,18 +54,18 @@ public abstract class CustomActionButton /// /// Returns true if the effect is currently active. /// - protected bool EffectActive; + public bool EffectActive { get; protected set; } + + /// + /// Returns the amount of uses left. + /// + public int UsesLeft { get; set; } /// /// A timer variable to measure cooldowns and effects. /// protected float Timer; - /// - /// Returns the amount of uses left. - /// - protected int UsesLeft; - /// /// The button object in game. This is created by Mira API automatically. /// @@ -135,6 +134,24 @@ public abstract class CustomActionButton Button?.OverrideText(name); } + /// + /// Increase the amount of uses this button has left. + /// + /// The amount you want to increase by. Default: 1 + public void IncreaseUses(int amount = 1) + { + UsesLeft += amount; + } + + /// + /// Decrease the amount of uses this button has left. + /// + /// The amount you want to decrease by. Default: 1 + public void DecreaseUses(int amount = 1) + { + UsesLeft -= amount; + } + /// /// A utility function that runs with the local PlayerControl's FixedUpdate if the button is enabled. /// diff --git a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs index b65cc2b..e355438 100644 --- a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs +++ b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using Il2CppInterop.Runtime.InteropTypes.Arrays; using MiraAPI.Networking; using MiraAPI.Roles; using MiraAPI.Utilities; @@ -8,7 +9,6 @@ using Reactor.Utilities; using Reactor.Utilities.Extensions; using System; using System.Linq; -using Il2CppInterop.Runtime.InteropTypes.Arrays; using TMPro; using UnityEngine; using UnityEngine.Events; @@ -224,7 +224,7 @@ public static class RoleSettingMenuPatches __instance.roleScreenshot.drawMode = SpriteDrawMode.Sliced; __instance.roleHeaderSprite.color = customRole.RoleColor; __instance.roleHeaderText.color = customRole.RoleColor.GetAlternateColor(); - + var bg = __instance.AdvancedRolesSettings.transform.Find("Background"); bg.localPosition = new Vector3(1.4041f, -7.08f, 0); bg.GetComponent().size = new Vector2(89.4628f, 100); @@ -237,7 +237,7 @@ public static class RoleSettingMenuPatches { continue; } - + optionBehaviour.OnValueChanged = new Action(__instance.ValueChanged); if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost) { @@ -263,7 +263,7 @@ public static class RoleSettingMenuPatches roleOptionSetting.titleText.transform.localPosition = new Vector3(-0.5376f, -0.2923f, 0f); roleOptionSetting.titleText.color = customRole.RoleColor.GetAlternateColor(); roleOptionSetting.titleText.horizontalAlignment = HorizontalAlignmentOptions.Left; - + if (GameSettingMenuPatches.SelectedMod is null || GameSettingMenuPatches.SelectedMod.Options.Any(x => x.AdvancedRole != null && x.AdvancedRole.IsInstanceOfType(role))) { diff --git a/MiraAPI/Roles/CustomRoleManager.cs b/MiraAPI/Roles/CustomRoleManager.cs index f124a30..798c662 100644 --- a/MiraAPI/Roles/CustomRoleManager.cs +++ b/MiraAPI/Roles/CustomRoleManager.cs @@ -1,7 +1,9 @@ using AmongUs.GameOptions; using Il2CppInterop.Runtime; +using Il2CppInterop.Runtime.Injection; using MiraAPI.Networking; using MiraAPI.PluginLoading; +using MiraAPI.Utilities; using Reactor.Localization.Utilities; using Reactor.Networking.Rpc; using Reactor.Utilities; @@ -9,8 +11,6 @@ using Reactor.Utilities.Extensions; using System; using System.Collections.Generic; using System.Linq; -using Il2CppInterop.Runtime.Injection; -using MiraAPI.Utilities; using TMPro; using UnityEngine; using Object = UnityEngine.Object; @@ -20,11 +20,11 @@ namespace MiraAPI.Roles; public static class CustomRoleManager { public static readonly Dictionary CustomRoles = new(); - + public static readonly Dictionary RoleIds = new(); - + private static ushort _roleId = 100; - + private static ushort GetNextRoleId() { return _roleId++; @@ -37,8 +37,8 @@ public static class CustomRoleManager public static void RegisterRoleTypes(List roles, MiraPluginInfo pluginInfo) { - roles.ForEach(x=>RoleIds.Add(x, GetNextRoleId())); - + roles.ForEach(x => RoleIds.Add(x, GetNextRoleId())); + foreach (var roleType in roles) { ClassInjector.RegisterTypeInIl2Cpp(roleType); @@ -68,7 +68,7 @@ public static class CustomRoleManager roleBehaviour.gameObject.Destroy(); return null; } - + var roleId = RoleIds[roleType]; roleBehaviour.Role = (RoleTypes)roleId; @@ -83,7 +83,7 @@ public static class CustomRoleManager roleBehaviour.TasksCountTowardProgress = customRole.TasksCount; roleBehaviour.CanVent = customRole.CanUseVent; roleBehaviour.DefaultGhostRole = customRole.GhostRole; - roleBehaviour.MaxCount = 15; + roleBehaviour.MaxCount = customRole.MaxPlayers; roleBehaviour.RoleScreenshot = customRole.OptionsScreenshot.LoadAsset(); if (customRole.IsGhostRole) @@ -101,7 +101,7 @@ public static class CustomRoleManager var config = parentMod.PluginConfig; config.Bind(customRole.NumConfigDefinition, 1); config.Bind(customRole.ChanceConfigDefinition, 100); - + return roleBehaviour; } @@ -156,8 +156,8 @@ public static class CustomRoleManager panel.SetTaskText(role.SetTabText().ToString()); } - - internal static void SyncAllRoleSettings(int targetId=-1) + + internal static void SyncAllRoleSettings(int targetId = -1) { var data = CustomRoles.Values .Where(x => x is ICustomRole { HideSettings: false }) @@ -181,7 +181,7 @@ public static class CustomRoleManager oldConfigSetting.Add(plugin, plugin.PluginConfig.SaveOnConfigSet); plugin.PluginConfig.SaveOnConfigSet = false; } - + foreach (var netData in data) { if (!CustomRoles.TryGetValue((ushort)netData.Id, out var role)) @@ -197,7 +197,7 @@ public static class CustomRoleManager var num = BitConverter.ToInt32(netData.Data, 0); var chance = BitConverter.ToInt32(netData.Data, 4); - + DestroyableSingleton.Instance.Notifier.AddRoleSettingsChangeMessage(role.StringName, num, chance, role.TeamType, false); try @@ -215,13 +215,13 @@ public static class CustomRoleManager Logger.Error(e); } } - + foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins.Values) { plugin.PluginConfig.Save(); plugin.PluginConfig.SaveOnConfigSet = oldConfigSetting[plugin]; } - + if (LobbyInfoPane.Instance) { LobbyInfoPane.Instance.RefreshPane(); diff --git a/MiraAPI/Roles/ICustomRole.cs b/MiraAPI/Roles/ICustomRole.cs index f6c74e3..f8c3e8d 100644 --- a/MiraAPI/Roles/ICustomRole.cs +++ b/MiraAPI/Roles/ICustomRole.cs @@ -3,11 +3,11 @@ using BepInEx.Configuration; using HarmonyLib; using MiraAPI.Modifiers; using MiraAPI.Networking; +using MiraAPI.PluginLoading; using MiraAPI.Utilities; using MiraAPI.Utilities.Assets; using System; using System.Text; -using MiraAPI.PluginLoading; using UnityEngine; namespace MiraAPI.Roles; @@ -24,6 +24,8 @@ public interface ICustomRole ModdedRoleTeams Team { get; } + int MaxPlayers => 15; + LoadableAsset OptionsScreenshot => MiraAssets.Empty; LoadableAsset Icon => MiraAssets.Empty; @@ -53,7 +55,7 @@ public interface ICustomRole RoleTypes GhostRole => Team == ModdedRoleTeams.Crewmate ? RoleTypes.CrewmateGhost : RoleTypes.ImpostorGhost; MiraPluginInfo ParentMod => CustomRoleManager.FindParentMod(this); - + /// /// Runs on the PlayerControl FixedUpdate method for any player with this role /// @@ -76,7 +78,7 @@ public interface ICustomRole var taskStringBuilder = Helpers.CreateForRole(this); return taskStringBuilder; } - + bool IsModifierApplicable(BaseModifier modifier) { return true; @@ -86,7 +88,7 @@ public interface ICustomRole { ParentMod.PluginConfig.TryGetEntry(NumConfigDefinition, out var numEntry); ParentMod.PluginConfig.TryGetEntry(ChanceConfigDefinition, out var chanceEntry); - + return new NetData(RoleId.Get(GetType()), BitConverter.GetBytes(numEntry.Value).AddRangeToArray(BitConverter.GetBytes(chanceEntry.Value))); } } \ No newline at end of file