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
+672 -538

No files matched your search

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