Compare commits

...
Author SHA1 Message Date
XtraCube 9504862bea add format string option to number options 2025-02-21 12:01:28 -05:00
XtraCube 4b6ffc65df fix after murder event 2025-02-21 09:26:53 -05:00
XtraCube ccde63068b fix lobby view pane issues 2025-02-18 21:49:54 -05:00
XtraCube 5e16429acf fix more scrolling issues 2025-02-18 11:15:13 -05:00
XtraCube 1e47500686 fix scrolling issues 2025-02-18 11:03:50 -05:00
XtraCube 0b1cf998f8 fix coloring issues and hidden roles in rolesettingsmenu 2025-02-17 21:59:58 -05:00
XtraCube 14a3669031 fix rolebehaviour stubs cuz im an idiot 2025-02-17 11:52:57 -05:00
XtraCube ae79cd87d9 :shush: 2025-02-17 11:37:02 -05:00
9 changed files with 115 additions and 57 deletions

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@ public class ExampleOptions : AbstractOptionGroup
[ModdedToggleOption("Toggle Opt 2")]
public bool ToggleOpt2 { get; set; } = true;
[ModdedNumberOption("Number Opt", min: 0, max: 10, suffixType: MiraNumberSuffixes.Percent)]
[ModdedNumberOption("Number Opt", min: 0, max: 10, increment: .25f, formatString: "0.00", suffixType: MiraNumberSuffixes.Percent)]
public float NumberOpt { get; set; } = 4f;
[ModdedEnumOption("Best API", typeof(BestApi), ["Mira API", "Mitochondria", "Reactor"])]
@@ -15,13 +15,14 @@ public class ModdedNumberOptionAttribute(
float max,
float increment = 1,
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None,
string? formatString = null,
bool zeroInfinity = false,
Type? roleType = null)
: ModdedOptionAttribute(title, roleType)
{
internal override IModdedOption CreateOption(object? value, PropertyInfo property)
{
return new ModdedNumberOption(Title, (float)(value ?? min+increment), min, max, increment, suffixType, zeroInfinity, RoleType);
return new ModdedNumberOption(Title, (float)(value ?? min+increment), min, max, increment, suffixType, formatString, zeroInfinity, RoleType);
}
/// <inheritdoc />
@@ -46,6 +46,7 @@ public class ModdedNumberOption : ModdedOption<float>
/// <param name="max">The maximum value.</param>
/// <param name="increment">The increment.</param>
/// <param name="suffixType">The suffix type.</param>
/// <param name="formatString">Optional format string for the option screen.</param>
/// <param name="zeroInfinity">Whether zero is infinity or not.</param>
/// <param name="roleType">An optional role type.</param>
public ModdedNumberOption(
@@ -55,6 +56,7 @@ public class ModdedNumberOption : ModdedOption<float>
float max,
float increment,
MiraNumberSuffixes suffixType,
string? formatString = null,
bool zeroInfinity = false,
Type? roleType = null) : base(title, defaultValue, roleType)
{
@@ -74,7 +76,13 @@ public class ModdedNumberOption : ModdedOption<float>
data.Value = Value;
data.Increment = Increment;
data.ValidRange = new FloatRange(Min, Max);
data.FormatString = Increment % 1 == 0 && Value % 1 == 0 && Min % 1 == 0 && Max % 1 == 0 ? "0" : "0.0"; // not sure if the == checks will work since this is floats but we'll find out
data.FormatString = formatString ??
(!Mathf.Approximately(defaultValue, 0) ||
!Mathf.Approximately(Increment % 1, 0) ||
!Mathf.Approximately(Value % 1, 0) ||
!Mathf.Approximately(Min % 1, 0) ||
!Mathf.Approximately(Max % 1, 0) ? "0.0" : "0");
data.ZeroIsInfinity = ZeroInfinity;
data.SuffixType = (NumberSuffixes)SuffixType;
data.OptionName = FloatOptionNames.Invalid;
+3 -3
View File
@@ -263,6 +263,9 @@ public static class CustomMurderRpc
deadBody.enabled = true;
}
var afterMurderEvent = new AfterMurderEvent(source, target);
MiraEventManager.InvokeEvent(afterMurderEvent);
if (!isParticipant)
{
yield break;
@@ -275,8 +278,5 @@ public static class CustomMurderRpc
PlayerControl.LocalPlayer.isKilling = false;
source.isKilling = false;
var afterMurderEvent = new AfterMurderEvent(source, target);
MiraEventManager.InvokeEvent(afterMurderEvent);
}
}
@@ -4,17 +4,19 @@ using UnityEngine;
namespace MiraAPI.Patches.Colors;
[HarmonyPatch(typeof(PlayerTab))]
/// <summary>
/// This patch adds scrolling to the colors tab in the player customization menu.
/// </summary>
[HarmonyPatch(typeof(PlayerTab), nameof(PlayerTab.OnEnable))]
public static class ScrollingColorsPatch
{
// Collider
private static BoxCollider2D? _collider;
/// <summary>
/// Add scrolling to the colors tab
/// Add scrolling to the colors tab.
/// </summary>
[HarmonyPostfix, HarmonyPatch("OnEnable")]
public static void AddScrollingToColorsTabPatch(PlayerTab __instance)
public static void Postfix(PlayerTab __instance)
{
if (!PlayerCustomizationMenu.Instance)
{
@@ -157,8 +157,6 @@ public static class GameSettingMenuPatches
roles.AdvancedRolesSettings.gameObject.SetActive(false);
roles.RoleChancesSettings.gameObject.SetActive(true);
roles.SetQuotaTab();
roles.scrollBar.CalculateAndSetYBounds(roles.roleChances.Count + 5, 1f, 6f, 0.43f);
roles.scrollBar.ScrollToTop();
}
+36 -25
View File
@@ -6,6 +6,7 @@ using MiraAPI.Utilities.Assets;
using System;
using System.Collections.Generic;
using System.Linq;
using Reactor.Localization.Utilities;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
@@ -211,34 +212,43 @@ public static class LobbyViewPanePatches
var list = new List<Type>();
foreach (var team in Enum.GetValues<ModdedRoleTeams>())
{
var filteredRoles = SelectedMod.CustomRoles.Values
.OfType<ICustomRole>()
.Where(x => !x.Configuration.HideSettings && x.Team == team).ToList();
var roleGroups = GameSettingMenuPatches.SelectedMod?.CustomRoles.Values.OfType<ICustomRole>()
.ToLookup(x => x.RoleOptionsGroup);
if (filteredRoles.Count == 0)
if (roleGroups is null)
{
return;
}
// sort the groups by priority
var sortedRoleGroups = roleGroups
.OrderBy(x => x.Key.Priority)
.ThenBy(x => x.Key.Name);
foreach (var grouping in sortedRoleGroups)
{
if (!grouping.Any())
{
continue;
}
var categoryHeaderRoleVariant =
Object.Instantiate(instance.categoryHeaderRoleOrigin, instance.settingsContainer, true);
var group = grouping.Key;
switch (team)
var name = group.Name switch
{
case ModdedRoleTeams.Crewmate:
categoryHeaderRoleVariant.SetHeader(StringNames.CrewmateRolesHeader, 61);
break;
case ModdedRoleTeams.Impostor:
categoryHeaderRoleVariant.SetHeader(StringNames.ImpostorRolesHeader, 61);
break;
default:
categoryHeaderRoleVariant.SetHeader(StringNames.CrewmateRolesHeader, 61);
categoryHeaderRoleVariant.Title.text = team + " Roles";
categoryHeaderRoleVariant.Background.color = Color.gray;
categoryHeaderRoleVariant.Title.color = Color.white;
break;
"Crewmate" => StringNames.CrewmateRolesHeader,
"Impostor" => StringNames.ImpostorRolesHeader,
_ => CustomStringName.CreateAndRegister(group.Name),
};
var categoryHeaderRoleVariant = Object.Instantiate(instance.categoryHeaderRoleOrigin, instance.settingsContainer, true);
categoryHeaderRoleVariant.SetHeader(name, 61);
if (name is not (StringNames.CrewmateRolesHeader or StringNames.ImpostorRolesHeader))
{
var veryDarkColor = group.Color.DarkenColor(.35f);
categoryHeaderRoleVariant.Title.color = veryDarkColor;
categoryHeaderRoleVariant.Background.color = group.Color;
}
categoryHeaderRoleVariant.transform.localScale = Vector3.one;
@@ -246,7 +256,7 @@ public static class LobbyViewPanePatches
instance.settingsInfo.Add(categoryHeaderRoleVariant.gameObject);
num -= 0.696f;
foreach (var customRole in filteredRoles)
foreach (var customRole in grouping)
{
var roleBehaviour = customRole as RoleBehaviour;
if (roleBehaviour == null)
@@ -259,8 +269,6 @@ public static class LobbyViewPanePatches
var numPerGame =
GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetNumPerGame(roleBehaviour.Role);
var flag = numPerGame == 0;
var viewSettingsInfoPanelRoleVariant =
Object.Instantiate(
instance.infoPanelRoleOrigin,
@@ -273,7 +281,7 @@ public static class LobbyViewPanePatches
.Where(x => x.AdvancedRole == customRole.GetType())
.ToList();
if (!flag && advancedRoleOptions.Count > 0)
if (numPerGame > 0 && advancedRoleOptions.Count > 0)
{
list.Add(customRole.GetType());
}
@@ -286,6 +294,8 @@ public static class LobbyViewPanePatches
customRole.RoleColor,
customRole.Configuration.Icon.LoadAsset(),
true);
viewSettingsInfoPanelRoleVariant.iconSprite.transform.localScale = new Vector3(0.365f, 0.365f, 1f);
viewSettingsInfoPanelRoleVariant.iconSprite.transform.localPosition = new Vector3(0.7144f, -0.028f, -2);
viewSettingsInfoPanelRoleVariant.titleText.color =
viewSettingsInfoPanelRoleVariant.chanceTitle.color =
@@ -370,6 +380,7 @@ public static class LobbyViewPanePatches
maskLayer,
role.TeamType == RoleTeamTypes.Crewmate,
customRole.Configuration.Icon.LoadAsset());
viewPanel.header.icon.transform.localScale = new Vector3(0.465f, 0.465f, 1f);
viewPanel.divider.material.SetInt(PlayerMaterial.MaskLayer, maskLayer);
var num = viewPanel.yPosStart;
@@ -26,10 +26,16 @@ public static class RoleSettingMenuPatches
private static List<CategoryHeaderEditRole> CategoryHeaderEditRoles { get; } = [];
private static List<RoleOptionSetting> RoleOptionSettings { get; } = [];
private static float ScrollerNum { get; set; } = 0.522f;
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.SetQuotaTab))]
public static bool PatchStart(RolesSettingsMenu __instance)
{
CategoryHeaderEditRoles.ForEach(Object.Destroy);
CategoryHeaderEditRoles.Clear();
RoleOptionSettings.ForEach(Object.Destroy);
RoleOptionSettings.Clear();
__instance.roleChances = new Il2CppSystem.Collections.Generic.List<RoleOptionSetting>();
__instance.advancedSettingChildren = new Il2CppSystem.Collections.Generic.List<OptionBehaviour>();
@@ -48,7 +54,7 @@ public static class RoleSettingMenuPatches
return true;
}
var num = 0.522f;
ScrollerNum = 0.522f;
__instance.AllButton.transform.parent.gameObject.SetActive(false);
__instance.AllButton.gameObject.SetActive(false);
@@ -80,13 +86,15 @@ public static class RoleSettingMenuPatches
continue;
}
RoleGroupHidden.TryAdd(grouping.Key, false);
var group = grouping.Key;
var name = grouping.Key.Name switch
RoleGroupHidden.TryAdd(group, false);
var name = group.Name switch
{
"Crewmate" => StringNames.CrewmateRolesHeader,
"Impostor" => StringNames.ImpostorRolesHeader,
_ => CustomStringName.CreateAndRegister(grouping.Key.Name),
_ => CustomStringName.CreateAndRegister(group.Name),
};
var categoryHeaderEditRole = Object.Instantiate(
@@ -95,15 +103,26 @@ public static class RoleSettingMenuPatches
Quaternion.identity,
__instance.RoleChancesSettings.transform);
categoryHeaderEditRole.SetHeader(name, 20);
categoryHeaderEditRole.transform.localPosition = new Vector3(4.986f, num, -2f);
if (name is not (StringNames.CrewmateRolesHeader or StringNames.ImpostorRolesHeader))
{
var darkColor = group.Color.DarkenColor(.25f);
var veryDarkColor = group.Color.DarkenColor(.35f);
categoryHeaderEditRole.Title.color = veryDarkColor;
categoryHeaderEditRole.blankLabel.color = veryDarkColor;
categoryHeaderEditRole.Background.color = group.Color;
categoryHeaderEditRole.chanceLabel.color = darkColor;
categoryHeaderEditRole.countLabel.color = darkColor;
}
categoryHeaderEditRole.transform.localPosition = new Vector3(4.986f, ScrollerNum, -2f);
categoryHeaderEditRole.transform.Find("LabelSprite").transform.localScale = new Vector3(1.3f, 1, 0.5529f);
categoryHeaderEditRole.transform.Find("QuotaHeader").gameObject.SetActive(!RoleGroupHidden[grouping.Key]);
categoryHeaderEditRole.transform.Find("QuotaHeader").gameObject.SetActive(!RoleGroupHidden[group]);
CategoryHeaderEditRoles.Add(categoryHeaderEditRole);
num -= 0.522f;
ScrollerNum -= 0.522f;
var label = RoleGroupHidden[grouping.Key]
var label = RoleGroupHidden[group]
? "(Click to open)"
: "(Click to close)";
var newText = Object.Instantiate(categoryHeaderEditRole.Title, categoryHeaderEditRole.transform);
@@ -111,7 +130,7 @@ public static class RoleSettingMenuPatches
newText.transform.localPosition = new Vector3(-3.3425f, -0.1706f, -1);
newText.gameObject.GetComponent<TextTranslatorTMP>().Destroy();
if (!RoleGroupHidden[grouping.Key])
if (!RoleGroupHidden[group])
{
foreach (var role in grouping)
{
@@ -120,7 +139,7 @@ public static class RoleSettingMenuPatches
continue;
}
var option = CreateQuotaOption(__instance, roleBehaviour, ref num, num3);
var option = CreateQuotaOption(__instance, roleBehaviour, num3);
if (option is not null)
{
RoleOptionSettings.Add(option);
@@ -140,7 +159,10 @@ public static class RoleSettingMenuPatches
headerBtn.OnClick.AddListener(
(UnityAction)(() =>
{
RoleGroupHidden[grouping.Key] = !RoleGroupHidden[grouping.Key];
if (RoleGroupHidden.TryGetValue(group, out var value))
{
RoleGroupHidden[group] = !value;
}
foreach (var header in CategoryHeaderEditRoles)
{
header.gameObject.Destroy();
@@ -155,15 +177,20 @@ public static class RoleSettingMenuPatches
}));
headerBtn.SetButtonEnableState(true);
if (!RoleGroupHidden[grouping.Key])
if (!RoleGroupHidden[group])
{
num -= 0.4f;
ScrollerNum -= 0.4f;
}
}
__instance.scrollBar.CalculateAndSetYBounds(__instance.roleChances.Count + 5, 1f, 6f, 0.43f);
__instance.scrollBar.SetScrollBounds();
return false;
}
private static void SetScrollBounds(this Scroller scroller)
{
scroller.CalculateAndSetYBounds(1 + 1.5f * CategoryHeaderEditRoles.Count + RoleOptionSettings.Count, 1f, 6f, 0.43f);
}
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.Update))]
public static bool UpdatePatch()
@@ -175,7 +202,12 @@ public static class RoleSettingMenuPatches
[HarmonyPatch(nameof(RolesSettingsMenu.OpenChancesTab))]
public static void OpenChancesTabPostfix(RolesSettingsMenu __instance)
{
__instance.scrollBar.CalculateAndSetYBounds(__instance.roleChances.Count + 5, 1f, 6f, 0.43f);
if (GameSettingMenuPatches.SelectedModIdx == 0)
{
return;
}
__instance.scrollBar.SetScrollBounds();
__instance.scrollBar.ScrollToTop();
}
@@ -319,7 +351,7 @@ public static class RoleSettingMenuPatches
__instance.RefreshChildren();
}
private static RoleOptionSetting? CreateQuotaOption(RolesSettingsMenu __instance, RoleBehaviour role, ref float yPos, int index)
private static RoleOptionSetting? CreateQuotaOption(RolesSettingsMenu __instance, RoleBehaviour role, int index)
{
if (role is not ICustomRole customRole)
{
@@ -327,12 +359,17 @@ public static class RoleSettingMenuPatches
return null;
}
if (customRole.Configuration.HideSettings)
{
return null;
}
var roleOptionSetting = Object.Instantiate(
__instance.roleOptionSettingOrigin,
Vector3.zero,
Quaternion.identity,
__instance.RoleChancesSettings.transform);
roleOptionSetting.transform.localPosition = new Vector3(-0.15f, yPos, -2f);
roleOptionSetting.transform.localPosition = new Vector3(-0.15f, ScrollerNum, -2f);
roleOptionSetting.SetRole(GameOptionsManager.Instance.CurrentGameOptions.RoleOptions, role, 20);
roleOptionSetting.labelSprite.color = customRole.RoleColor;
@@ -379,7 +416,7 @@ public static class RoleSettingMenuPatches
if (index < GameSettingMenuPatches.SelectedMod?.CustomRoles.Count - 1)
{
yPos += -0.43f;
ScrollerNum += -0.43f;
}
return roleOptionSetting;
+3 -2
View File
@@ -11,10 +11,11 @@ public static class RoleBehaviourStubs
/// Stub method for RoleBehaviour.Initialize.
/// </summary>
/// <param name="instance">The RoleBehaviour object.</param>
/// <param name="player">The PlayerControl to initialize.</param>
[HarmonyReversePatch]
[HarmonyPatch(typeof(RoleBehaviour), nameof(RoleBehaviour.Initialize))]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Initialize(RoleBehaviour instance)
public static void Initialize(RoleBehaviour instance, PlayerControl player)
{
// nothing needed
}
@@ -38,7 +39,7 @@ public static class RoleBehaviourStubs
/// <param name="instance">The RoleBehaviour object.</param>
/// <param name="taskStringBuilder">The StringBuilder to append the task hint to.</param>
[HarmonyReversePatch]
[HarmonyPatch(typeof(RoleBehaviour), nameof(RoleBehaviour.AppendTaskHint))]
[HarmonyPatch(typeof(RoleBehaviour), nameof(RoleBehaviour.AppendTaskHint), typeof(StringBuilder))]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void AppendTaskHint(RoleBehaviour instance, StringBuilder taskStringBuilder)
{