merge ruleset into editorconfig

This commit is contained in:
Az committed 2026-09-13 18:40:37 -04:00
1 parent cd94666ed9
commit 554a77fb64
146 files changed
+648 -514

No files matched your search

+45
View File
@@ -38,3 +38,48 @@ dotnet_diagnostic.S2245.severity = none
# IDE0130: Namespace does not match folder structure
dotnet_diagnostic.IDE0130.severity = none
# SA1633: File should have header
dotnet_diagnostic.SA1633.severity = none
# SA1101: Prefix local calls with this
dotnet_diagnostic.SA1101.severity = none
# SA1600: Elements should be documented
dotnet_diagnostic.SA1600.severity = none
# SA1516: Elements should be separated by blank line
dotnet_diagnostic.SA1516.severity = none
# SA1503: Braces should not be omitted
dotnet_diagnostic.SA1503.severity = none
# SA1201: Elements should appear in the correct order
dotnet_diagnostic.SA1201.severity = none
# SA1402: File may only contain a single type
dotnet_diagnostic.SA1402.severity = none
# SA1204: Static elements should appear before instance elements
dotnet_diagnostic.SA1204.severity = none
# SA1202: Elements should be ordered by access
dotnet_diagnostic.SA1202.severity = none
# SA1649: File name should match first type name
dotnet_diagnostic.SA1649.severity = none
# SA1313: Parameter names should begin with lower-case letter
dotnet_diagnostic.SA1313.severity = none
# SA1636: The file header copyright text should match the copyright text from the settings
dotnet_diagnostic.SA1636.severity = none
# SA1309: Field names should not begin with underscore
dotnet_diagnostic.SA1309.severity = none
# SA1407: Arithmetic expressions should declare precedence
dotnet_diagnostic.SA1407.severity = none
# SA1133: Each attribute should be placed in its own set of square brackets
dotnet_diagnostic.SA1133.severity = none
+6 -9
View File
@@ -28,18 +28,15 @@
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>recommended</AnalysisMode>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<NoWarn>$(NoWarn);SA0001</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Roslynator.Analyzers" Version="5.0.0" PrivateAssets="all" />
<PackageReference Include="Roslynator.Formatting.Analyzers" Version="5.0.0" PrivateAssets="all" />
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="5.0.0" PrivateAssets="all" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.32.0.713" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" PrivateAssets="all" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.32.0.713">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<AdditionalFiles Include="$(MSBuildThisFileDirectory)/stylecop.json" Link="stylecop.json" Visible="false" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)\stylecop.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
</Project>
@@ -61,11 +61,14 @@ public class TeleportButton : CustomActionButton
{
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize;
foreach (var cam in Camera.allCameras)
cam.orthographicSize = Camera.main.orthographicSize;
yield return null;
}
foreach (var cam in Camera.allCameras) cam.orthographicSize = zoomDistance;
foreach (var cam in Camera.allCameras)
cam.orthographicSize = zoomDistance;
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
}
@@ -75,12 +78,14 @@ public class TeleportButton : CustomActionButton
{
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize;
foreach (var cam in Camera.allCameras)
cam.orthographicSize = Camera.main.orthographicSize;
yield return null;
}
foreach (var cam in Camera.allCameras) cam.orthographicSize = 3f;
foreach (var cam in Camera.allCameras)
cam.orthographicSize = 3f;
HudManager.Instance.ShadowQuad.gameObject.SetActive(true);
IsZoom = false;
+2 -1
View File
@@ -1,4 +1,5 @@
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using MiraAPI.Events;
using MiraAPI.Events.Mira;
+2 -2
View File
@@ -1,7 +1,7 @@
using MiraAPI.GameOptions;
using System.Collections.Generic;
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes;
using MiraAPI.Utilities;
using System.Collections.Generic;
using UnityEngine;
namespace MiraAPI.Example.Options;
+5 -5
View File
@@ -9,13 +9,13 @@ namespace MiraAPI.Example.Roles;
public class ChameleonRole : CrewmateRole, ICustomRole
{
private bool shouldHide;
public string IdPart => "Chameleon";
public string IdPrefix => "ApiExample.Role.Crewmate";
public Color RoleColor => Palette.AcceptedGreen;
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
private bool _shouldHide;
public CustomRoleConfiguration Configuration => new(this)
{
OptionsScreenshot = ExampleAssets.Banner,
@@ -30,12 +30,12 @@ public class ChameleonRole : CrewmateRole, ICustomRole
{
Logger<ExamplePlugin>.Info("Initializing ChameleonRole for player: " + player.PlayerId);
RoleBehaviourStubs.Initialize(this, player);
_shouldHide = true;
shouldHide = true;
}
public void FixedUpdate()
{
if (!Player || !_shouldHide)
if (!Player || !shouldHide)
{
return;
}
@@ -76,7 +76,7 @@ public class ChameleonRole : CrewmateRole, ICustomRole
{
Logger<ExamplePlugin>.Info("Deinitializing ChameleonRole for player: " + targetPlayer.PlayerId);
RoleBehaviourStubs.Deinitialize(this, targetPlayer);
_shouldHide = false;
shouldHide = false;
foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>(true))
{
cosmetic.color = Color.white;
+9 -6
View File
@@ -32,18 +32,21 @@ public sealed class CustomColor(StringNames name, Color32 mainColor, Color32 sha
/// </summary>
public CustomColorBrightness ColorBrightness { get; set; } = CustomColorBrightness.Darker;
/// <inheritdoc />
public CustomColor(StringNames name, Color32 mainColor) : this(name, mainColor, mainColor.GetShadowColor(60))
/// <inheritdoc cref="CustomColor"/>
public CustomColor(StringNames name, Color32 mainColor)
: this(name, mainColor, mainColor.GetShadowColor(60))
{
}
/// <inheritdoc />
public CustomColor(string name, Color32 mainColor) : this(name, mainColor, mainColor.GetShadowColor(60))
/// <inheritdoc cref="CustomColor"/>
public CustomColor(string name, Color32 mainColor)
: this(name, mainColor, mainColor.GetShadowColor(60))
{
}
/// <inheritdoc />
public CustomColor(string name, Color32 mainColor, Color32 shadowColor) : this(MiraLocaleManager.GetOrCreateLocaleString(name), mainColor, shadowColor)
/// <inheritdoc cref="CustomColor"/>
public CustomColor(string name, Color32 mainColor, Color32 shadowColor)
: this(MiraLocaleManager.GetOrCreateLocaleString(name), mainColor, shadowColor)
{
}
}
@@ -7,7 +7,8 @@ namespace MiraAPI.Events.Mira;
/// </summary>
/// <typeparam name="T">The <see cref="CustomActionButton"/> type.</typeparam>
/// <param name="button">The <see cref="CustomActionButton"/> whose click was cancelled.</param>
public sealed class MiraButtonCancelledEvent<T>(T button) : MiraEvent where T : CustomActionButton
public sealed class MiraButtonCancelledEvent<T>(T button) : MiraEvent
where T : CustomActionButton
{
/// <summary>
/// Gets the <see cref="CustomActionButton"/> whose click was cancelled.
+2 -1
View File
@@ -8,7 +8,8 @@ namespace MiraAPI.Events.Mira;
/// <typeparam name="T">The <see cref="CustomActionButton"/> type.</typeparam>
/// <param name="button">The <see cref="CustomActionButton"/> that was clicked.</param>
/// <param name="genericClickEvent">The generic <see cref="MiraButtonClickEvent"/> invoked before button-specific events.</param>
public class MiraButtonClickEvent<T>(T button, MiraButtonClickEvent genericClickEvent) : MiraCancelableEvent where T : CustomActionButton
public class MiraButtonClickEvent<T>(T button, MiraButtonClickEvent genericClickEvent) : MiraCancelableEvent
where T : CustomActionButton
{
/// <summary>
/// Gets the <see cref="CustomActionButton"/> that was clicked.
+4 -2
View File
@@ -17,7 +17,8 @@ public static class MiraEventManager
/// <param name="eventInstance">The <typeparamref name="T"/> instance.</param>
/// <typeparam name="T">Type of Event.</typeparam>
/// <returns>If there was an event handler invoked for this event, return <see langword="true"/>. Otherwise, return <see langword="false"/>.</returns>
public static bool InvokeEvent<T>(this T eventInstance) where T : MiraEvent
public static bool InvokeEvent<T>(this T eventInstance)
where T : MiraEvent
{
EventWrappers.TryGetValue(typeof(T), out var handlers);
@@ -109,7 +110,8 @@ public static class MiraEventManager
/// <param name="priority">The priority of the event handler. Lower values are called first.</param>
/// <typeparam name="T">Type of <see cref="MiraEvent"/> event.</typeparam>
/// <returns>A <see cref="MiraEventHandle"/> to use when unregistering the event.</returns>
public static MiraEventHandle RegisterEventHandler<T>(Action<T> handler, int priority = 0) where T : MiraEvent
public static MiraEventHandle RegisterEventHandler<T>(Action<T> handler, int priority = 0)
where T : MiraEvent
{
EventWrappers.TryAdd(typeof(T), []);
@@ -7,7 +7,8 @@ namespace MiraAPI.Events.Vanilla.Gameplay;
/// </summary>
/// <typeparam name="T">The vanilla <see cref="AbilityButton"/> type.</typeparam>
/// <param name="button">The vanilla <see cref="AbilityButton"/> whose click was cancelled.</param>
public sealed class VanillaButtonCancelledEvent<T>(T button) : MiraEvent where T : AbilityButton
public sealed class VanillaButtonCancelledEvent<T>(T button) : MiraEvent
where T : AbilityButton
{
/// <summary>
/// Gets the Vanilla <see cref="AbilityButton"/> whose click was cancelled.
@@ -8,7 +8,8 @@ namespace MiraAPI.Events.Vanilla.Gameplay;
/// <typeparam name="T">The vanilla <see cref="AbilityButton"/> type.</typeparam>
/// <param name="button">The vanilla <see cref="AbilityButton"/> that was clicked.</param>
/// <param name="genericClickEvent">The generic <see cref="VanillaButtonClickEvent"/> invoked before button-specific events.</param>
public sealed class VanillaButtonClickEvent<T>(T button, VanillaButtonClickEvent genericClickEvent) : MiraCancelableEvent where T : AbilityButton
public sealed class VanillaButtonClickEvent<T>(T button, VanillaButtonClickEvent genericClickEvent) : MiraCancelableEvent
where T : AbilityButton
{
/// <summary>
/// Gets the vanilla <see cref="AbilityButton"/> that was clicked.
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using MiraAPI.Voting;
@@ -11,7 +12,7 @@ namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <param name="exiledPlayer">The player to be exiled. Will be <see langword="null"/> if no player is to be exiled.</param>
public class ProcessVotesEvent(List<CustomVote> votes, NetworkedPlayerInfo? exiledPlayer = null) : MiraEvent
{
private readonly List<CustomVote> _originalVotes = [.. votes];
private readonly List<CustomVote> originalVotes = [.. votes];
/// <summary>
/// Gets a value indicating whether the exiled player has been modified by the event.
@@ -21,7 +22,7 @@ public class ProcessVotesEvent(List<CustomVote> votes, NetworkedPlayerInfo? exil
/// <summary>
/// Gets a value indicating whether the votes have been modified by the event.
/// </summary>
public bool VotesModified => !Votes.SequenceEqual(_originalVotes);
public bool VotesModified => !Votes.SequenceEqual(originalVotes);
/// <summary>
/// Gets the list of <see cref="CustomVote"/>s that are being processed.
@@ -41,6 +42,7 @@ public class ProcessVotesEvent(List<CustomVote> votes, NetworkedPlayerInfo? exil
/// <summary>
/// Gets or sets the player to be exiled. Will be <see langword="null"/> if no player is to be exiled.
/// </summary>
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "Looks weird.")]
public NetworkedPlayerInfo? ExiledPlayer
{
get;
+4 -2
View File
@@ -48,7 +48,8 @@ public abstract class CustomGameOver
/// </summary>
/// <typeparam name="T">Type of the custom game over.</typeparam>
/// <returns>The <see cref="global::GameOverReason"/> associated with the custom game over.</returns>
public static GameOverReason GameOverReason<T>() where T : CustomGameOver
public static GameOverReason GameOverReason<T>()
where T : CustomGameOver
{
return (GameOverReason)GameOverManager.GetGameOverId<T>();
}
@@ -58,7 +59,8 @@ public abstract class CustomGameOver
/// </summary>
/// <param name="winners">A collection of winners.</param>
/// <typeparam name="T">Type of the custom game over.</typeparam>
public static void Trigger<T>(IEnumerable<NetworkedPlayerInfo> winners) where T : CustomGameOver
public static void Trigger<T>(IEnumerable<NetworkedPlayerInfo> winners)
where T : CustomGameOver
{
var reason = GameOverManager.GetGameOverId<T>();
var data = new GameOverData(reason, [.. winners]);
+6 -5
View File
@@ -12,7 +12,7 @@ public static class GameOverManager
private static readonly Dictionary<Type, int> GameOverIds = [];
private static readonly Dictionary<int, Type> GameOverTypes = [];
private static int _nextId = Enum.GetNames<GameOverReason>().Length;
private static int nextId = Enum.GetNames<GameOverReason>().Length;
/// <summary>
/// Register a <see cref="CustomGameOver"/>.
@@ -39,9 +39,9 @@ public static class GameOverManager
return false;
}
GameOverIds.Add(gameOverType, _nextId);
GameOverTypes.Add(_nextId, gameOverType);
_nextId++;
GameOverIds.Add(gameOverType, nextId);
GameOverTypes.Add(nextId, gameOverType);
nextId++;
return true;
}
@@ -68,7 +68,8 @@ public static class GameOverManager
/// </summary>
/// <typeparam name="T">Type of the <see cref="CustomGameOver"/>.</typeparam>
/// <returns>The ID of the <see cref="CustomGameOver"/>.</returns>
public static int GetGameOverId<T>() where T : CustomGameOver
public static int GetGameOverId<T>()
where T : CustomGameOver
{
return GetGameOverId(typeof(T));
}
+2 -2
View File
@@ -298,8 +298,8 @@ public abstract class AbstractGameMode : IOptionable
instance.closedPosition = new Vector3(xPos, yPos, instance.closedPosition.z);
instance.openPosition = new Vector3(instance.openPosition.x, yPos, instance.openPosition.z);
instance.timer = instance.open
? Mathf.Min(1f, instance.timer + Time.deltaTime / instance.animationTimeSeconds)
: Mathf.Max(0f, instance.timer - Time.deltaTime / instance.animationTimeSeconds);
? Mathf.Min(1f, instance.timer + (Time.deltaTime / instance.animationTimeSeconds))
: Mathf.Max(0f, instance.timer - (Time.deltaTime / instance.animationTimeSeconds));
Vector3 relativePos = new(
Mathf.SmoothStep(instance.closedPosition.x, instance.openPosition.x, instance.timer),
+3 -1
View File
@@ -74,7 +74,8 @@ public static class CustomGameModeManager
/// </summary>
/// <typeparam name="T">The AbstractGameMode subclass being checked.</typeparam>
/// <returns>Whether the provided mode is the current active one.</returns>
public static bool IsActiveGameMode<T>() where T : AbstractGameMode
public static bool IsActiveGameMode<T>()
where T : AbstractGameMode
{
return ActiveMode is T;
}
@@ -108,6 +109,7 @@ public static class CustomGameModeManager
{
var defaultMode = new ClassicMode();
IdToModeMap.Add(0, defaultMode);
// no need to add to game mode option as it already contains it
// because we cannot have the option be created with no values
defaultMode.ID = 0;
+10 -6
View File
@@ -19,7 +19,7 @@ namespace MiraAPI.GameModes;
public static class GameModeOption
{
/// <summary>
/// Gets the current index of the Game Mode Option
/// Gets the current index of the Game Mode Option.<br/>
/// For the value as an <see cref="AbstractGameMode"/>, see <see cref="CustomGameModeManager.ActiveMode"/>.
/// </summary>
public static int Value
@@ -38,11 +38,6 @@ public static class GameModeOption
LastValue = value;
}
}
internal static StringOption OptionBehaviour { get; set; } = null!;
[SuppressMessage("Critical Code Smell", "S2223:Non-constant static fields should not be visible", Justification = "Internal behaviour that does not need property-level validation.")]
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")] // why so many warnings???
internal static int LastValue;
internal static readonly StringNames GamemodeName = MiraLocaleManager.GetOrCreateLocaleString("Gamemode");
internal static readonly StringNames CustomName = MiraLocaleManager.GetOrCreateLocaleString("Custom");
@@ -51,6 +46,12 @@ public static class GameModeOption
[0] = MiraLocaleManager.GetOrCreateLocaleString("MiraApi.Gamemode.Classic"),
};
internal static StringOption OptionBehaviour { get; set; } = null!;
[SuppressMessage("Critical Code Smell", "S2223:Non-constant static fields should not be visible", Justification = "Internal behaviour that does not need property-level validation.")]
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")] // why so many warnings???
internal static int LastValue;
internal static void AddOption(AbstractGameMode mode)
{
if (!Values.ContainsKey(mode.ID))
@@ -110,6 +111,7 @@ public static class GameModeOption
CustomGameModeManager.GetAndSetGameMode();
HudPatches.SetGameModeText(CustomGameModeManager.GetMode(Values.ElementAt(LastValue).Key).ColoredName);
var gm = CustomGameModeManager.ActiveMode!;
if (gm != previousMode)
{
ModdedOptionsManager.AddSettingsChangeMessage(
@@ -127,6 +129,7 @@ public static class GameModeOption
}
}
}
// TODO: could make Values a dict of AbstractGameMode too
}
@@ -145,6 +148,7 @@ public static class GameModeOption
GameOptionsMenuPatch.ToggleGamemodeOptions(CustomGameModeManager.ActiveMode, __instance);
GameSettingMenu.Instance.RoleSettingsButton.gameObject.SetActive(CustomGameModeManager.ActiveMode.ShowNormalRoleSettings);
}
return false;
}
+15 -4
View File
@@ -104,6 +104,7 @@ public class HideAndSeekMode : AbstractGameMode
list2.Add(networkedPlayerInfo);
}
}
var currentGameOptions = GameOptionsManager.Instance.CurrentGameOptions;
var adjustedNumImpostors = GameOptionsManager.Instance.CurrentGameOptions.GetAdjustedNumImpostors(list2.Count);
AssignRolesForTeam(list2, currentGameOptions, RoleTeamTypes.Impostor, Math.Max(adjustedNumImpostors, 1), RoleTypes.Impostor);
@@ -204,19 +205,19 @@ public class HideAndSeekMode : AbstractGameMode
Info($"MiraAPI.Patches.Roles.LogicRoleSelectionHnsPatch - AssignRolesForTeam: Before Guaranteed Assignment");
var newImpostors = new List<NetworkedPlayerInfo>();
// Specified Seeker
if (HasImpostorPlayerID() &&
ValidateImpostorPlayerID(players) &&
!AmongUsClient.Instance.IsGamePublic)
{
// Specified Seeker
var networkedPlayerInfo = players.First(p => p.PlayerId == ImpostorPlayerID());
players.Remove(networkedPlayerInfo);
newImpostors.Add(networkedPlayerInfo);
Info($"MiraAPI.Patches.Roles.LogicRoleSelectionHnsPatch - AssignRolesForTeam: Seeker is {networkedPlayerInfo.PlayerName}, ID: {networkedPlayerInfo.PlayerId}");
}
// Random Seeker
else
{
// Random Seeker
var num2 = 0;
while (num2 < teamMax && players.Count > 0)
{
@@ -226,6 +227,7 @@ public class HideAndSeekMode : AbstractGameMode
{
pseudoRandomList.PickRandom();
}
var networkedPlayerInfo = pseudoRandomList.PickRandom();
players.Remove(networkedPlayerInfo);
newImpostors.Add(networkedPlayerInfo);
@@ -233,6 +235,7 @@ public class HideAndSeekMode : AbstractGameMode
Info($"MiraAPI.Patches.Roles.LogicRoleSelectionHnsPatch - AssignRolesForTeam: Seeker is {networkedPlayerInfo.PlayerName}, ID: {networkedPlayerInfo.PlayerId}");
}
}
Info($"MiraAPI.Patches.Roles.LogicRoleSelectionHnsPatch - AssignRolesForTeam: After Guaranteed Assignment");
AddGuaranteedRoles(guaranteedRoles, opts, list);
@@ -301,6 +304,7 @@ public class HideAndSeekMode : AbstractGameMode
{
introCutscene.ImpostorTitle.text = impostor.Data.Role.GetRoleName();
}
PoolablePlayer? playerSlot = null;
if (impostor != null)
{
@@ -397,6 +401,7 @@ public class HideAndSeekMode : AbstractGameMode
impostor.cosmetics.SetBodyCosmeticsVisible(false);
}
}
ShipStatus.Instance.StartSFX();
HnsMusicHandler.Instance.OnGameStart();
HnsDangerMeter.Instance.OnGameStart();
@@ -429,6 +434,7 @@ public class HideAndSeekMode : AbstractGameMode
mapOptions.IncludeDeadBodies = false;
mapOptions.ShowLivePlayerPosition = false;
}
return mapOptions;
}
@@ -441,14 +447,17 @@ public class HideAndSeekMode : AbstractGameMode
{
instance.Manager.RpcEndGame(GameOverReason.ImpostorDisconnect, !DataManager.Player.Ads.HasPurchasedAdRemoval);
}
if (players.Any(x => !x.Data.Role.IsImpostor))
{
if (HideAndSeekHudHelper.Instance.AllTimersExpired())
{
instance.Manager.RpcEndGame(GameOverReason.HideAndSeek_CrewmatesByTimer, !DataManager.Player.Ads.HasPurchasedAdRemoval);
}
return;
}
instance.Manager.RpcEndGame(GameOverReason.HideAndSeek_ImpostorsByKills, !DataManager.Player.Ads.HasPurchasedAdRemoval);
}
@@ -462,10 +471,12 @@ public class HideAndSeekMode : AbstractGameMode
{
return PlayerBodyTypes.Horse;
}
if (AprilFoolsMode.ShouldLongAround())
{
return PlayerBodyTypes.Long;
}
return PlayerBodyTypes.Normal;
}
@@ -507,8 +518,8 @@ public class HideAndSeekMode : AbstractGameMode
instance.closedPosition = new Vector3(xPos, yPos, instance.closedPosition.z);
instance.openPosition = new Vector3(instance.openPosition.x, yPos, instance.openPosition.z);
instance.timer = instance.open
? Mathf.Min(1f, instance.timer + Time.deltaTime / instance.animationTimeSeconds)
: Mathf.Max(0f, instance.timer - Time.deltaTime / instance.animationTimeSeconds);
? Mathf.Min(1f, instance.timer + (Time.deltaTime / instance.animationTimeSeconds))
: Mathf.Max(0f, instance.timer - (Time.deltaTime / instance.animationTimeSeconds));
Vector3 relativePos = new(
Mathf.SmoothStep(instance.closedPosition.x, instance.openPosition.x, instance.timer),
+6 -3
View File
@@ -35,7 +35,7 @@ public abstract class AbstractOptionGroup
/// Gets a value indicating whether the group should be shown in the modifiers menu.
/// </summary>
// Completed: make this not a boolean
[Obsolete("Use ParentMenu instead.")]
[Obsolete("Use ParentMenu instead.", true)]
[SuppressMessage("Info Code Smell", "S1133:Deprecated code should be removed", Justification = "Retained.")]
public virtual bool ShowInModifiersMenu => false;
@@ -76,7 +76,8 @@ public abstract class AbstractOptionGroup
/// Base class for option groups. An option group is a collection of options that are displayed together in the options menu.
/// </summary>
/// <typeparam name="T">The type of the optionable that this group contains.</typeparam>
public abstract class AbstractOptionGroup<T> : AbstractOptionGroup where T : IOptionable
public abstract class AbstractOptionGroup<T> : AbstractOptionGroup
where T : IOptionable
{
/// <inheritdoc />
public override Type OptionableType => typeof(T);
@@ -95,6 +96,7 @@ public abstract class AbstractOptionGroup<T> : AbstractOptionGroup where T : IOp
{
return MenuCategory.Roles;
}
return MenuCategory.Game;
}
}
@@ -104,7 +106,8 @@ public abstract class AbstractOptionGroup<T> : AbstractOptionGroup where T : IOp
/// Base class for option groups. An option group is a collection of options that are displayed together in the options menu.
/// </summary>
/// <typeparam name="T">The custom role that the group is for.</typeparam>
public abstract class AbstractRoleOptionGroup<T> : AbstractOptionGroup<T> where T : ICustomRole
public abstract class AbstractRoleOptionGroup<T> : AbstractOptionGroup<T>
where T : ICustomRole
{
/// <inheritdoc />
public override Type OptionableType => typeof(T);
@@ -43,7 +43,8 @@ public class ModdedEnumOptionAttribute(string title, Type enumType, string[]? va
/// <typeparam name="T">The enum type.</typeparam>
[AttributeUsage(AttributeTargets.Property)]
public class ModdedEnumOptionAttribute<T>(string title, string[]? values = null)
: ModdedOptionAttribute(title) where T : Enum
: ModdedOptionAttribute(title)
where T : Enum
{
internal override IModdedOption CreateOption(object? value, PropertyInfo property)
{
@@ -1,8 +1,8 @@
using MiraAPI.GameOptions.OptionTypes;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MiraAPI.GameOptions.OptionTypes;
namespace MiraAPI.GameOptions.Attributes;
@@ -52,6 +52,7 @@ public sealed class ModdedOptionVisibilityAttribute(Type? holderType = null, str
return () => (bool)vProperty.GetValue(instanceGet?.Invoke())!;
}
if (member is MethodInfo vMethod)
{
if (vMethod.ReturnType != typeof(bool))
@@ -114,6 +115,7 @@ public sealed class ModdedOptionVisibilityAttribute(Type? holderType = null, str
{
return _ => (bool)vProperty.GetValue(instanceGet?.Invoke())!;
}
if (indexParams[0].ParameterType != typeof(int))
{
Error($"Indexer {memberName}'s parameter is not an int.");
@@ -122,6 +124,7 @@ public sealed class ModdedOptionVisibilityAttribute(Type? holderType = null, str
return i => (bool)vProperty.GetValue(instanceGet?.Invoke(), [i])!;
}
if (member is MethodInfo vMethod)
{
if (vMethod.ReturnType != typeof(bool))
@@ -141,6 +144,7 @@ public sealed class ModdedOptionVisibilityAttribute(Type? holderType = null, str
{
return _ => (bool)vMethod.Invoke(instanceGet?.Invoke(), null)!;
}
if (paramList[0].ParameterType != typeof(int))
{
Error($"Method {memberName}'s parameter is not an int.");
@@ -179,6 +183,7 @@ public sealed class ModdedOptionVisibilityAttribute(Type? holderType = null, str
instanceGet = () => instanceProp.GetValue(null)!;
}
}
MemberInfo? member = type.GetMember(memberName, flags).FirstOrDefault();
if (instanceGet != null)
{
@@ -189,6 +194,7 @@ public sealed class ModdedOptionVisibilityAttribute(Type? holderType = null, str
instanceGet = null;
}
}
return member;
}
#pragma warning restore S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
@@ -1,7 +1,7 @@
using MiraAPI.GameOptions.OptionTypes;
using System;
using System;
using System.Collections;
using System.Reflection;
using MiraAPI.GameOptions.OptionTypes;
namespace MiraAPI.GameOptions.Attributes;
@@ -41,7 +41,8 @@ public class ModdedEnumOptionListAttribute(string title, Type enumType, string[]
/// <typeparam name="T">The enum type.</typeparam>
[AttributeUsage(AttributeTargets.Property)]
public class ModdedEnumOptionListAttribute<T>(string title, string[]? values = null)
: ModdedOptionListAttribute(title) where T : Enum
: ModdedOptionListAttribute(title)
where T : Enum
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
@@ -1,8 +1,8 @@
using MiraAPI.GameOptions.OptionTypes;
using MiraAPI.Utilities;
using System;
using System;
using System.Collections;
using System.Reflection;
using MiraAPI.GameOptions.OptionTypes;
using MiraAPI.Utilities;
namespace MiraAPI.GameOptions.Attributes;
@@ -85,8 +85,10 @@ public abstract class ModdedOptionListAttribute(string title) : PropertyOptionAt
{
return string.Format(Title, index);
}
Error("ModdedOptionList Title cannot contain more than the first parameter for formatting.");
}
return Title + index;
}
}
@@ -1,7 +1,7 @@
using MiraAPI.GameOptions.OptionTypes;
using System;
using System;
using System.Collections;
using System.Reflection;
using MiraAPI.GameOptions.OptionTypes;
namespace MiraAPI.GameOptions.Attributes;
+11 -19
View File
@@ -48,24 +48,14 @@ public static class ModdedOptionsManager
public static void AddSettingsChangeMessage(NotificationPopper notif, StringNames key, string value, Color textColor, TMP_SpriteAsset? sprite, bool playSound = true)
{
var text = textColor.ToTextColor();
var item = sprite != null
? TranslationController.Instance.GetString(
var translatedKey = TranslationController.Instance.GetString(key);
var fontTag = "<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">";
var spritePrefix = sprite != null ? $"<sprite name=\"{sprite.name}\">" : string.Empty;
var item = TranslationController.Instance.GetString(
StringNames.LobbyChangeSettingNotification,
string.Concat(
"<sprite name=\"",
sprite.name,
"\"><font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">",
text,
TranslationController.Instance.GetString(key),
"</color></font>"),
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" + value + "</font>"
)
: TranslationController.Instance.GetString(
StringNames.LobbyChangeSettingNotification,
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" +
text +
TranslationController.Instance.GetString(key) + "</color></font>",
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" + value + "</font>");
$"{spritePrefix}{fontTag}{text}{translatedKey}</color></font>",
$"{fontTag}{value}</font>");
notif.SettingsChangeMessageLogic(key, item, playSound);
}
@@ -110,6 +100,7 @@ public static class ModdedOptionsManager
GameModeOptionGroups.Add(group.OptionableType, [group]);
}
}
pluginInfo.InternalOptionGroups.Add(group);
RegisterGroupInternal(group, type);
@@ -119,8 +110,7 @@ public static class ModdedOptionsManager
[SuppressMessage(
"Major Code Smell",
"S3011:Reflection should not be used to increase accessibility of classes, methods, or fields",
Justification = "Dynamic singleton initialization requires reflection to bypass the private field access modifier because the type is only known at runtime."
)]
Justification = "Dynamic singleton initialization requires reflection to bypass the private field access modifier because the type is only known at runtime.")]
private static void RegisterGroupInternal(AbstractOptionGroup group, Type type)
{
Groups.Add(group);
@@ -248,6 +238,7 @@ public static class ModdedOptionsManager
Error($"Failed to get option for {property.Name}");
return;
}
if (propertyList.Count != optionList.Count)
{
Error("Mismatch in count between values and created options.");
@@ -285,6 +276,7 @@ public static class ModdedOptionsManager
{
option.Visible = () => visibilityFunc(i);
}
RegisterOption(option, group, property.Name + i, pluginInfo);
}
}
+2 -1
View File
@@ -7,7 +7,8 @@ namespace MiraAPI.GameOptions;
/// Singleton for <see cref="AbstractOptionGroup"/>s.
/// </summary>
/// <typeparam name="T">The option group type.</typeparam>
public static class OptionGroupSingleton<T> where T : AbstractOptionGroup
public static class OptionGroupSingleton<T>
where T : AbstractOptionGroup
{
private static T? _instance;
@@ -11,7 +11,7 @@ namespace MiraAPI.GameOptions;
/// </summary>
public record struct OptionNotifConfiguration
{
[Obsolete("Default constructor is not supported. Please use the constructor that takes an AbstractOptionGroup parameter.")]
[Obsolete("Default constructor is not supported. Please use the constructor that takes an AbstractOptionGroup parameter.", true)]
[SuppressMessage("Info Code Smell", "S1133:Deprecated code should be removed", Justification = "Will not be removed, as this throws instead.")]
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member (Justification: Read above.)
public OptionNotifConfiguration()
@@ -28,7 +28,8 @@ public class ModdedEnumOption : ModdedOption<int>
/// <param name="enumType">The <see cref="Enum"/> type.</param>
/// <param name="values">An option list of string values to use in place of the <see langword="enum"/> name.</param>
/// <param name="includeInPreset">Whether to include this option in the preset or not.</param>
public ModdedEnumOption(string title, int defaultValue, Type enumType, string[]? values = null, bool includeInPreset = true) : base(title, defaultValue, includeInPreset)
public ModdedEnumOption(string title, int defaultValue, Type enumType, string[]? values = null, bool includeInPreset = true)
: base(title, defaultValue, includeInPreset)
{
Values = values ?? Enum.GetNames(enumType);
@@ -111,7 +112,8 @@ public class ModdedEnumOption : ModdedOption<int>
/// An option for selecting an <see langword="enum"/> value.
/// </summary>
/// <typeparam name="T">The <see cref="Enum"/> type.</typeparam>
public class ModdedEnumOption<T> : ModdedOption<T> where T : Enum
public class ModdedEnumOption<T> : ModdedOption<T>
where T : Enum
{
/// <summary>
/// Gets the string values of the <see langword="enum"/>.
@@ -125,7 +127,8 @@ public class ModdedEnumOption<T> : ModdedOption<T> where T : Enum
/// <param name="defaultValue">The default value as an <see langword="int"/>.</param>
/// <param name="values">An option list of string values to use in place of the <see langword="enum"/> name.</param>
/// <param name="includeInPreset">Whether to include this option in the preset or not.</param>
public ModdedEnumOption(string title, T defaultValue, string[]? values = null, bool includeInPreset = true) : base(title, defaultValue, includeInPreset)
public ModdedEnumOption(string title, T defaultValue, string[]? values = null, bool includeInPreset = true)
: base(title, defaultValue, includeInPreset)
{
Values = values ?? Enum.GetNames(typeof(T));
@@ -77,7 +77,8 @@ public class ModdedNumberOption : ModdedOption<float>
MiraNumberSuffixes suffixType,
string? formatString = null,
bool halfIncrements = false,
bool includeInPreset = true) : base(title, defaultValue, includeInPreset)
bool includeInPreset = true)
: base(title, defaultValue, includeInPreset)
{
Min = min;
Max = max;
@@ -130,7 +131,8 @@ public class ModdedNumberOption : ModdedOption<float>
MiraNumberSuffixes suffixType,
string? formatString = null,
bool zeroInfinity = false,
bool includeInPreset = true) : base(title, defaultValue, includeInPreset)
bool includeInPreset = true)
: base(title, defaultValue, includeInPreset)
{
Min = min;
Max = max;
@@ -125,6 +125,7 @@ public abstract class ModdedOption<T> : IModdedOption
Error($"Attempted to save {Title} to preset, but ConfigDefinition is null.");
return;
}
Bind(presetConfig);
presetConfig[ConfigDefinition].BoxedValue = saveDefault ? DefaultValue : Value;
}
@@ -9,7 +9,8 @@ namespace MiraAPI.GameOptions.OptionTypes;
/// Represents a modded option list.
/// </summary>
/// <typeparam name="T">The type of options.</typeparam>
public class ModdedOptionList<T> : IModdedOptionList where T : IModdedOption
public class ModdedOptionList<T> : IModdedOptionList
where T : IModdedOption
{
/// <inheritdoc/>
public int Count { get; }
@@ -34,7 +34,8 @@ public class ModdedPlayerOption : ModdedOption<int>
/// </summary>
/// <param name="title">The title of the option.</param>
/// <param name="allowNone">Whether the option includes a none option. If None is selected, value will return -1.</param>
public ModdedPlayerOption(string title, bool allowNone = true) : base(title, allowNone ? -1 : 0, false)
public ModdedPlayerOption(string title, bool allowNone = true)
: base(title, allowNone ? -1 : 0, false)
{
Data = ScriptableObject.CreateInstance<PlayerSelectionGameSetting>();
var data = (PlayerSelectionGameSetting)Data;
@@ -36,6 +36,7 @@ public class ModdedStringOption : ModdedOption<string>
{
return Array.IndexOf(Values, value);
}
Info($"Cannot find a valid index for {value}. Returning -1 instead. Values: {string.Join(", ", Values)}");
return -1;
}
@@ -79,12 +80,14 @@ public class ModdedStringOption : ModdedOption<string>
{
Error("StringOption is null.");
}
Warning("OptionBehaviour is valid");
}
else
{
Error("OptionBehaviour is null.");
}
Warning("Data is valid");
}
else
@@ -100,7 +103,8 @@ public class ModdedStringOption : ModdedOption<string>
/// <param name="defaultValue">The default value as a string.</param>
/// <param name="values">An option list of string values to use.</param>
/// <param name="includeInPreset">Whether to include this option in the preset or not.</param>
public ModdedStringOption(string title, string defaultValue, string[] values, bool includeInPreset = true) : base(title, defaultValue, includeInPreset)
public ModdedStringOption(string title, string defaultValue, string[] values, bool includeInPreset = true)
: base(title, defaultValue, includeInPreset)
{
Values = values;
Data = ScriptableObject.CreateInstance<StringGameSetting>();
@@ -17,7 +17,8 @@ public class ModdedToggleOption : ModdedOption<bool>
/// <param name="title">The option title.</param>
/// <param name="defaultValue">The default value.</param>
/// <param name="includeInPreset">Whether to include this option in the preset or not.</param>
public ModdedToggleOption(string title, bool defaultValue, bool includeInPreset = true) : base(title, defaultValue, includeInPreset)
public ModdedToggleOption(string title, bool defaultValue, bool includeInPreset = true)
: base(title, defaultValue, includeInPreset)
{
Data = ScriptableObject.CreateInstance<CheckboxGameSetting>();
+1
View File
@@ -1,2 +1,3 @@
global using static Reactor.Utilities.Logger<MiraAPI.MiraApiPlugin>;
global using CppCollections = Il2CppSystem.Collections.Generic;
global using CppIEnumerator = Il2CppSystem.Collections.IEnumerator;
@@ -26,8 +26,9 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr)
private AudioClip finalHideAlertSfx;
private AudioClip finalHideCountdownSfx;
[SuppressMessage("Style", "IDE0052:Remove unread private members", Justification = "Ignore for now; tentative code.")]
// ReSharper disable once NotAccessedField.Local (Justification: Read above.)
[SuppressMessage("Style", "IDE0052:Remove unread private members", Justification = "Ignore for now; tentative code.")]
private AudioClip taskFinishedSound;
// private const int SECONDS_TO_BEEP = 10;
@@ -166,11 +167,13 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr)
HudManager.Instance.TaskPanel.SetTaskText(string.Empty);
return;
}
var data = PlayerControl.LocalPlayer.Data;
if (data == null)
{
return;
}
var flag = data.Role != null && data.Role.IsImpostor;
HudManager.Instance.tasksString.Clear();
if (PlayerControl.LocalPlayer.myTasks == null || PlayerControl.LocalPlayer.myTasks.Count == 0)
@@ -190,20 +193,25 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr)
playerTask.AppendTaskText(HudManager.Instance.tasksString);
break;
}
playerTask.AppendTaskText(HudManager.Instance.tasksString);
}
}
if (data.Role != null)
{
data.Role.AppendTaskHint(HudManager.Instance.tasksString);
}
if (HideCountdown > 0f)
{
HideCountdown -= num;
HudManager.Instance.tasksString.Append("\n\n" + ((int)HideCountdown));
}
HudManager.Instance.tasksString.TrimEnd();
}
HudManager.Instance.TaskPanel.SetTaskText(HudManager.Instance.tasksString.ToString());
}
+24 -24
View File
@@ -21,6 +21,26 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr)
/// </summary>
public static HnsMusicHandler Instance { get; private set; }
private static readonly Dictionary<LogicHnSMusic.HideAndSeekMusicTrack, string> MusicNames = new()
{
{
LogicHnSMusic.HideAndSeekMusicTrack.Normal,
"HnS_Music_Normal"
},
{
LogicHnSMusic.HideAndSeekMusicTrack.Task,
"HnS_Music_Task"
},
{
LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel1,
"HnS_Music_DangerLevel1"
},
{
LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel2,
"HnS_Music_DangerLevel2"
},
};
private HideAndSeekMusicCollection musicCollection;
private float lastMusicSyncTime;
@@ -45,26 +65,6 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr)
private float musicLerpSpeed = 5f;
private readonly Dictionary<LogicHnSMusic.HideAndSeekMusicTrack, string> musicNames = new()
{
{
LogicHnSMusic.HideAndSeekMusicTrack.Normal,
"HnS_Music_Normal"
},
{
LogicHnSMusic.HideAndSeekMusicTrack.Task,
"HnS_Music_Task"
},
{
LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel1,
"HnS_Music_DangerLevel1"
},
{
LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel2,
"HnS_Music_DangerLevel2"
},
};
private void Awake()
{
Instance = this;
@@ -94,7 +94,7 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr)
if (normalSource == null)
{
normalSource =
SoundManager.Instance.GetNamedSfxSource(musicNames[LogicHnSMusic.HideAndSeekMusicTrack.Normal]);
SoundManager.Instance.GetNamedSfxSource(MusicNames[LogicHnSMusic.HideAndSeekMusicTrack.Normal]);
}
normalSource.outputAudioMixerGroup = SoundManager.Instance.MusicChannel;
@@ -103,7 +103,7 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr)
if (taskSource == null)
{
taskSource =
SoundManager.Instance.GetNamedSfxSource(musicNames[LogicHnSMusic.HideAndSeekMusicTrack.Task]);
SoundManager.Instance.GetNamedSfxSource(MusicNames[LogicHnSMusic.HideAndSeekMusicTrack.Task]);
}
taskSource.outputAudioMixerGroup = SoundManager.Instance.MusicChannel;
@@ -114,7 +114,7 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr)
{
dangerLevel1Source =
SoundManager.Instance.GetNamedSfxSource(
musicNames[LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel1]);
MusicNames[LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel1]);
}
dangerLevel1Source.outputAudioMixerGroup = SoundManager.Instance.MusicChannel;
@@ -125,7 +125,7 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr)
{
dangerLevel2Source =
SoundManager.Instance.GetNamedSfxSource(
musicNames[LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel2]);
MusicNames[LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel2]);
}
dangerLevel2Source.outputAudioMixerGroup = SoundManager.Instance.MusicChannel;
+4 -3
View File
@@ -209,6 +209,7 @@ public abstract class CustomActionButton
Keybind.OnActivate(() =>
{
if (!Enabled(PlayerControl.LocalPlayer.Data.Role)) return;
// Invoke the generic button click event.
var genericEvent = new MiraButtonClickEvent(this);
MiraEventManager.InvokeEvent(genericEvent);
@@ -248,8 +249,7 @@ public abstract class CustomActionButton
Helpers.CreateKeybindIcon(
Button.gameObject,
Keybind.CurrentKey,
new Vector3(0.4f, 0.45f, -9f)
);
new Vector3(0.4f, 0.45f, -9f));
KeybindText = KeybindIcon.transform.GetChild(0).GetComponent<TextMeshPro>();
HudManagerPatches.ModdedKeybindIcons.Add(KeybindText);
Button.usesRemainingSprite.transform.localPosition = new(-0.341f, 0.45f, -0.1f);
@@ -584,7 +584,8 @@ public abstract class CustomActionButton
/// Custom action button that has a target <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of the target object.</typeparam>
public abstract class CustomActionButton<T> : CustomActionButton where T : MonoBehaviour
public abstract class CustomActionButton<T> : CustomActionButton
where T : MonoBehaviour
{
/// <summary>
/// Gets or sets the target <typeparamref name="T"/> of the button.
+1 -2
View File
@@ -35,8 +35,7 @@ public static class CustomButtonManager
[SuppressMessage(
"Major Code Smell",
"S3011:Reflection should not be used to increase accessibility of classes, methods, or fields",
Justification = "Dynamic singleton initialization requires reflection to bypass the private field access modifier because the type is only known at runtime."
)]
Justification = "Dynamic singleton initialization requires reflection to bypass the private field access modifier because the type is only known at runtime.")]
internal static bool RegisterButton(Type buttonType, MiraPluginInfo pluginInfo)
{
if (!buttonType.IsAssignableTo(typeof(CustomActionButton)) || Activator.CreateInstance(buttonType) is not CustomActionButton button)
+2 -1
View File
@@ -7,7 +7,8 @@ namespace MiraAPI.Hud;
/// A utility class to get the instance of a <see cref="CustomActionButton"/>.
/// </summary>
/// <typeparam name="T">The type of the button you are trying to access.</typeparam>
public static class CustomButtonSingleton<T> where T : CustomActionButton
public static class CustomButtonSingleton<T>
where T : CustomActionButton
{
private static T? _instance;
+1
View File
@@ -112,6 +112,7 @@ public class CustomPlayerMenu(IntPtr il2CppPtr) : Minigame(il2CppPtr)
potentialVictims.Add(shapeshifterPanel);
list2.Add(shapeshifterPanel.Button);
}
ControllerManager.Instance.OpenOverlayMenu(name, backButton, defaultButtonSelected, list2);
}
}
+3
View File
@@ -68,6 +68,7 @@ internal sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr)
{
return;
}
UpdateSubmergedButtons(instance);
}
@@ -122,6 +123,7 @@ internal sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr)
listButton.GetComponent<AspectPosition>().Destroy();
listButton.localPosition = new Vector3(0, 0, 0);
}
settingsButton.transform.SetAsLastSibling();
chatButton.transform.SetParent(UiTopRight.transform, false);
instance.Chat.chatButton = chatButton.GetComponent<PassiveButton>();
@@ -182,6 +184,7 @@ internal sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr)
oldPos = ModifierDisplayObject.transform.GetChild(1).localPosition;
ModifierDisplayObject.transform.GetChild(1).localPosition = new Vector3(-0.45f, 0.3f, oldPos.z);
}
MiraApiSettings.SetUpButtonPositions();
}
+2 -1
View File
@@ -8,7 +8,8 @@ namespace MiraAPI.Hud;
/// <see cref="CustomActionButton"/> that has multiple target objects.
/// </summary>
/// <typeparam name="T">The type of the target objects.</typeparam>
public abstract class MultiTargetButton<T> : CustomActionButton where T : MonoBehaviour
public abstract class MultiTargetButton<T> : CustomActionButton
where T : MonoBehaviour
{
/// <summary>
/// Gets or sets the list of targets of the button.
+1
View File
@@ -70,6 +70,7 @@ public static class KeybindUtils
var used = KeybindManager.Keybinds.Exists(e => e.DefaultKey == key);
if (!used) return key;
}
return KeyboardKeyCode.None;
}
}
+2 -1
View File
@@ -6,7 +6,8 @@ namespace MiraAPI.Keybinds;
/// Singleton for getting a <see cref="VanillaKeybind"/> by <see cref="ActionButton"/>.
/// </summary>
/// <typeparam name="T"><see cref="ActionButton"/> type.</typeparam>
public static class VanillaKeybinding<T> where T : ActionButton
public static class VanillaKeybinding<T>
where T : ActionButton
{
[SuppressMessage("Major Code Smell", "S2743:Static fields should not be used in generic types", Justification = "The instance holds a reference to the button that defines the class's type parameter.")]
private static VanillaKeybind? _instance;
@@ -14,8 +14,8 @@ namespace MiraAPI.LocalSettings.Attributes;
public class LocalEnumSettingAttribute(
string? name = null,
string? description = null,
string[]? names = null
) : LocalSettingAttribute(name, description)
string[]? names = null)
: LocalSettingAttribute(name, description)
{
private readonly string? _name = name;
private readonly string? _description = description;
@@ -24,8 +24,8 @@ public class LocalNumberSettingAttribute(
float max = 5,
float increment = 1,
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None,
string? formatString = null
) : LocalSettingAttribute(name, description)
string? formatString = null)
: LocalSettingAttribute(name, description)
{
private readonly string? _name = name;
private readonly string? _description = description;
@@ -12,9 +12,9 @@ namespace MiraAPI.LocalSettings.Attributes;
public abstract class LocalSettingAttribute(
#pragma warning disable CS9113 // Parameter is unread (Justification: No idea why they exist, but they probably do for a reason unknown to me.)
string? name = null,
string? description = null
string? description = null)
#pragma warning restore CS9113 // Parameter is unread
) : Attribute
: Attribute
{
/// <summary>
/// Returns the created <see cref="ILocalSetting"/> object.
@@ -26,8 +26,8 @@ public class LocalSliderSettingAttribute(
bool displayValue = false,
string? formatString = null,
bool roundValue = false,
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None
) : LocalSettingAttribute(name, description)
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None)
: LocalSettingAttribute(name, description)
{
private readonly string? _name = name;
private readonly string? _description = description;
@@ -12,8 +12,8 @@ namespace MiraAPI.LocalSettings.Attributes;
[AttributeUsage(AttributeTargets.Property)]
public class LocalToggleSettingAttribute(
string? name = null,
string? description = null
) : LocalSettingAttribute(name, description)
string? description = null)
: LocalSettingAttribute(name, description)
{
private readonly string? _name = name;
private readonly string? _description = description;
@@ -73,6 +73,7 @@ public class LocalSettingsButton(string text, Action onClick)
offset += 0.5f;
order = 1;
}
if (last)
offset += 0.6f;
@@ -18,8 +18,7 @@ public static class LocalSettingsManager
[SuppressMessage(
"Major Code Smell",
"S3011:Reflection should not be used to increase accessibility of classes, methods, or fields",
Justification = "Dynamic singleton initialization requires reflection to bypass the private field access modifier because the type is only known at runtime."
)]
Justification = "Dynamic singleton initialization requires reflection to bypass the private field access modifier because the type is only known at runtime.")]
internal static bool RegisterTab(Type type, BasePlugin pluginInfo)
{
if (Activator.CreateInstance(type, pluginInfo.Config) is not LocalSettingsTab tab)
@@ -38,6 +37,7 @@ public static class LocalSettingsManager
{
AvailableTabs.Add(tab);
}
TypeToTab.Add(type, tab);
typeof(LocalSettingsTabSingleton<>).MakeGenericType(type)
@@ -93,6 +93,7 @@ public abstract class LocalSettingsTab(ConfigFile config)
{
setting.RefreshOption();
}
foreach (var button in Buttons)
{
button.RefreshButton();
@@ -7,7 +7,8 @@ namespace MiraAPI.LocalSettings;
/// Singleton for <see cref="LocalSettingsTab"/>s.
/// </summary>
/// <typeparam name="T">The settings tab type.</typeparam>
public static class LocalSettingsTabSingleton<T> where T : LocalSettingsTab
public static class LocalSettingsTabSingleton<T>
where T : LocalSettingsTab
{
private static T? _instance;
@@ -63,6 +63,7 @@ public class LocalEnumSetting(
highlight.color = Tab!.TabAppearance.EnumHoverColor;
highlight.gameObject.SetActive(false);
}
toggleComp.Destroy();
if (last && order == 1)
@@ -100,6 +101,7 @@ public class LocalEnumSetting(
{
tmp.text = Description;
}
highlight?.gameObject.SetActive(true);
}));
button.OnMouseOut.AddListener((UnityAction)(() =>
@@ -116,6 +118,7 @@ public class LocalEnumSetting(
offset += 0.5f;
order = 1;
}
if (last)
offset += 0.6f;
@@ -73,6 +73,7 @@ public class LocalNumberSetting(
highlight.color = Tab!.TabAppearance.NumberHoverColor;
highlight.gameObject.SetActive(false);
}
toggleComp.Destroy();
if (last && order == 1)
@@ -110,6 +111,7 @@ public class LocalNumberSetting(
{
tmp.text = Description;
}
highlight?.gameObject.SetActive(true);
}));
button.OnMouseOut.AddListener((UnityAction)(() =>
@@ -126,6 +128,7 @@ public class LocalNumberSetting(
offset += 0.5f;
order = 1;
}
if (last)
offset += 0.6f;
@@ -20,8 +20,8 @@ public class LocalToggleSetting(
Type tab,
ConfigEntryBase configEntry,
string? name = null,
string? description = null
) : LocalSettingBase<bool>(tab, configEntry, name, description)
string? description = null)
: LocalSettingBase<bool>(tab, configEntry, name, description)
{
private ToggleButtonBehaviour _toggle;
@@ -79,6 +79,7 @@ public class LocalToggleSetting(
offset += 0.5f;
order = 1;
}
if (last)
offset += 0.6f;
@@ -69,6 +69,7 @@ public class MeetingAbilityBehaviour : MonoBehaviour
Error($"Could not initialize MeetingButtonBehaviour for {Button.GetType().Name}, Destroying...");
Destroy(this);
}
_init = true;
Button = but;
CooldownText = Instantiate(HudManager.Instance.KillButton.cooldownTimerText, transform);
@@ -113,6 +114,7 @@ public class MeetingAbilityBehaviour : MonoBehaviour
CooldownText.text = _button.Timer.ToString(_button.CooldownTimerFormatString, NumberFormatInfo.InvariantInfo);
UsesText.text = string.Empty;
}
SetFillUp(_button.Timer, _button.InitialCooldown);
}
@@ -336,6 +336,7 @@ public abstract class MeetingActionButton
{
Button!.SetDisabled();
}
Button.SetCooldownFormat(Timer, Cooldown, CooldownTimerFormatString);
Button.SetCoolDown(Timer, Cooldown);
}
@@ -57,6 +57,7 @@ public static class MeetingButtonManager
{
ability.UsesLeft = ability.MaxUses;
}
foreach (var ability in UntargetedButtons.Where(x => x.UsesMode == MeetingButtonUsesMode.PerGame))
{
ability.UsesLeft = ability.MaxUses;
@@ -101,6 +102,7 @@ public static class MeetingButtonManager
var btn = ability.CreateButton(playerVoteArea);
btn.transform.SetParent(playerVoteArea.Buttons.transform);
}
var btn2 = ability.CreateButton(meetingHud.SkipVoteButton);
btn2.transform.SetParent(meetingHud.SkipVoteButton.Buttons.transform);
@@ -112,10 +114,12 @@ public static class MeetingButtonManager
Error($"Failed to create targeted meeting button {ability.Name}: {e.Message}");
}
}
foreach (var playerVoteArea in meetingHud.playerStates)
{
playerVoteArea.CancelButton.transform.SetAsFirstSibling();
}
meetingHud.SkipVoteButton.CancelButton.transform.SetAsFirstSibling();
}
}
@@ -40,6 +40,7 @@ public abstract class MultiTargetMeetingButton : TargetedMeetingButton
HandleFinish();
return;
}
OnSelect(playerVoteArea, toggle);
}
@@ -53,6 +54,7 @@ public abstract class MultiTargetMeetingButton : TargetedMeetingButton
{
button.Renderer.sprite = Sprite.LoadAsset();
}
Timer = Cooldown;
UsesLeft -= 1;
OnFinish();
@@ -7,7 +7,8 @@ namespace MiraAPI.MeetingAbilities;
/// A utility class to get the instance of a <see cref="TargetedMeetingButton"/>.
/// </summary>
/// <typeparam name="T">The type of the button you are trying to access.</typeparam>
public static class TargetedMeetingButtonSingleton<T> where T : TargetedMeetingButton
public static class TargetedMeetingButtonSingleton<T>
where T : TargetedMeetingButton
{
private static T? _instance;
+3 -3
View File
@@ -1,6 +1,4 @@
global using static Reactor.Utilities.Logger<MiraAPI.MiraApiPlugin>;
using System;
using System;
using System.Globalization;
using BepInEx;
using BepInEx.Configuration;
@@ -25,8 +23,10 @@ namespace MiraAPI;
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
[ReactorModFlags(ModFlags.RequireOnAllClients)]
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line (Justification: ReSharper suppression,)
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated by BepInEx.)
public partial class MiraApiPlugin : BasePlugin, IMiraPlugin
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
{
/// <summary>
/// Gets the specified Culture for string manipulations.
+6
View File
@@ -57,6 +57,7 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
HudManagerPatches.ResizeUI(1f / OldButtonScaleFactor);
HudManagerPatches.ResizeUI(ButtonUIFactorSlider.Value);
}
OldButtonScaleFactor = ButtonUIFactorSlider.Value;
}
else if (configEntry == TopRightButtonsFactorSlider)
@@ -65,6 +66,7 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
{
ResizeUI(TopRightButtonsFactorSlider.Value);
}
OldUiButtonScaleFactor = TopRightButtonsFactorSlider.Value;
}
else if (configEntry == WikiOnBottomRow)
@@ -134,6 +136,7 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
{
continue;
}
if (button.transform.name.Contains("Friends List Button"))
{
button.gameObject.transform.localScale = new Vector3(0.2675f * actualScaleVal, 0.2675f * actualScaleVal, 1);
@@ -148,6 +151,7 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
{
baseGrid.ArrangeChilds();
}
baseAspect.AdjustPosition();
}
@@ -163,6 +167,7 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
{
continue;
}
if (button.transform.name.Contains("Modifiers"))
{
button.gameObject.transform.localScale = new Vector3(0.65f * scaleFactor, 0.65f * scaleFactor, 1);
@@ -177,6 +182,7 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config)
{
extraGrid.ArrangeChilds();
}
extraAspect.AdjustPosition();
}
+2 -2
View File
@@ -41,8 +41,8 @@ public abstract class BaseModifier : IOptionable
/// </summary>
public MiraPluginInfo ParentMod => Array.Find(
MiraPluginManager.Instance.RegisteredPlugins,
x => x.InternalModifiers.Exists(y => y.TypeId == TypeId)
) ?? throw new InvalidOperationException("Modifier is not registered.");
x => x.InternalModifiers.Exists(y => y.TypeId == TypeId))
?? throw new InvalidOperationException("Modifier is not registered.");
/// <summary>
/// Gets the modifier name.
+31 -17
View File
@@ -26,6 +26,10 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
[HideFromIl2Cpp]
public ImmutableList<BaseModifier> ActiveModifiers { get; private set; } = ImmutableList<BaseModifier>.Empty;
private readonly List<BaseModifier> _toRemove = [];
private readonly List<BaseModifier> _toAdd = [];
private ModifierDisplayComponent? ModifierDisplay { get; set; }
[HideFromIl2Cpp]
@@ -33,10 +37,6 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
private PlayerControl _player = null!;
private readonly List<BaseModifier> _toRemove = [];
private readonly List<BaseModifier> _toAdd = [];
internal void ClearModifiers()
{
_toRemove.AddRange(Modifiers);
@@ -171,7 +171,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the <see cref="BaseModifier"/>e.</typeparam>
/// <returns>An <see cref="IEnumerable{T}"/> of <typeparamref name="T"/>s.</returns>
[HideFromIl2Cpp]
public IEnumerable<T> GetModifiers<T>(Func<T, bool>? predicate = null) where T : BaseModifier
public IEnumerable<T> GetModifiers<T>(Func<T, bool>? predicate = null)
where T : BaseModifier
{
return ActiveModifiers.OfType<T>().Where(x => predicate == null || predicate(x));
}
@@ -210,7 +211,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the interface of the <see cref="BaseModifier"/>.</typeparam>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="BaseModifier"/>s of type <typeparamref name="T"/>.</returns>
[HideFromIl2Cpp]
public IEnumerable<T> GetModifiersOfType<T>(Func<T, bool>? predicate = null) where T : class
public IEnumerable<T> GetModifiersOfType<T>(Func<T, bool>? predicate = null)
where T : class
{
return ActiveModifiers.OfType<T>().Where(x => predicate == null || predicate(x));
}
@@ -223,7 +225,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the <see cref="BaseModifier"/>.</typeparam>
/// <returns><see langword="true"/> if the <typeparamref name="T"/> was found, <see langword="false"/> otherwise.</returns>
[HideFromIl2Cpp]
public bool TryGetModifier<T>([NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null) where T : BaseModifier
public bool TryGetModifier<T>([NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null)
where T : BaseModifier
{
modifier = GetModifier(predicate);
return modifier != null;
@@ -278,7 +281,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the interface of the <see cref="BaseModifier"/>.</typeparam>
/// <returns><see langword="true"/> if the <see cref="BaseModifier"/> of type <typeparamref name="T"/> was found, <see langword="false"/> otherwise.</returns>
[HideFromIl2Cpp]
public bool TryGetModifierOfType<T>([NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null) where T : class
public bool TryGetModifierOfType<T>([NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null)
where T : class
{
modifier = GetModifierOfType(predicate);
return modifier != null;
@@ -291,7 +295,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the <see cref="BaseModifier"/>.</typeparam>
/// <returns>The <typeparamref name="T"/> if it is found, <see langword="null"/> otherwise.</returns>
[HideFromIl2Cpp]
public T? GetModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
public T? GetModifier<T>(Func<T, bool>? predicate = null)
where T : BaseModifier
{
return GetModifiers(predicate).FirstOrDefault();
}
@@ -341,7 +346,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the interface of the <see cref="BaseModifier"/>.</typeparam>
/// <returns>The <see cref="BaseModifier"/> of type <typeparamref name="T"/> if it is found, <see langword="null"/> otherwise.</returns>
[HideFromIl2Cpp]
public T? GetModifierOfType<T>(Func<T, bool>? predicate = null) where T : class
public T? GetModifierOfType<T>(Func<T, bool>? predicate = null)
where T : class
{
return GetModifiersOfType(predicate).FirstOrDefault();
}
@@ -352,7 +358,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The <see cref="BaseModifier"/> type.</typeparam>
/// <param name="predicate">The predicate to check the <typeparamref name="T"/> by.</param>
[HideFromIl2Cpp]
public void RemoveModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
public void RemoveModifier<T>(Func<T, bool>? predicate = null)
where T : BaseModifier
{
RemoveModifier(typeof(T), x => predicate == null || predicate((T)x));
}
@@ -435,7 +442,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <returns><see langword="false"/> if the <typeparamref name="T"/> is not active on this player, or there are multiple instances;
/// else <see langword="true"/>.</returns>
[HideFromIl2Cpp]
public bool TryRemoveModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
public bool TryRemoveModifier<T>(Func<T, bool>? predicate = null)
where T : BaseModifier
{
return TryGetModifier(out var modifier, predicate) &&
TryRemoveModifier(modifier);
@@ -505,7 +513,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the <see cref="BaseModifier"/>.</typeparam>
/// <returns>The new <typeparamref name="T"/>.</returns>
[HideFromIl2Cpp]
public T? AddModifier<T>(params object[] args) where T : BaseModifier
public T? AddModifier<T>(params object[] args)
where T : BaseModifier
{
return AddModifier(typeof(T), args) as T;
}
@@ -544,6 +553,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
{
modifier.UniqueId = Guid.NewGuid();
}
return modifier;
}
@@ -585,7 +595,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the <see cref="BaseModifier"/>.</typeparam>
/// <returns><see langword="true"/> if the <typeparamref name="T"/> is present, <see langword="false"/> otherwise.</returns>
[HideFromIl2Cpp]
public bool HasModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
public bool HasModifier<T>(Func<T, bool>? predicate = null)
where T : BaseModifier
{
return ActiveModifiers.Exists(x => x is T modifier && (predicate == null || predicate(modifier)));
}
@@ -636,7 +647,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the <see cref="BaseModifier"/>.</typeparam>
/// <returns><see langword="true"/> if the <typeparamref name="T"/> is present, <see langword="false"/> otherwise.</returns>
[HideFromIl2Cpp]
public bool HasModifier<T>(bool checkInactive, Func<T, bool>? predicate = null) where T : BaseModifier
public bool HasModifier<T>(bool checkInactive, Func<T, bool>? predicate = null)
where T : BaseModifier
{
return ActiveModifiers.Exists(MatchExpr) || (checkInactive && _toAdd.Exists(MatchExpr));
bool MatchExpr(BaseModifier bm)
@@ -701,7 +713,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the interface of the Modifier.</typeparam>
/// <returns>True if the Modifier is present, false otherwise.</returns>
[HideFromIl2Cpp]
public bool HasModifierOfType<T>(Func<T, bool>? predicate = null) where T : class
public bool HasModifierOfType<T>(Func<T, bool>? predicate = null)
where T : class
{
return ActiveModifiers.Exists(x => x is T modifier && (predicate == null || predicate(modifier)));
}
@@ -714,7 +727,8 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
/// <typeparam name="T">The Type of the interface of the Modifier.</typeparam>
/// <returns>True if the Modifier is present, false otherwise.</returns>
[HideFromIl2Cpp]
public bool HasModifierOfType<T>(bool checkInactive, Func<T, bool>? predicate = null) where T : class
public bool HasModifierOfType<T>(bool checkInactive, Func<T, bool>? predicate = null)
where T : class
{
return ActiveModifiers.Exists(MatchExpr) || (checkInactive && _toAdd.Exists(MatchExpr));
bool MatchExpr(BaseModifier bm)
@@ -23,11 +23,15 @@ namespace MiraAPI.Modifiers.ModifierDisplay;
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity Convention.")]
public class ModifierDisplayComponent(nint cppPtr) : MonoBehaviour(cppPtr)
{
private const int ItemsPerPage = 3;
/// <summary>
/// Gets the instance of the <see cref="ModifierDisplayComponent"/>.
/// </summary>
public static ModifierDisplayComponent? Instance { get; private set; }
private readonly Dictionary<BaseModifier, ModifierUiComponent> _modifiers = [];
private RectTransform _children = null!;
private GameObject _modTemplate = null!;
private PassiveButton _toggleButton = null!;
@@ -39,9 +43,6 @@ public class ModifierDisplayComponent(nint cppPtr) : MonoBehaviour(cppPtr)
private PassiveButton _backButton = null!;
private int _currentPage;
private const int ItemsPerPage = 3;
private readonly Dictionary<BaseModifier, ModifierUiComponent> _modifiers = [];
/// <summary>
/// Gets a <see cref="ReadOnlyDictionary{TKey, TValue}"/> of the created <see cref="ModifierUiComponent"/>s.
@@ -25,6 +25,7 @@ public class ModifierUiComponent(nint cppPtr) : MonoBehaviour(cppPtr)
private SpriteRenderer icon = null!;
private TextMeshPro nameText = null!;
private RectTransform descRect = null!;
// ReSharper restore InconsistentNaming
private void Awake()
{
+16 -8
View File
@@ -52,7 +52,8 @@ public static class ModifierExtensions
/// <param name="player">The <see cref="PlayerControl"/> to add the <typeparamref name="T"/> to.</param>
/// <param name="args">The arguments to initialize the <typeparamref name="T"/> with.</param>
/// <typeparam name="T">The <see cref="BaseModifier"/> Type.</typeparam>
public static void RpcAddModifier<T>(this PlayerControl player, params object[] args) where T : BaseModifier
public static void RpcAddModifier<T>(this PlayerControl player, params object[] args)
where T : BaseModifier
{
player.RpcAddModifier(typeof(T), args);
}
@@ -147,7 +148,8 @@ public static class ModifierExtensions
/// <param name="player">The <see cref="PlayerControl"/> instance.</param>
/// <param name="predicate">Optional predicate to filter the <see cref="BaseModifier"/>s.</param>
/// <returns><see langword="true"/> if the <see cref="PlayerControl"/> has the <typeparamref name="T"/>, <see langword="false"/> otherwise.</returns>
public static bool HasModifier<T>(this PlayerControl player, Func<T, bool>? predicate = null) where T : BaseModifier
public static bool HasModifier<T>(this PlayerControl player, Func<T, bool>? predicate = null)
where T : BaseModifier
{
return player.GetModifierComponent().HasModifier(predicate);
}
@@ -197,7 +199,8 @@ public static class ModifierExtensions
/// <param name="player">The <see cref="PlayerControl"/> instance.</param>
/// <param name="predicate">Optional predicate to filter the <see cref="BaseModifier"/>s.</param>
/// <returns><see langword="true"/> if the <see cref="PlayerControl"/> has the <see cref="BaseModifier"/> of type <typeparamref name="T"/>, <see langword="false"/> otherwise.</returns>
public static bool HasModifierOfType<T>(this PlayerControl player, Func<T, bool>? predicate = null) where T : class
public static bool HasModifierOfType<T>(this PlayerControl player, Func<T, bool>? predicate = null)
where T : class
{
return player.GetModifierComponent().HasModifierOfType(predicate);
}
@@ -234,7 +237,8 @@ public static class ModifierExtensions
/// <param name="predicate">The predicate to check the <typeparamref name="T"/> by.</param>
/// <typeparam name="T">The Type of the <see cref="BaseModifier"/>.</typeparam>
/// <returns><see langword="true"/> if the <typeparamref name="T"/> was found, <see langword="false"/> otherwise.</returns>
public static bool TryGetModifier<T>(this PlayerControl player, [NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null) where T : BaseModifier
public static bool TryGetModifier<T>(this PlayerControl player, [NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null)
where T : BaseModifier
{
return player.GetModifierComponent().TryGetModifier(out modifier, predicate);
}
@@ -285,7 +289,8 @@ public static class ModifierExtensions
/// <param name="predicate">The predicate to check the <see cref="BaseModifier"/> of type <typeparamref name="T"/> by.</param>
/// <typeparam name="T">The Type of the interface of the <see cref="BaseModifier"/>.</typeparam>
/// <returns><see langword="true"/> if the <see cref="BaseModifier"/> of type <typeparamref name="T"/> was found, <see langword="false"/> otherwise.</returns>
public static bool TryGetModifierOfType<T>(this PlayerControl player, [NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null) where T : class
public static bool TryGetModifierOfType<T>(this PlayerControl player, [NotNullWhen(true)] out T? modifier, Func<T, bool>? predicate = null)
where T : class
{
return player.GetModifierComponent().TryGetModifierOfType(out modifier, predicate);
}
@@ -297,7 +302,8 @@ public static class ModifierExtensions
/// <param name="player">The <see cref="PlayerControl"/> instance.</param>
/// <param name="predicate">Optional predicate to filter the <typeparamref name="T"/>s.</param>
/// <returns>The <typeparamref name="T"/> if found, <see langword="null"/> otherwise.</returns>
public static T? GetModifier<T>(this PlayerControl player, Func<T, bool>? predicate = null) where T : BaseModifier
public static T? GetModifier<T>(this PlayerControl player, Func<T, bool>? predicate = null)
where T : BaseModifier
{
return player.GetModifierComponent().GetModifier(predicate);
}
@@ -352,7 +358,8 @@ public static class ModifierExtensions
/// <param name="player">The <see cref="PlayerControl"/> instance.</param>
/// <param name="predicate">Optional predicate to filter the <see cref="BaseModifier"/>s.</param>
/// <returns>The <see cref="BaseModifier"/> of type <typeparamref name="T"/> if found, <see langword="null"/> otherwise.</returns>
public static T? GetModifierOfType<T>(this PlayerControl player, Func<T, bool>? predicate = null) where T : class
public static T? GetModifierOfType<T>(this PlayerControl player, Func<T, bool>? predicate = null)
where T : class
{
return player.GetModifierComponent().GetModifierOfType(predicate);
}
@@ -546,7 +553,8 @@ public static class ModifierExtensions
/// <param name="player">The <see cref="PlayerControl"/> instance.</param>
/// <param name="args">The arguments to initialize the <typeparamref name="T"/> with.</param>
/// <returns>The added <typeparamref name="T"/>.</returns>
public static T? AddModifier<T>(this PlayerControl player, params object[] args) where T : BaseModifier
public static T? AddModifier<T>(this PlayerControl player, params object[] args)
where T : BaseModifier
{
return player.GetModifierComponent().AddModifier<T>(args);
}
+2 -1
View File
@@ -63,7 +63,8 @@ public static class ModifierFactory
/// Factory for creating instances of <typeparamref name="T"/>. More efficient than using reflection.
/// </summary>
/// <typeparam name="T">The <see cref="BaseModifier"/> type.</typeparam>
public static class ModifierFactory<T> where T : BaseModifier
public static class ModifierFactory<T>
where T : BaseModifier
{
private static readonly Func<object[], T> Constructor = CreateConstructor();
+2
View File
@@ -136,6 +136,7 @@ public static class ModifierManager
{
Warning($"No valid players for modifier {modifier.ModifierName.Translate()}");
}
continue;
}
@@ -188,6 +189,7 @@ public static class ModifierManager
!player.HasModifier(modifierId) && modifier.IsModifierValidOn(player.Data.Role) &&
modifier.CanSpawnOnCurrentMode();
}
private static bool IsGameModifierPostCheck(PlayerControl player, GameModifier modifier, uint modifierId)
{
return (player.Data.Role is not ICustomRole role || role.IsModifierApplicable(modifier)) &&
+4 -2
View File
@@ -15,7 +15,8 @@ public static class ModifierUtils
/// <param name="predicate">Select if <typeparamref name="T"/> is valid to be added to list.</param>
/// <typeparam name="T">The <see cref="BaseModifier"/> type.</typeparam>
/// <returns>An <see cref="IEnumerable{T}"/> of <typeparamref name="T"/>s.</returns>
public static IEnumerable<T> GetActiveModifiers<T>(Func<T, bool>? predicate = null) where T : BaseModifier
public static IEnumerable<T> GetActiveModifiers<T>(Func<T, bool>? predicate = null)
where T : BaseModifier
{
return PlayerControl.AllPlayerControls.ToArray().SelectMany(x => x.GetModifiers(predicate));
}
@@ -26,7 +27,8 @@ public static class ModifierUtils
/// <param name="predicate">Select if <typeparamref name="T"/> is valid.</param>
/// <typeparam name="T">The <see cref="BaseModifier"/> type.</typeparam>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="PlayerControl"/>s with that <typeparamref name="T"/>.</returns>
public static IEnumerable<PlayerControl> GetPlayersWithModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
public static IEnumerable<PlayerControl> GetPlayersWithModifier<T>(Func<T, bool>? predicate = null)
where T : BaseModifier
{
return PlayerControl.AllPlayerControls.ToArray().Where(x => x.HasModifier(predicate));
}
+3 -1
View File
@@ -12,8 +12,10 @@ namespace MiraAPI.Networking;
/// </summary>
/// <inheritdoc />
[RegisterCustomRpc((uint)MiraRpc.CustomGameOver)]
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated via Activator.CreateInstance.)
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line (Justification: ReSharper suppression.)
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated by Reactor.)
public class CustomGameOverRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc<MiraApiPlugin, GameOverData>(plugin, id)
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
{
/// <inheritdoc />
public override RpcLocalHandling LocalHandling => RpcLocalHandling.After;
+4
View File
@@ -81,6 +81,7 @@ public static class CustomMurderRpc
{
return;
}
var murderResultFlags = didSucceed ? MurderResultFlags.Succeeded : MurderResultFlags.FailedError;
var beforeMurderEvent = new BeforeMurderEvent(source, target, inMeeting);
@@ -222,6 +223,7 @@ public static class CustomMurderRpc
{
return;
}
var murderResultFlags = didSucceed ? MurderResultFlags.Succeeded : MurderResultFlags.FailedError;
var beforeMurderEvent = new BeforeMurderEvent(source, target, isIndirect, ignoreDefense, inMeeting);
@@ -351,6 +353,7 @@ public static class CustomMurderRpc
{
return;
}
var murderResultFlags = didSucceed ? MurderResultFlags.Succeeded : MurderResultFlags.FailedError;
var beforeMurderEvent = new BeforeMurderEvent(source, target, framed, isIndirect, ignoreDefense, inMeeting);
@@ -745,6 +748,7 @@ public static class CustomMurderRpc
{
yield break;
}
var cam = Camera.main?.GetComponent<FollowerCamera>();
var playerToLunge = framed ?? source;
var isParticipant = playerToLunge.AmOwner || target.AmOwner;
@@ -13,8 +13,10 @@ namespace MiraAPI.Networking.Modifiers;
/// <param name="plugin">Mira plugin.</param>
/// <param name="id">RPC ID.</param>
[RegisterCustomRpc((uint)MiraRpc.AddModifier)]
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line (Justification: ReSharper suppression.)
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated by Reactor.)
public class AddModifierRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc<MiraApiPlugin, ModifierData>(plugin, id)
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
{
/// <inheritdoc />
public override RpcLocalHandling LocalHandling => RpcLocalHandling.Before;
+3 -1
View File
@@ -7,8 +7,10 @@ namespace MiraAPI.Networking;
// METHOD RPC DOESN'T WORK WITH THE ARRAYS AND STUFF SO THIS IS HOW WE WILL DO IT FOR NOW
[RegisterCustomRpc((uint)MiraRpc.SyncGameOptions)]
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated via Activator.CreateInstance.)
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line (Justification: ReSharper suppression.)
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated by Reactor.)
internal sealed class SyncOptionsRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc<MiraApiPlugin, NetData[]>(plugin, id)
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
{
public override RpcLocalHandling LocalHandling => RpcLocalHandling.None;
+3 -1
View File
@@ -6,8 +6,10 @@ using Reactor.Networking.Rpc;
namespace MiraAPI.Networking;
[RegisterCustomRpc((uint)MiraRpc.SyncRoleOptions)]
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated via Activator.CreateInstance.)
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line (Justification: ReSharper suppression.)
// ReSharper disable once ClassNeverInstantiated.Global (Justification: Instantiated by Reactor.)
internal sealed class SyncRoleOptionsRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc<MiraApiPlugin, NetData[]>(plugin, id)
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
{
public override RpcLocalHandling LocalHandling => RpcLocalHandling.None;
@@ -9,8 +9,10 @@ namespace MiraAPI.Patches.Accessibility;
[HarmonyPatch]
[SuppressMessage("Style", "IDE0074:Use compound assignment", Justification = "Using compound assignment bypasses Unity lifetime checks.")]
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line (Justification: ReSharper suppression.)
// ReSharper disable ConvertIfStatementToNullCoalescingAssignment (Justification: Read above.)
public static class HudManagerFlashPatches
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
{
[HarmonyPatch(typeof(HudManager), nameof(HudManager.StartReactorFlash))]
[HarmonyPrefix]
@@ -42,6 +44,7 @@ public static class HudManagerFlashPatches
{
yield break;
}
var hudManager = HudManager.Instance;
var wait = new WaitForSeconds(1f);
var light = false;
@@ -55,6 +58,7 @@ public static class HudManagerFlashPatches
{
SoundManager.Instance.PlaySound(ShipStatus.Instance.SabotageSound, false);
}
light = !light;
/*if (!MiraApiPlugin.IsMobile)
+1
View File
@@ -21,6 +21,7 @@ public static class CanUsePatches
yield return AccessTools.Method(typeof(PlatformConsole), nameof(PlatformConsole.CanUse));
yield return AccessTools.Method(typeof(SystemConsole), nameof(SystemConsole.CanUse));
yield return AccessTools.Method(typeof(ZiplineConsole), nameof(ZiplineConsole.CanUse));
// vent is not necessary as it has its own patch
}
@@ -31,6 +31,7 @@ public static class VanillaButtonPatches
{
ventTarget = role.Cast<EngineerRole>().currentTarget;
}
var genericEvent = new VanillaButtonClickEvent(__instance, playerTarget, ventTarget);
MiraEventManager.InvokeEvent(genericEvent);
if (genericEvent.IsCancelled)
@@ -52,6 +53,7 @@ public static class VanillaButtonPatches
{
playerTarget = role.Cast<DetectiveRole>().currentTarget;
}
var genericEvent = new VanillaButtonClickEvent(__instance, playerTarget);
MiraEventManager.InvokeEvent(genericEvent);
if (genericEvent.IsCancelled)
@@ -35,6 +35,7 @@ public static class VentEventPatches
{
_showButtons = !@event.IsCancelled;
}
return !@event.IsCancelled;
}
@@ -52,6 +53,7 @@ public static class VentEventPatches
{
_showButtons = @event.IsCancelled;
}
return !@event.IsCancelled;
}
}
+10 -3
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
@@ -23,8 +24,8 @@ namespace MiraAPI.Patches.Freeplay;
[HarmonyPatch(typeof(TaskAdderGame))]
public static class TaskAdderPatches
{
private static Scroller _scroller = null!;
private static readonly Dictionary<string, TaskFolder> Folders = [];
private static Scroller _scroller = null!;
public static string CrewmateName => TranslationController.Instance.GetString(StringNames.Crewmate);
public static string ImpostorName => TranslationController.Instance.GetString(StringNames.Impostor);
@@ -33,6 +34,7 @@ public static class TaskAdderPatches
[HarmonyPostfix]
[HarmonyPatch(nameof(TaskAdderGame.Begin))]
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment should be preceded by blank line", Justification = "Don't know, but seems important enough to keep.")]
public static void AddRolesFolder(TaskAdderGame __instance)
{
GameObject inner = new("Inner");
@@ -73,13 +75,13 @@ public static class TaskAdderPatches
__instance.TaskParent = inner.transform;
var crewmateFolder = __instance.Root.SubFolders.ToArray().FirstOrDefault(x => x.FolderName == CrewmateName)!;
var impostorFolder = __instance.Root.SubFolders.ToArray().FirstOrDefault(x => x.FolderName == ImpostorName)!;
// var neutralFolder = __instance.CreateFolder("Neutral", __instance.Root, 2, Color.gray);
// var neutralFolder = __instance.CreateFolder(NeutralName, __instance.Root, 2, Color.gray);
var modifiersFolder = __instance.CreateFolder(ModifiersName, __instance.Root, 0, Color.blue);
Folders.Clear();
Folders.Add(crewmateFolder.FolderName, crewmateFolder);
Folders.Add(impostorFolder.FolderName, impostorFolder);
// folders.Add("Neutrals", neutralFolder);
// Folders.Add(NeutralName, neutralFolder);
Folders.Add(ModifiersName, modifiersFolder);
var folderIdx = 2;
@@ -266,6 +268,7 @@ public static class TaskAdderPatches
stringBuilder.Append(t.FolderName);
stringBuilder.Append('\\');
}
__instance.PathText.text = stringBuilder.ToString();
__instance.PathText.fontSizeMin = 3;
__instance.PathText.fontSizeMax = 3;
@@ -368,6 +371,7 @@ public static class TaskAdderPatches
{
// I hate you
}
if (split is ["Roles", _, _] && Folders.Any(x => taskFolder.IsChildOf(x.Value)))
{
var plugin = MiraPluginManager.GetPluginByGuid(split[2]);
@@ -381,6 +385,7 @@ public static class TaskAdderPatches
{
continue;
}
var crewLocale = TranslationController.Instance.GetString(StringNames.Crewmate);
var impLocale = TranslationController.Instance.GetString(StringNames.Impostor);
@@ -389,6 +394,7 @@ public static class TaskAdderPatches
{
teamFolder = cs.Configuration.FreeplayFolder;
}
if (split[1] != teamFolder)
{
continue;
@@ -416,6 +422,7 @@ public static class TaskAdderPatches
{
customColor = Palette.ImpostorRed;
}
roleAddButton.FileImage.color = customColor;
roleAddButton.RolloverHandler.OutColor = customColor;
}
+20 -20
View File
@@ -10,10 +10,18 @@ internal static class ConsolePatches
[HarmonyPrefix, HarmonyPatch(typeof(Console), nameof(Console.CanUse))]
public static bool CanUsePatch(Console __instance, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
{
if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance)
if (AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started || !ShipStatus.Instance)
{
if (CustomGameModeManager.ActiveMode == null || CustomGameModeManager.ActiveMode.CanUseTasks(__instance))
canUse = couldUse = true;
return true;
}
if (CustomGameModeManager.ActiveMode != null && !CustomGameModeManager.ActiveMode.CanUseTasks(__instance))
{
canUse = couldUse = false;
return false;
}
var task = __instance.FindTask(pc.Object);
if (task && task.GetComponent<SabotageTask>())
@@ -27,19 +35,15 @@ internal static class ConsolePatches
return true;
}
canUse = couldUse = false;
return false;
}
[HarmonyPrefix, HarmonyPatch(typeof(SystemConsole), nameof(SystemConsole.CanUse))]
public static bool SystemCanUsePatch(SystemConsole __instance, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
{
if (AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started || !ShipStatus.Instance)
{
canUse = couldUse = true;
return true;
}
[HarmonyPrefix, HarmonyPatch(typeof(SystemConsole), nameof(SystemConsole.CanUse))]
public static bool SystemCanUsePatch(SystemConsole __instance, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
{
if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance)
{
if (CustomGameModeManager.ActiveMode == null || CustomGameModeManager.ActiveMode.CanUseSystemConsole(__instance))
{
canUse = couldUse = true;
@@ -50,15 +54,15 @@ internal static class ConsolePatches
return false;
}
[HarmonyPrefix, HarmonyPatch(typeof(MapConsole), nameof(MapConsole.CanUse))]
public static bool MapCanUsePatch(MapConsole __instance, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
{
if (AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started || !ShipStatus.Instance)
{
canUse = couldUse = true;
return true;
}
[HarmonyPrefix, HarmonyPatch(typeof(MapConsole), nameof(MapConsole.CanUse))]
public static bool MapCanUsePatch(MapConsole __instance, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
{
if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance)
{
if (CustomGameModeManager.ActiveMode == null || CustomGameModeManager.ActiveMode.CanUseMapConsole(__instance))
{
canUse = couldUse = true;
@@ -69,10 +73,6 @@ internal static class ConsolePatches
return false;
}
canUse = couldUse = true;
return true;
}
[HarmonyPrefix, HarmonyPatch(typeof(MapConsole), nameof(MapConsole.Use))]
public static bool MapUsePatch(MapConsole __instance)
{
@@ -30,6 +30,7 @@ internal static class GameLogicPatches
{
return true;
}
__result = CustomGameModeManager.ActiveMode.GetBodyType(player);
return false;
}
@@ -17,6 +17,7 @@ internal static class GameManagerPatches
return true;
}
[HarmonyPrefix, HarmonyPatch(nameof(GameManager.ShowCrewmatesKilled))]
public static bool ShowCrewmatesKilledPrefix(ref bool __result)
{
@@ -28,6 +29,7 @@ internal static class GameManagerPatches
return true;
}
[HarmonyPatch(typeof(NormalGameManager), nameof(NormalGameManager.GetMapOptions))]
[HarmonyPrefix]
public static bool GetMapOptions(ref MapOptions __result)
+6
View File
@@ -50,6 +50,7 @@ public static class HudManagerPatches
{
_storedButtonsParent = HudManager.Instance.transform.FindChild("Buttons");
}
if (_storedButtonsParent)
{
foreach (var aspect in _storedButtonsParent.GetComponentsInChildren<AspectPosition>(true))
@@ -146,6 +147,7 @@ public static class HudManagerPatches
{
return;
}
__instance.chatButton.transform.localPosition = MiraHudHelper.ClonedChatButton.transform.localPosition + new Vector3(-0.3f, 0);
}
@@ -219,6 +221,7 @@ public static class HudManagerPatches
fakeButton.ToggleVisible(true);
fakeButton.Destroy();
}
ModdedKeybindIcons = [];
foreach (var button in CustomButtonManager.CustomButtons)
@@ -244,6 +247,7 @@ public static class HudManagerPatches
Error($"Failed to create custom button {button.GetType().Name}: {e}");
}
}
__instance.ImpostorVentButton.transform.SetParent(null);
__instance.ImpostorVentButton.transform.SetParent(BottomRight.transform);
@@ -273,6 +277,7 @@ public static class HudManagerPatches
{
continue;
}
var icon = Helpers.CreateKeybindIcon(buttonObj, key, keybindIconPos);
vanillaKeybindIcons.Add(icon.transform.GetChild(0).GetComponent<TextMeshPro>(), actionId);
if (!MiraApiPlugin.IsMobile)
@@ -281,6 +286,7 @@ public static class HudManagerPatches
KeybindManager.VanillaKeybinds[comp.GetType()].Button = comp;
}
}
MiraApiSettings.OldButtonScaleFactor =
LocalSettingsTabSingleton<MiraApiSettings>.Instance.ButtonUIFactorSlider.Value;
MiraApiSettings.OldUiButtonScaleFactor =
+4
View File
@@ -50,6 +50,7 @@ public static class IntroCutscenePatches
public static void Postfix(Il2CppObjectBase __instance)
{
var wrapper = new StateMachineWrapper<IntroCutscene>(__instance);
// run before the first yield
if (wrapper.GetState() != 1)
{
@@ -117,17 +118,20 @@ public static class IntroCutscenePatches
if (_usedFallback)
{
var wrapper = new StateMachineWrapper<IntroCutscene>(__instance);
// run after the final yield
if (wrapper.GetState() != -1)
{
return;
}
introCutscene = wrapper.Instance;
}
else
{
introCutscene = __instance.Cast<IntroCutscene>();
}
Info("IntroCutscene ended");
MeetingButtonManager.OnGameStart();
@@ -36,6 +36,7 @@ public static class OptionsMenuBehaviourPatch
{
return;
}
if (_remapBackground == null)
{
return;
@@ -14,14 +14,16 @@ namespace MiraAPI.Patches.LocalSettings;
[HarmonyPatch(typeof(OptionsMenuBehaviour))]
public static class OptionsMenuPatches
{
private static readonly Dictionary<int, List<GameObject>> TabButtons = [];
private static int currentPage = 1;
internal static OptionsMenuBehaviour? Instance { get; private set; }
[SuppressMessage("Critical Code Smell", "S2223:Non-constant static fields should not be visible", Justification = "Internal behaviour that does not need property-level validation.")]
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")]
internal static BoxCollider2D MaskCollider = null!;
private static SpriteRenderer? background;
private static int currentPage = 1;
private static readonly Dictionary<int, List<GameObject>> TabButtons = [];
private static SpriteRenderer? background;
/// <summary>
/// Creates the <see cref="LocalSettingsTab"/>s and their content.
@@ -31,6 +33,7 @@ public static class OptionsMenuPatches
public static void StartPostfix(OptionsMenuBehaviour __instance)
{
Instance = __instance;
// Fix for tabs not being clickable in the main menu
if (!AmongUsClient.Instance.IsInGame)
{
@@ -87,11 +90,13 @@ public static class OptionsMenuPatches
TabButtons.Add(page, []);
list = TabButtons[page];
}
list.Add(button);
yOffset += 0.6f;
tabIdx++;
i++;
}
if (i > 7)
{
i = 0;
@@ -107,6 +112,7 @@ public static class OptionsMenuPatches
{
currentPage = 1;
}
if (currentPage < 1)
{
currentPage = TabButtons.Count;
@@ -220,6 +226,7 @@ public static class OptionsMenuPatches
tab.Open();
}
private static void CustomClose(LocalSettingsTab tab)
{
if (tab.TabButton?.Button)
+7 -1
View File
@@ -18,8 +18,8 @@ namespace MiraAPI.Patches.Menu;
[HarmonyPatch(typeof(HatsTab))]
public static class HatsTabPatches
{
private static SortedList<string, List<HatData>> sortedHats = [];
private static readonly Dictionary<int, string> StoreNames = [];
private static SortedList<string, List<HatData>> sortedHats = [];
private static int currentPage;
private static void PreviousPage(HatsTab hatsTab)
@@ -44,6 +44,7 @@ public static class HatsTabPatches
{
return true;
}
__instance.currentHat = HatManager.Instance.GetHatById(DataManager.Player.Customization.Hat);
var allHats = HatManager.Instance.GetUnlockedHats().ToImmutableList();
@@ -80,6 +81,7 @@ public static class HatsTabPatches
{
return;
}
if (sortedHats.Count == 0) return;
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
@@ -120,6 +122,7 @@ public static class HatsTabPatches
text.fontSizeMax = 5f;
text.fontSizeMin = 0f;
var xLerp = __instance.XRange.Lerp(0.5f);
// ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
var yLerp = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
text.transform.localPosition = new Vector3(xLerp, yLerp, -1f);
@@ -127,6 +130,7 @@ public static class HatsTabPatches
hatIndex += 5;
loadRoutine = Coroutines.Start(CoGenerateChips(__instance, hats));
}
// ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
__instance.scroller.ContentYBounds.max = -(__instance.YStart - (hatIndex + 1) / __instance.NumPerRow * __instance.YOffset) - 3f;
__instance.currentHatIsEquipped = true;
@@ -143,6 +147,7 @@ public static class HatsTabPatches
foreach (var hat in batch.OrderBy(HatManager.Instance.allHats.IndexOf))
{
var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
// ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), hat);
@@ -153,6 +158,7 @@ public static class HatsTabPatches
__instance.SetScrollerBounds();
yield return new WaitForSeconds(0.01f);
}
__instance.currentHatIsEquipped = true;
loadRoutine = null;
}
+2 -1
View File
@@ -10,7 +10,8 @@ namespace MiraAPI.Patches.Menu;
public static class InventoryUtility
{
public static void CreateNextBackButtons<T>(T tab, Action<T> previousPage, Action<T> nextPage) where T : InventoryTab
public static void CreateNextBackButtons<T>(T tab, Action<T> previousPage, Action<T> nextPage)
where T : InventoryTab
{
var title = tab.transform.FindChild("Text");
title.localPosition = new Vector3(.9123f, -.23f, -55);
+8 -4
View File
@@ -1,12 +1,12 @@
using AmongUs.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using AmongUs.Data;
using HarmonyLib;
using Innersloth.Assets;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -50,6 +50,7 @@ public static class NameplatesTabPatches
{
return true;
}
__instance.plateId = HatManager.Instance.GetNamePlateById(DataManager.Player.Customization.namePlate).ProdId;
if (!SortedNameplates.ContainsKey("Vanilla")) AddRange(HatManager.Instance.GetUnlockedNamePlates().Select(x => ("Vanilla", x)));
@@ -70,6 +71,7 @@ public static class NameplatesTabPatches
{
return;
}
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
{
PreviousPage(__instance);
@@ -109,6 +111,7 @@ public static class NameplatesTabPatches
foreach (var visor in nameplates.OrderBy(HatManager.Instance.allNamePlates.IndexOf))
{
var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
// ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), visor);
@@ -149,6 +152,7 @@ public static class NameplatesTabPatches
void LoadNameplate(NamePlateViewData viewData)
{
colorChip.transform.GetChild(1).GetComponent<SpriteRenderer>().sprite = viewData.Image;
// (colorChip as NameplateChip).image.sprite = viewData?.Image;
}
}
+9 -5
View File
@@ -1,12 +1,12 @@
using AmongUs.Data;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using AmongUs.Data;
using HarmonyLib;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities.Extensions;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using TMPro;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -41,6 +41,7 @@ public static class SkinsTabPatches
{
return true;
}
__instance.skinId = HatManager.Instance.GetSkinById(DataManager.Player.Customization.Skin).ProdId;
var allSkins = HatManager.Instance.GetUnlockedSkins().ToImmutableList();
@@ -71,6 +72,7 @@ public static class SkinsTabPatches
{
return;
}
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
{
PreviousPage(__instance);
@@ -110,6 +112,7 @@ public static class SkinsTabPatches
foreach (var skin in skins.OrderBy(HatManager.Instance.allSkins.IndexOf))
{
var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
// ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), skin);
@@ -136,6 +139,7 @@ public static class SkinsTabPatches
{
colorChip.Button.OnClick.AddListener((Action)(() => __instance.SelectSkin(skin)));
}
colorChip.Button.ClickMask = __instance.scroller.Hitbox;
colorChip.ProductId = skin.ProductId;
colorChip.SelectionHighlight.gameObject.SetActive(false);
+7 -4
View File
@@ -1,11 +1,11 @@
using AmongUs.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using AmongUs.Data;
using HarmonyLib;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -49,6 +49,7 @@ public static class VisorsTabPatches
{
return true;
}
__instance.visorId = HatManager.Instance.GetVisorById(DataManager.Player.Customization.Visor).ProdId;
if (!SortedVisors.ContainsKey("Vanilla")) AddRange(HatManager.Instance.GetUnlockedVisors().Select(x => ("Vanilla", x)));
@@ -69,6 +70,7 @@ public static class VisorsTabPatches
{
return;
}
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
{
PreviousPage(__instance);
@@ -108,6 +110,7 @@ public static class VisorsTabPatches
foreach (var visor in visors.OrderBy(HatManager.Instance.allVisors.IndexOf))
{
var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
// ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), visor);
@@ -33,6 +33,7 @@ internal static class EndGameDidWinPatch
{
CachedWinners.Add(new CachedPlayerData(networkedPlayerInfo));
}
continue;
}
@@ -36,7 +36,6 @@ internal static class GameOptionsMenuPatch
[HarmonyPrefix]
[HarmonyPatch(nameof(GameOptionsMenu.Initialize))]
// ReSharper disable once InconsistentNaming
public static bool InitPatch(GameOptionsMenu __instance)
{
__instance.Children ??= new List<OptionBehaviour>();
@@ -101,8 +100,7 @@ internal static class GameOptionsMenuPatch
texture,
new Rect(0, 0, texture.width, texture.height),
Vector2.one / 2,
100f / scale
);
100f / scale);
_modIcon.sprite = newSprite;
_modIcon.drawMode = SpriteDrawMode.Simple;
@@ -122,6 +120,7 @@ internal static class GameOptionsMenuPatch
num -= 0.63f;
opt.gameObject.SetActive(true);
}
foreach (var opt in VanillaOptions)
{
opt.gameObject.SetActive(true);
@@ -135,6 +134,7 @@ internal static class GameOptionsMenuPatch
{
opt.gameObject.SetActive(false);
}
foreach (var opt in VanillaOptions)
{
opt.gameObject.SetActive(false);
@@ -183,6 +183,7 @@ internal static class GameOptionsMenuPatch
instance.ControllerSelectable.Add(obj);
}
}
instance.scrollBar.SetYBoundsMax(-num - 1.65f);
}
@@ -217,6 +218,7 @@ internal static class GameOptionsMenuPatch
{
MainOptions.Add(optionBehaviour);
}
for (var i = 1; i < GameModeOption.Values.Count; i++)
{
GameModeOption.OptionBehaviour.Values =
@@ -296,12 +298,14 @@ internal static class GameOptionsMenuPatch
additionalVanillaScrollNum -= 0.45f;
}
}
foreach (var optionBehaviour in VanillaOptions)
{
if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost)
{
optionBehaviour.SetAsPlayer();
}
instance.Children.Add(optionBehaviour);
}
@@ -328,6 +332,7 @@ internal static class GameOptionsMenuPatch
CreateGroup(instance, group, container, ref newNum, ref optionBehaviours, ref categoryHeaders);
group.Ready = true;
}
GameModeHeaders.Add(mode, categoryHeaders);
GameModeOptions.Add(mode, optionBehaviours);
}
@@ -337,6 +342,7 @@ internal static class GameOptionsMenuPatch
{
instance.ControllerSelectable.Add(obj);
}
instance.scrollBar.SetYBoundsMax(-num - 1.65f);
}
@@ -356,13 +362,13 @@ internal static class GameOptionsMenuPatch
[HarmonyPostfix]
[HarmonyPatch(nameof(GameOptionsMenu.Update))]
// ReSharper disable once InconsistentNaming
public static void UpdatePatch(GameOptionsMenu __instance)
{
if (MenuState.Instance.CurrentModIdx == 0 && GameModeGroups.Count <= 0)
{
return;
}
var num = 2.1f;
switch (MenuState.Instance.CurrentMenu)
@@ -383,6 +389,7 @@ internal static class GameOptionsMenuPatch
GamemodeOptionsUpdate(ref num);
break;
}
var filteredGroups =
MenuState.Instance.CurrentMod.InternalOptionGroups
.Where(x => (x.OptionableType == null || CustomGameModeManager.ActiveMode!.GetType().IsAssignableTo(x.OptionableType)) &&
@@ -398,6 +405,7 @@ internal static class GameOptionsMenuPatch
__instance.scrollBar.SetYBoundsMax(-num - 1.65f);
}
private static void CreateGroup(GameOptionsMenu menu, AbstractOptionGroup group, Transform container, ref float num, ref System.Collections.Generic.List<OptionBehaviour> optionBehaviours, ref System.Collections.Generic.List<CategoryHeaderMasked> categoryHeaders)
{
var categoryHeaderMasked = Object.Instantiate(
@@ -569,6 +577,7 @@ internal static class GameOptionsMenuPatch
UpdateGroup(group, ref num);
}
}
private static void CustomMenuOneUpdate(ref float num)
{
var groups = MenuState.Instance.CurrentMod.InternalOptionGroups
@@ -696,14 +705,13 @@ internal static class GameOptionsMenuPatch
group.Header = categoryHeaderMasked;
}
var options = group.Options.Where(opt => opt.OptionBehaviour == null || !opt.OptionBehaviour
).Select(opt => opt.CreateOption(
var options = group.Options.Where(opt => opt.OptionBehaviour == null || !opt.OptionBehaviour)
.Select(opt => opt.CreateOption(
menu.checkboxOrigin,
menu.numberOptionOrigin,
menu.stringOptionOrigin,
menu.playerOptionOrigin,
container)
);
container));
OptionPreset? defaultPreset = null;
if (PresetManager.DefaultPresets.TryGetValue(MenuState.Instance.CurrentMod, out var preset))
@@ -20,13 +20,13 @@ namespace MiraAPI.Patches.Options;
internal static class GamePresetsTabPatches
{
private static readonly object Lock = new();
private static GameObject _saveButton = null!;
private static GameObject _refreshButton = null!;
private static GameObject _folderButton = null!;
private static GameObject _newDivider = null!;
private static readonly object Lock = new();
[HarmonyPatch(typeof(GamePresetsTab), nameof(GamePresetsTab.OnEnable))]
public static class GamePresetsOnEnablePatch
{
@@ -57,14 +57,17 @@ internal static class GamePresetsTabPatches
{
_saveButton.SetActive(MenuState.Instance.CurrentModIdx != 0);
}
if (_refreshButton)
{
_refreshButton.SetActive(MenuState.Instance.CurrentModIdx != 0);
}
if (_folderButton)
{
_folderButton.SetActive(MenuState.Instance.CurrentModIdx != 0);
}
if (_newDivider)
{
_newDivider.SetActive(MenuState.Instance.CurrentModIdx != 0);
@@ -123,10 +126,12 @@ internal static class GamePresetsTabPatches
{
_saveButton.SetActive(false);
}
if (_refreshButton)
{
_refreshButton.SetActive(false);
}
if (_folderButton)
{
_folderButton.SetActive(false);
@@ -267,6 +272,7 @@ internal static class GamePresetsTabPatches
refreshButton.OnClick = new Button.ButtonClickedEvent();
refreshButton.OnClick.AddListener((UnityAction)Refresh);
}
refreshButton = _refreshButton.GetComponent<PassiveButton>();
if (!_folderButton)
@@ -317,6 +323,7 @@ internal static class GamePresetsTabPatches
{
PresetManager.LoadPresets(MenuState.Instance.CurrentMod);
}
GameSettingMenu.Instance.ChangeTab(0, false); // refresh the tab
}
}
@@ -37,6 +37,7 @@ internal static class GameSettingMenuPatches
{
Error("MenuState instance is null. Cannot change tab.");
}
return false;
}
}
Loaded 100 of 146 files, more files were not shown because too many files have changed in this diff. Show more