diff --git a/MiraAPI.Example/ExampleOptions.cs b/MiraAPI.Example/ExampleOptions.cs index 44d7296..0395966 100644 --- a/MiraAPI.Example/ExampleOptions.cs +++ b/MiraAPI.Example/ExampleOptions.cs @@ -9,11 +9,20 @@ namespace MiraAPI.Example public string GroupName => "General Group"; public Color GroupColor => Color.red; - [ModdedToggleOption("Use Thing")] public bool useThing { get; set; } = false; - [ModdedToggleOption("Use another thing")] public bool useAnotherThing { get; set; } = true; - [ModdedNumberOption("Sussy level", min: 0, max: 10)] public float sussyLevel { get; set; } = 4f; - [ModdedStringOption("Sus choices", ["hello", "hello 2", "hello 3"])] public int susChoices { get; set; } = 2; - [ModdedEnumOption("Enum test", typeof(TestEnum))] public TestEnum enumTest { get; set; } = TestEnum.Bye; + [ModdedToggleOption("Use Thing")] + public bool useThing { get; set; } = false; + + [ModdedToggleOption("Use another thing")] + public bool useAnotherThing { get; set; } = true; + + [ModdedNumberOption("Sussy level", min: 0, max: 10)] + public float sussyLevel { get; set; } = 4f; + + [ModdedStringOption("Sus choices", ["hello", "hello 2", "hello 3"])] + public int susChoices { get; set; } = 2; + + [ModdedEnumOption("Enum test", typeof(TestEnum))] + public TestEnum enumTest { get; set; } = TestEnum.Bye; } public enum TestEnum diff --git a/MiraAPI.Example/ExamplePlugin.cs b/MiraAPI.Example/ExamplePlugin.cs index 2d0975c..dec31c1 100644 --- a/MiraAPI.Example/ExamplePlugin.cs +++ b/MiraAPI.Example/ExamplePlugin.cs @@ -1,4 +1,5 @@ using BepInEx; +using BepInEx.Configuration; using BepInEx.Unity.IL2CPP; using HarmonyLib; using MiraAPI.PluginLoading; @@ -15,6 +16,7 @@ namespace MiraAPI.Example; public partial class ExamplePlugin : BasePlugin, IMiraPlugin { public Harmony Harmony { get; } = new(Id); + public ConfigFile GetConfigFile() => Config; public override void Load() { Harmony.PatchAll(); diff --git a/MiraAPI/GameOptions/IModdedOptionGroup.cs b/MiraAPI/GameOptions/IModdedOptionGroup.cs index 41c0d36..1560a70 100644 --- a/MiraAPI/GameOptions/IModdedOptionGroup.cs +++ b/MiraAPI/GameOptions/IModdedOptionGroup.cs @@ -7,7 +7,7 @@ namespace MiraAPI.GameOptions { public string GroupName { get; } public Func GroupVisible => () => true; - public Color GroupColor => Color.white; + public Color GroupColor => Color.clear; public Type AdvancedRole => null; } } diff --git a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs index 2543232..2627dc8 100644 --- a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs +++ b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs @@ -25,6 +25,11 @@ public static class GameOptionsMenuPatch { CategoryHeaderMasked categoryHeaderMasked = UnityEngine.Object.Instantiate(__instance.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer); categoryHeaderMasked.SetHeader(CustomStringName.CreateAndRegister(group.GroupName), 20); + if (group.GroupColor != Color.clear) + { + categoryHeaderMasked.Background.color = group.GroupColor; + categoryHeaderMasked.Title.color = group.GroupColor.DarkenColor(); + } categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f; categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, num, -2f); num -= 0.63f; @@ -38,10 +43,13 @@ public static class GameOptionsMenuPatch SpriteRenderer[] componentsInChildren = newOpt.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { + if (group.GroupColor != Color.clear) componentsInChildren[i].color = group.GroupColor; componentsInChildren[i].material.SetInt(PlayerMaterial.MaskLayer, 20); } + foreach (TextMeshPro textMeshPro in newOpt.GetComponentsInChildren(true)) { + if (group.GroupColor != Color.clear) textMeshPro.color = group.GroupColor.DarkenColor(); textMeshPro.fontMaterial.SetFloat("_StencilComp", 3f); textMeshPro.fontMaterial.SetFloat("_Stencil", 20); } diff --git a/MiraAPI/Patches/Options/GameSettingMenuPatches.cs b/MiraAPI/Patches/Options/GameSettingMenuPatches.cs index 1e9fd6c..5926f14 100644 --- a/MiraAPI/Patches/Options/GameSettingMenuPatches.cs +++ b/MiraAPI/Patches/Options/GameSettingMenuPatches.cs @@ -33,7 +33,7 @@ public static class GameSettingMenuPatches text = tmpText.GetComponent(); text.fontSizeMax = 3.2f; - UpdateText(__instance.GameSettingsTab); + UpdateText(__instance.GameSettingsTab, __instance.RoleSettingsTab); text.alignment = TextAlignmentOptions.Center; @@ -51,8 +51,8 @@ public static class GameSettingMenuPatches if (currentSelectedMod != MiraPluginManager.Instance.RegisteredPlugins.Count) { currentSelectedMod += 1; + UpdateText(__instance.GameSettingsTab, __instance.RoleSettingsTab); } - UpdateText(__instance.GameSettingsTab); })); GameObject backButton = GameObject.Instantiate(nextButton, __instance.BackButton.transform.parent).gameObject; @@ -65,12 +65,12 @@ public static class GameSettingMenuPatches if (currentSelectedMod != 0) { currentSelectedMod -= 1; + UpdateText(__instance.GameSettingsTab, __instance.RoleSettingsTab); } - UpdateText(__instance.GameSettingsTab); })); } - public static void UpdateText(GameOptionsMenu settings) + public static void UpdateText(GameOptionsMenu settings, RolesSettingsMenu roles) { if (currentSelectedMod == 0) { @@ -84,31 +84,62 @@ public static class GameSettingMenuPatches if (selectedMod == null) { currentSelectedMod = 0; - UpdateText(settings); + UpdateText(settings, roles); } string name = selectedMod.PluginInfo.Metadata.Name; text.text = name.Substring(0, Math.Min(name.Length, 15)); } - if (settings.Children is null || settings is null) return; - - foreach (var child in settings.Children) + if (roles is not null && roles.roleChances is not null) { - if (child.TryCast()) continue; - if (child.gameObject is null) continue; + if (roles.advancedSettingChildren is not null) + { + foreach (var child in roles.advancedSettingChildren) + { + child.gameObject.DestroyImmediate(); + } + roles.advancedSettingChildren.Clear(); + roles.advancedSettingChildren = null; + } - child.gameObject.DestroyImmediate(); + foreach (var header in roles.RoleChancesSettings.transform.GetComponentsInChildren()) + { + header.gameObject.DestroyImmediate(); + } + + foreach (var roleChance in roles.roleChances) + { + roleChance.gameObject.DestroyImmediate(); + } + + + roles.roleChances.Clear(); + roles.roleChances = null; + roles.AdvancedRolesSettings.gameObject.SetActive(false); + roles.RoleChancesSettings.gameObject.SetActive(true); + roles.SetQuotaTab(); } - foreach (var header in settings.settingsContainer.GetComponentsInChildren()) + if (settings is not null && settings.Children is not null) { - header.gameObject.DestroyImmediate(); + foreach (var child in settings.Children) + { + if (child.TryCast()) continue; + if (child.gameObject is null) continue; + + child.gameObject.DestroyImmediate(); + } + + foreach (var header in settings.settingsContainer.GetComponentsInChildren()) + { + header.gameObject.DestroyImmediate(); + } + + settings.Children.Clear(); + settings.Children = null; + + settings.Initialize(); } - - settings.Children.Clear(); - settings.Children = null; - - settings.Initialize(); } } diff --git a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs index 73b0fda..a802041 100644 --- a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs +++ b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs @@ -1,5 +1,6 @@ using HarmonyLib; using MiraAPI.Roles; +using MiraAPI.Utilities; using MiraAPI.Utilities.Assets; using Reactor.Utilities.Extensions; using System; @@ -18,8 +19,13 @@ namespace MiraAPI.Patches.Options [HarmonyPrefix, HarmonyPatch(nameof(RolesSettingsMenu.SetQuotaTab))] public static bool PatchStart(RolesSettingsMenu __instance) { + __instance.roleChances = new Il2CppSystem.Collections.Generic.List(); + __instance.advancedSettingChildren = new Il2CppSystem.Collections.Generic.List(); + if (GameSettingMenuPatches.currentSelectedMod == 0) { + __instance.AllButton.transform.parent.gameObject.SetActive(true); + __instance.AllButton.gameObject.SetActive(true); __instance.scrollBar.transform.localPosition = new Vector3(-1.4957f, 0.657f, -4); return true; } @@ -134,7 +140,7 @@ namespace MiraAPI.Patches.Options __instance.roleScreenshot.sprite = Sprite.Create(role.RoleScreenshot.texture, new Rect(0, 0, 370, 230), Vector2.one / 2, 100); __instance.roleScreenshot.drawMode = SpriteDrawMode.Sliced; __instance.roleHeaderSprite.color = customRole.RoleColor; - __instance.roleHeaderText.color = new Color(customRole.RoleColor.r - 0.3f, customRole.RoleColor.g - 0.3f, customRole.RoleColor.b - 0.3f); + __instance.roleHeaderText.color = customRole.RoleColor.DarkenColor(); CreateAdvancedSettings(__instance, role); @@ -154,10 +160,12 @@ namespace MiraAPI.Patches.Options public static void CreateQuotaOption(RolesSettingsMenu __instance, RoleBehaviour role, ref float yPos, int index) { + ICustomRole customRole = role as ICustomRole; RoleOptionSetting roleOptionSetting = Object.Instantiate(__instance.roleOptionSettingOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform); roleOptionSetting.transform.localPosition = new Vector3(-0.15f, yPos, -2f); roleOptionSetting.SetRole(GameOptionsManager.Instance.CurrentGameOptions.RoleOptions, role, 20); - roleOptionSetting.labelSprite.color = (role as ICustomRole).RoleColor; + roleOptionSetting.labelSprite.color = customRole.RoleColor; + roleOptionSetting.titleText.color = customRole.RoleColor.DarkenColor(); roleOptionSetting.OnValueChanged = new Action(ValueChanged); roleOptionSetting.titleText.horizontalAlignment = TMPro.HorizontalAlignmentOptions.Left; roleOptionSetting.SetClickMask(__instance.ButtonClickMask); diff --git a/MiraAPI/Patches/Roles/RoleOptionSettingPatch.cs b/MiraAPI/Patches/Roles/RoleOptionSettingPatch.cs deleted file mode 100644 index 7ad8500..0000000 --- a/MiraAPI/Patches/Roles/RoleOptionSettingPatch.cs +++ /dev/null @@ -1,24 +0,0 @@ -using HarmonyLib; -using MiraAPI.Roles; - -namespace MiraAPI.Patches.Roles; -/* -[HarmonyPatch(typeof(RoleOptionSetting))] -public static class RoleOptionSettingPatch -{ - /// - /// Update the role details screen in role settings for Launchpad roles - /// - [HarmonyPrefix, HarmonyPatch("ShowRoleDetails")] - public static bool ShowRoleDetailsPrefix(RoleOptionSetting __instance) - { - if (__instance.Role is ICustomRole customRole) - { - GameSettingMenu.Instance.RoleName.text = __instance.Role.NiceName; - GameSettingMenu.Instance.RoleBlurb.text = __instance.Role.BlurbLong; - GameSettingMenu.Instance.RoleIcon.sprite = customRole.Icon.LoadAsset(); - return false; - } - return true; - } -}*/ \ No newline at end of file diff --git a/MiraAPI/Patches/Roles/RolesSettingsMenuPatches.cs b/MiraAPI/Patches/Roles/RolesSettingsMenuPatches.cs deleted file mode 100644 index e39a1a7..0000000 --- a/MiraAPI/Patches/Roles/RolesSettingsMenuPatches.cs +++ /dev/null @@ -1,148 +0,0 @@ -using AmongUs.GameOptions; -using HarmonyLib; -using Il2CppInterop.Runtime; -using MiraAPI.Roles; -using Reactor.Networking.Rpc; -using Reactor.Utilities.Extensions; -using System.Linq; -using MiraAPI.Networking; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace MiraAPI.Patches.Roles; -/* -[HarmonyPatch(typeof(RolesSettingsMenu))] -public static class RolesSettingsMenuPatches -{ - /// - /// Create role buttons and advanced role settings menu for every custom Launchpad role - /// - [HarmonyPrefix, HarmonyPatch("OnEnable")] - public static void OnEnablePrefix(RolesSettingsMenu __instance) - { - var tabPrefab = __instance.AllAdvancedSettingTabs.ToArray()[1].Tab; - foreach (var (key, role) in CustomRoleManager.CustomRoles) - { - if (__instance.AllAdvancedSettingTabs.ToArray().Any(x => (ushort)x.Type == key)) - { - continue; - } - - if (role is ICustomRole { HideSettings: true }) - { - continue; - } - - var numChanceOption = Object.Instantiate(__instance.SettingPrefab, __instance.ItemParent); - numChanceOption.transform.localPosition = new Vector3(0.044f, 0, 0); - numChanceOption.name = role.NiceName; - numChanceOption.Role = role; - __instance.AllRoleSettings.Add(numChanceOption); - - - var newTab = Object.Instantiate(tabPrefab, __instance.AdvancedRolesSettings.transform); - newTab.name = role.NiceName + " Settings"; - var toggleSet = Object.Instantiate(newTab.GetComponentInChildren(true)); - var numberSet = Object.Instantiate(newTab.GetComponentInChildren(true)); - - foreach (var option in newTab.GetComponentsInChildren()) - { - option.gameObject.Destroy(); - } - - var startOffset = 0.5f; - - /* foreach (var customOption in CustomOptionsManager.CustomOptions) - { - if (customOption.AdvancedRole is not null && customOption.AdvancedRole == role.GetType()) - { - startOffset -= 0.5f; - - switch (customOption) - { - case CustomNumberOption numberOption: - var numOpt = numberOption.CreateNumberOption(numberSet, newTab.transform); - numOpt.transform.localPosition = new Vector3(-1.25f, startOffset, 0); - break; - - case CustomToggleOption toggleOption: - var togOpt = toggleOption.CreateToggleOption(toggleSet, newTab.transform); - togOpt.transform.localPosition = new Vector3(-1.25f, startOffset, 0); - break; - } - } - }*\/ - - var tmp = newTab.GetComponentInChildren(); - tmp.defaultStr = role.NiceName; - tmp.TargetText = role.StringName; - - var newAdvSet = new AdvancedRoleSettingsButton - { - Tab = newTab, - Type = (RoleTypes)key - }; - - __instance.AllAdvancedSettingTabs.Add(newAdvSet); - - toggleSet.gameObject.Destroy(); - numberSet.gameObject.Destroy(); - } - } - - /// - /// Set custom role options OnValueChanged and re-enable the role settings menu scrolling - /// - [HarmonyPostfix, HarmonyPatch("Start")] - public static void StartPostfix(RolesSettingsMenu __instance) - { - /* foreach (var customOption in CustomOptionsManager.CustomOptions) - { - if (customOption.AdvancedRole is not null) - { - customOption.OptionBehaviour.OnValueChanged = (Action)customOption.ValueChanged; - } - }*\/ - - var scroll = __instance.GetComponentInChildren(); - scroll.active = true; - scroll.ContentYBounds.max = 2 * __instance.AllRoleSettings.Count / 10f; - - scroll.transform.FindChild("UI_Scrollbar").gameObject.SetActive(true); - } - - /// - /// Update config when value changed - /// - [HarmonyPrefix, HarmonyPatch("ValueChanged")] - public static bool ValueChangedPrefix(RolesSettingsMenu __instance, [HarmonyArgument(0)] OptionBehaviour obj) - { - if (obj.GetIl2CppType() != Il2CppType.Of()) - { - return true; - } - - var roleSetting = obj.Cast(); - - if (roleSetting.Role is not ICustomRole role || role.HideSettings) - { - return true; - } - - MiraAPIPlugin.Instance.Config.TryGetEntry(role.NumConfigDefinition, out var numEntry); - numEntry.Value = roleSetting.RoleMaxCount; - - MiraAPIPlugin.Instance.Config.TryGetEntry(role.ChanceConfigDefinition, out var chanceEntry); - chanceEntry.Value = roleSetting.RoleChance; - - roleSetting.UpdateValuesAndText(GameOptionsManager.Instance.CurrentGameOptions.RoleOptions); - - if (AmongUsClient.Instance.AmHost) - { - Rpc.Instance.Send(new SyncRoleOptionsRpc.Data((ushort)roleSetting.Role.Role, numEntry.Value, chanceEntry.Value)); - } - GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.CurrentGameOptions; - return false; - } -} -*/ \ No newline at end of file diff --git a/MiraAPI/PluginLoading/IMiraPlugin.cs b/MiraAPI/PluginLoading/IMiraPlugin.cs index 85c0cc8..4b7adba 100644 --- a/MiraAPI/PluginLoading/IMiraPlugin.cs +++ b/MiraAPI/PluginLoading/IMiraPlugin.cs @@ -1,6 +1,9 @@ -namespace MiraAPI.PluginLoading +using BepInEx.Configuration; + +namespace MiraAPI.PluginLoading { public interface IMiraPlugin { + public ConfigFile GetConfigFile(); } } diff --git a/MiraAPI/PluginLoading/MiraPluginInfo.cs b/MiraAPI/PluginLoading/MiraPluginInfo.cs index bd57202..f44bc50 100644 --- a/MiraAPI/PluginLoading/MiraPluginInfo.cs +++ b/MiraAPI/PluginLoading/MiraPluginInfo.cs @@ -1,4 +1,5 @@ using BepInEx; +using BepInEx.Configuration; using MiraAPI.GameModes; using MiraAPI.GameOptions; using System.Collections.Generic; @@ -8,8 +9,9 @@ namespace MiraAPI.PluginLoading; public class MiraPluginInfo { public string PluginId { get; set; } - public IMiraPlugin Config { get; set; } + public IMiraPlugin MiraPlugin { get; set; } public PluginInfo PluginInfo { get; set; } + public ConfigFile PluginConfig { get; set; } public readonly List OptionGroups = []; public readonly List Options = []; @@ -17,11 +19,12 @@ public class MiraPluginInfo public readonly Dictionary CustomRoles = []; public readonly Dictionary GameModes = []; - public MiraPluginInfo(string id, IMiraPlugin config, PluginInfo info) + public MiraPluginInfo(string id, IMiraPlugin miraPlugin, PluginInfo info) { PluginId = id; - Config = config; + MiraPlugin = miraPlugin; PluginInfo = info; + PluginConfig = miraPlugin.GetConfigFile(); } } \ No newline at end of file diff --git a/MiraAPI/Roles/CustomRoleManager.cs b/MiraAPI/Roles/CustomRoleManager.cs index a0e2ecf..9de57f5 100644 --- a/MiraAPI/Roles/CustomRoleManager.cs +++ b/MiraAPI/Roles/CustomRoleManager.cs @@ -1,6 +1,7 @@ using AmongUs.GameOptions; using Il2CppInterop.Runtime; using MiraAPI.Networking; +using MiraAPI.PluginLoading; using Reactor.Localization.Utilities; using Reactor.Networking.Rpc; using Reactor.Utilities; @@ -83,6 +84,10 @@ public static class CustomRoleManager return roleBehaviour; } + public static MiraPluginInfo FindParentMod(ICustomRole role) + { + return MiraPluginManager.Instance.RegisteredPlugins.First(plugin => plugin.Value.CustomRoles.Values.Contains(role as RoleBehaviour)).Value; + } public static bool GetCustomRoleBehaviour(RoleTypes roleType, out ICustomRole result) { diff --git a/MiraAPI/Utilities/Extensions.cs b/MiraAPI/Utilities/Extensions.cs index 4be7630..99ed160 100644 --- a/MiraAPI/Utilities/Extensions.cs +++ b/MiraAPI/Utilities/Extensions.cs @@ -15,6 +15,10 @@ namespace MiraAPI.Utilities return false; } + public static Color DarkenColor(this Color color) + { + return new Color(color.r - 0.3f, color.g - 0.3f, color.b - 0.3f); + } public static void UpdateBodies(this PlayerControl playerControl, Color outlineColor, ref DeadBody target) { foreach (var body in Object.FindObjectsOfType())