From 8418b479d844d34a4946a056a1a806559624060a Mon Sep 17 00:00:00 2001 From: Az <56699741+AlchlcDvl@users.noreply.github.com> Date: Sun, 6 Sep 2026 07:03:31 -0400 Subject: [PATCH] cleared all warnings except for the todo ones, since they are supposed to be annoying --- .editorconfig | 15 ++ .gitignore | 2 +- Directory.Build.props | 2 +- .../Modifiers/GeneralModifierOptions.cs | 2 +- MiraAPI/Events/Mira/UiButtonPostResetEvent.cs | 19 +- .../Vanilla/Gameplay/BeforeMurderEvent.cs | 12 +- .../Events/Vanilla/Gameplay/GameEndEvent.cs | 2 +- .../Vanilla/Gameplay/IntroBeginEvent.cs | 2 +- .../Vanilla/Gameplay/IntroRoleRevealEvent.cs | 2 +- .../Meeting/Voting/ProcessVotesEvent.cs | 7 +- .../Vanilla/Player/CompleteTaskEvent.cs | 2 +- .../Events/Vanilla/Player/PlayerDeathEvent.cs | 2 +- .../Events/Vanilla/Player/PlayerJoinEvent.cs | 2 +- .../Events/Vanilla/Player/PlayerLeaveEvent.cs | 2 +- .../Vanilla/Usables/PlayerCanUseEvent.cs | 2 +- .../Events/Vanilla/Usables/PlayerUseEvent.cs | 2 +- MiraAPI/GameModes/AbstractGameMode.cs | 35 ++-- MiraAPI/GameModes/ClassicMode.cs | 1 + MiraAPI/GameModes/CustomGameModeManager.cs | 16 +- MiraAPI/GameModes/GameModeOption.cs | 40 ++-- MiraAPI/GameModes/HideAndSeekMode.cs | 187 ++++++++++-------- MiraAPI/GameOptions/AbstractOptionGroup.cs | 6 +- .../Attributes/ModdedEnumOptionAttribute.cs | 3 + .../Attributes/ModdedNumberOptionAttribute.cs | 7 + MiraAPI/GameOptions/ModdedOptionsManager.cs | 5 +- .../OptionTypes/ModdedStringOption.cs | 30 +-- .../HnsReimplemented/HideAndSeekHudHelper.cs | 108 ++++++---- MiraAPI/HnsReimplemented/HnsDangerMeter.cs | 63 +++--- MiraAPI/HnsReimplemented/HnsMusicHandler.cs | 98 +++++---- .../Options/HnsCrewmateOptions.cs | 74 ++++--- .../Options/HnsFinalHideOptions.cs | 27 ++- .../Options/HnsImpostorOptions.cs | 13 +- .../Options/HnsTaskOptions.cs | 13 +- MiraAPI/Hud/CustomPlayerMenu.cs | 4 +- MiraAPI/Hud/MiraHudHelper.cs | 129 ++++++------ .../Attributes/LocalToggleSettingAttribute.cs | 2 + MiraAPI/LocalSettings/LocalSettingsButton.cs | 7 +- MiraAPI/LocalSettings/LocalSettingsTab.cs | 4 +- .../SettingTypes/LocalEnumSetting.cs | 4 +- .../SettingTypes/LocalNumberSetting.cs | 4 +- .../SettingTypes/LocalSettingBase.cs | 2 +- .../SettingTypes/LocalSliderSetting.cs | 4 +- .../SettingTypes/LocalToggleSetting.cs | 6 +- .../MeetingAbilityBehaviour.cs | 30 +-- .../MeetingAbilities/MeetingActionButton.cs | 6 +- .../MeetingAbilities/MeetingButtonManager.cs | 17 +- .../MeetingAbilities/MeetingButtonUsesMode.cs | 14 +- .../MultiTargetMeetingButton.cs | 10 +- MiraAPI/MiraAPI.csproj | 1 - MiraAPI/MiraApiPlugin.cs | 14 +- MiraAPI/MiraApiSettings.cs | 19 +- MiraAPI/ModCompatibility.cs | 28 ++- MiraAPI/Modifiers/ModifierManager.cs | 2 +- .../Accessibility/HudManagerFlashPatches.cs | 2 +- .../Patches/DetectiveNotesMinigamePatch.cs | 4 +- MiraAPI/Patches/Freeplay/TaskAdderPatches.cs | 10 +- MiraAPI/Patches/GameModes/ConsolePatches.cs | 25 +-- .../Patches/GameModes/CreateOptionsPatch.cs | 2 +- MiraAPI/Patches/GameModes/GameLogicPatches.cs | 14 +- .../Patches/GameModes/GameManagerPatches.cs | 2 +- MiraAPI/Patches/GameModes/HudPatches.cs | 1 - .../Patches/GameModes/ProgressTrackerPatch.cs | 1 + MiraAPI/Patches/GameModes/TaskPanelPatch.cs | 1 + MiraAPI/Patches/HudManagerPatches.cs | 7 - MiraAPI/Patches/IntroCutscenePatches.cs | 2 +- .../Patches/Options/GameOptionsMenuPatch.cs | 104 ++++------ .../Patches/Options/LobbyViewPanePatches.cs | 7 +- MiraAPI/Patches/Options/MenuState.cs | 2 +- .../Patches/Options/RoleSettingMenuPatches.cs | 2 +- MiraAPI/Patches/RoleGuidePatches.cs | 12 +- MiraAPI/Patches/Roles/HowToPlayPatch.cs | 4 +- .../Roles/LogicRoleSelectionHnsPatch.cs | 2 +- MiraAPI/Patches/Roles/SelectRolesPatch.cs | 2 +- MiraAPI/Patches/Stubs/MinigameStubs.cs | 1 + MiraAPI/PluginLoading/IMiraPlugin.cs | 4 +- MiraAPI/PluginLoading/MiraPluginManager.cs | 7 +- MiraAPI/Presets/PresetManager.cs | 21 +- MiraAPI/Translation/MiraLanguage.cs | 83 ++++++++ MiraAPI/Translation/MiraLocaleManager.cs | 139 ++++++++----- .../Translation/MiraLocalizationProvider.cs | 7 + MiraAPI/Translation/TranslationExtensions.cs | 2 + MiraAPI/Utilities/Assets/TmpSpriteUtils.cs | 2 - .../Components/CenteredGridArrange.cs | 18 +- MiraAPI/Utilities/Extensions.cs | 6 +- MiraAPI/Utilities/Helpers.cs | 18 +- MiraAPI/VanillaEvents/JudgeEvents.cs | 4 +- MiraAPI/VanillaEvents/UiResetEvents.cs | 12 +- MiraAPI/Voting/VotingUtils.cs | 17 ++ stylecop.json | 2 +- 89 files changed, 963 insertions(+), 696 deletions(-) diff --git a/.editorconfig b/.editorconfig index 83c451b..134bbe7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,3 +20,18 @@ dotnet_diagnostic.S3358.severity = none # IDE1006: Naming Styles dotnet_diagnostic.IDE1006.severity = none + +# S3267: Use LINQ methods to simply foreach loops +dotnet_diagnostic.S3267.severity = none + +# S125: Sections of code should not be commented out +dotnet_diagnostic.S125.severity = none + +# SA1512: Single-line comments should not be followed by blank line +dotnet_diagnostic.SA1512.severity = none + +# S2696: Instance members should not write to "static" fields +dotnet_diagnostic.S2696.severity = none + +# S2245: Pseudorandom number generators (PRNGs) should not be used in security contexts +dotnet_diagnostic.S2245.severity = none diff --git a/.gitignore b/.gitignore index b52f379..b8ff29a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ bin/ .qodo/ *.user -*.lock.json \ No newline at end of file +*.lock.json diff --git a/Directory.Build.props b/Directory.Build.props index 462fbe9..de8767b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -34,7 +34,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/MiraAPI.Example/Options/Modifiers/GeneralModifierOptions.cs b/MiraAPI.Example/Options/Modifiers/GeneralModifierOptions.cs index 72542af..4d2bd70 100644 --- a/MiraAPI.Example/Options/Modifiers/GeneralModifierOptions.cs +++ b/MiraAPI.Example/Options/Modifiers/GeneralModifierOptions.cs @@ -12,6 +12,6 @@ public class GeneralModifierOptions : AbstractOptionGroup [ModdedToggleOption("options.generalModifier.someBooleanOption")] public bool SomeBooleanOption { get; set; } = true; - [ModdedNumberOption("options.generalModifier.numberOption", 0, 10, 1)] + [ModdedNumberOption("options.generalModifier.numberOption", 0, 10)] public float NumberOption { get; set; } = 5; } diff --git a/MiraAPI/Events/Mira/UiButtonPostResetEvent.cs b/MiraAPI/Events/Mira/UiButtonPostResetEvent.cs index e7221ae..38c1755 100644 --- a/MiraAPI/Events/Mira/UiButtonPostResetEvent.cs +++ b/MiraAPI/Events/Mira/UiButtonPostResetEvent.cs @@ -5,26 +5,17 @@ namespace MiraAPI.Events.Mira; /// /// Event fired by Mira API to adjust the UI buttons at the top right of the screen. /// -public class UiButtonPostResetEvent : MiraEvent +/// The for the top UI row. +/// The for the second UI row. +public class UiButtonPostResetEvent(GameObject topUiRow, GameObject secondUiRow) : MiraEvent { /// /// Gets the parent for the very top UI row. /// - public GameObject MainTopUiRow { get; } + public GameObject MainTopUiRow { get; } = topUiRow; /// /// Gets the parent for the second top UI row. /// - public GameObject SecondTopUiRow { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The for the top UI row. - /// The for the second UI row. - public UiButtonPostResetEvent(GameObject topUiRow, GameObject secondUiRow) - { - MainTopUiRow = topUiRow; - SecondTopUiRow = secondUiRow; - } + public GameObject SecondTopUiRow { get; } = secondUiRow; } diff --git a/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs index e69f5a4..4441391 100644 --- a/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs +++ b/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs @@ -45,23 +45,13 @@ public sealed class BeforeMurderEvent(PlayerControl source, PlayerControl target /// public MeetingCheck InMeeting { get; } = inMeeting; - /// - /// Initializes a new instance of the class. - /// - /// The that is killing the . - /// The that is being killed. - public BeforeMurderEvent(PlayerControl source, PlayerControl target) - : this(source, target, MeetingCheck.Ignore) - { - } - /// /// Initializes a new instance of the class. /// /// The that is killing the . /// The that is being killed. /// Whether the murder is intended to be triggered in a meeting. - public BeforeMurderEvent(PlayerControl source, PlayerControl target, MeetingCheck inMeeting) + public BeforeMurderEvent(PlayerControl source, PlayerControl target, MeetingCheck inMeeting = MeetingCheck.Ignore) : this(source, target, false, false, inMeeting) { } diff --git a/MiraAPI/Events/Vanilla/Gameplay/GameEndEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/GameEndEvent.cs index df030a8..5d94b4b 100644 --- a/MiraAPI/Events/Vanilla/Gameplay/GameEndEvent.cs +++ b/MiraAPI/Events/Vanilla/Gameplay/GameEndEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Gameplay; /// -/// The event that is invoked when the end game screen is shown. Non cancelable. +/// The event that is invoked when the end game screen is shown. Non-cancelable. /// /// The instance. public class GameEndEvent(EndGameManager manager) : MiraEvent diff --git a/MiraAPI/Events/Vanilla/Gameplay/IntroBeginEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/IntroBeginEvent.cs index 7de4c6c..b381390 100644 --- a/MiraAPI/Events/Vanilla/Gameplay/IntroBeginEvent.cs +++ b/MiraAPI/Events/Vanilla/Gameplay/IntroBeginEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Gameplay; /// -/// The event that is invoked when the intro cutscene is shown. Non cancelable. +/// The event that is invoked when the intro cutscene is shown. Non-cancelable. /// /// The intro cutscene. public class IntroBeginEvent(IntroCutscene introCutscene) : MiraEvent diff --git a/MiraAPI/Events/Vanilla/Gameplay/IntroRoleRevealEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/IntroRoleRevealEvent.cs index 95ff2a2..417e96b 100644 --- a/MiraAPI/Events/Vanilla/Gameplay/IntroRoleRevealEvent.cs +++ b/MiraAPI/Events/Vanilla/Gameplay/IntroRoleRevealEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Gameplay; /// -/// The event that is invoked when the player's role is shown on the intro cutscene. Non cancelable. +/// The event that is invoked when the player's role is shown on the intro cutscene. Non-cancelable. /// /// The intro cutscene. public class IntroRoleRevealEvent(IntroCutscene introCutscene) : MiraEvent diff --git a/MiraAPI/Events/Vanilla/Meeting/Voting/ProcessVotesEvent.cs b/MiraAPI/Events/Vanilla/Meeting/Voting/ProcessVotesEvent.cs index 94464b8..9357298 100644 --- a/MiraAPI/Events/Vanilla/Meeting/Voting/ProcessVotesEvent.cs +++ b/MiraAPI/Events/Vanilla/Meeting/Voting/ProcessVotesEvent.cs @@ -13,8 +13,6 @@ public class ProcessVotesEvent(List votes, NetworkedPlayerInfo? exil { private readonly List _originalVotes = [.. votes]; - private NetworkedPlayerInfo? _exiledPlayer = exiledPlayer; - /// /// Gets a value indicating whether the exiled player has been modified by the event. /// @@ -45,11 +43,12 @@ public class ProcessVotesEvent(List votes, NetworkedPlayerInfo? exil /// public NetworkedPlayerInfo? ExiledPlayer { - get => _exiledPlayer; + get; set { - _exiledPlayer = value; + field = value; ExiledPlayerModified = true; } } + = exiledPlayer; } diff --git a/MiraAPI/Events/Vanilla/Player/CompleteTaskEvent.cs b/MiraAPI/Events/Vanilla/Player/CompleteTaskEvent.cs index 7266440..95b2430 100644 --- a/MiraAPI/Events/Vanilla/Player/CompleteTaskEvent.cs +++ b/MiraAPI/Events/Vanilla/Player/CompleteTaskEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Player; /// -/// The event that is invoked when a player completes a task. Non cancelable. +/// The event that is invoked when a player completes a task. Non-cancelable. /// /// The player who completed the task. /// The task that the player completed. diff --git a/MiraAPI/Events/Vanilla/Player/PlayerDeathEvent.cs b/MiraAPI/Events/Vanilla/Player/PlayerDeathEvent.cs index 3441521..b03d2aa 100644 --- a/MiraAPI/Events/Vanilla/Player/PlayerDeathEvent.cs +++ b/MiraAPI/Events/Vanilla/Player/PlayerDeathEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Player; /// -/// Event that is invoked when a player dies. Non cancelable. +/// Event that is invoked when a player dies. Non-cancelable. /// /// The player who died. /// The reason the player died. diff --git a/MiraAPI/Events/Vanilla/Player/PlayerJoinEvent.cs b/MiraAPI/Events/Vanilla/Player/PlayerJoinEvent.cs index 384f144..5f66472 100644 --- a/MiraAPI/Events/Vanilla/Player/PlayerJoinEvent.cs +++ b/MiraAPI/Events/Vanilla/Player/PlayerJoinEvent.cs @@ -3,7 +3,7 @@ namespace MiraAPI.Events.Vanilla.Player; /// -/// Event that is invoked when a player joins the lobby. Non cancelable. +/// Event that is invoked when a player joins the lobby. Non-cancelable. /// /// The data of the player who joined. public class PlayerJoinEvent(ClientData data) : MiraEvent diff --git a/MiraAPI/Events/Vanilla/Player/PlayerLeaveEvent.cs b/MiraAPI/Events/Vanilla/Player/PlayerLeaveEvent.cs index 11ce0d6..1af8bde 100644 --- a/MiraAPI/Events/Vanilla/Player/PlayerLeaveEvent.cs +++ b/MiraAPI/Events/Vanilla/Player/PlayerLeaveEvent.cs @@ -3,7 +3,7 @@ namespace MiraAPI.Events.Vanilla.Player; /// -/// Event that is invoked when a player leaves the game. Non cancelable. +/// Event that is invoked when a player leaves the game. Non-cancelable. /// /// The data of the player who left. /// The reason why the player left. diff --git a/MiraAPI/Events/Vanilla/Usables/PlayerCanUseEvent.cs b/MiraAPI/Events/Vanilla/Usables/PlayerCanUseEvent.cs index bc5a06f..4f547c6 100644 --- a/MiraAPI/Events/Vanilla/Usables/PlayerCanUseEvent.cs +++ b/MiraAPI/Events/Vanilla/Usables/PlayerCanUseEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Usables; /// -/// Event for if a can use an from Vanilla Among Us. Will always be ran locally. +/// Event for if a can use an from Vanilla Among Us. Will always be run locally. /// /// The . public class PlayerCanUseEvent(IUsable usable) : PlayerUseEvent(usable); diff --git a/MiraAPI/Events/Vanilla/Usables/PlayerUseEvent.cs b/MiraAPI/Events/Vanilla/Usables/PlayerUseEvent.cs index e3ce2d0..a23ce0e 100644 --- a/MiraAPI/Events/Vanilla/Usables/PlayerUseEvent.cs +++ b/MiraAPI/Events/Vanilla/Usables/PlayerUseEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Usables; /// -/// Event for using a from Vanilla Among Us. Will always be ran locally. +/// Event for using a from Vanilla Among Us. Will always be run locally. /// /// The . public class PlayerUseEvent(IUsable usable) : MiraCancelableEvent diff --git a/MiraAPI/GameModes/AbstractGameMode.cs b/MiraAPI/GameModes/AbstractGameMode.cs index 32339cf..3614341 100644 --- a/MiraAPI/GameModes/AbstractGameMode.cs +++ b/MiraAPI/GameModes/AbstractGameMode.cs @@ -84,15 +84,11 @@ public abstract class AbstractGameMode : IOptionable /// Resulting body type. public virtual PlayerBodyTypes GetBodyType(PlayerControl player) { - if (AprilFoolsMode.ShouldHorseAround()) - { - return PlayerBodyTypes.Horse; - } - if (AprilFoolsMode.ShouldLongAround()) - { - return PlayerBodyTypes.Long; - } - return PlayerBodyTypes.Normal; + return AprilFoolsMode.ShouldHorseAround() + ? PlayerBodyTypes.Horse + : (AprilFoolsMode.ShouldLongAround() + ? PlayerBodyTypes.Long + : PlayerBodyTypes.Normal); } /// @@ -185,9 +181,9 @@ public abstract class AbstractGameMode : IOptionable /// /// The IEnumerator that plays the intro cutscene for this gamemode. /// - /// An instance of IntroCutscene. + /// An instance of IntroCutscene. /// An IEnumerator to run the intro cutscene instead of the base game one. - public virtual IEnumerator IntroCutscene(IntroCutscene __instance) + public virtual IEnumerator IntroCutscene(IntroCutscene introCutscene) { yield return new WaitForEndOfFrame(); } @@ -268,11 +264,15 @@ public abstract class AbstractGameMode : IOptionable } /// - /// Does the task bar appear in the gamemode. + /// Gets a value indicating whether the task bar appears in the gamemode. /// /// True if the task bar is enabled in this mode. public virtual bool ShowTaskBar => true; + /// + /// Updates the task panel. + /// + /// The task panel to update. public virtual void UpdateTaskPanel(TaskPanelBehaviour instance) { instance.background.transform.localScale = (instance.taskText.textBounds.size.x > 0f) @@ -296,14 +296,9 @@ public abstract class AbstractGameMode : IOptionable var xPos = -instance.background.sprite.bounds.size.x * instance.background.transform.localScale.x; instance.closedPosition = new Vector3(xPos, yPos, instance.closedPosition.z); instance.openPosition = new Vector3(instance.openPosition.x, yPos, instance.openPosition.z); - if (instance.open) - { - instance.timer = Mathf.Min(1f, instance.timer + Time.deltaTime / instance.animationTimeSeconds); - } - else - { - instance.timer = Mathf.Max(0f, instance.timer - Time.deltaTime / instance.animationTimeSeconds); - } + instance.timer = instance.open + ? Mathf.Min(1f, instance.timer + Time.deltaTime / instance.animationTimeSeconds) + : Mathf.Max(0f, instance.timer - Time.deltaTime / instance.animationTimeSeconds); Vector3 relativePos = new( Mathf.SmoothStep(instance.closedPosition.x, instance.openPosition.x, instance.timer), diff --git a/MiraAPI/GameModes/ClassicMode.cs b/MiraAPI/GameModes/ClassicMode.cs index 3da9a23..440ce75 100644 --- a/MiraAPI/GameModes/ClassicMode.cs +++ b/MiraAPI/GameModes/ClassicMode.cs @@ -16,5 +16,6 @@ public class ClassicMode : AbstractGameMode /// public override string Description => "MiraApi.Gamemode.Classic.Description"; + /// public override LoadableAsset? Icon => MiraAssets.ClassicGamemodeIcon; } diff --git a/MiraAPI/GameModes/CustomGameModeManager.cs b/MiraAPI/GameModes/CustomGameModeManager.cs index 2d3f071..b5e8177 100644 --- a/MiraAPI/GameModes/CustomGameModeManager.cs +++ b/MiraAPI/GameModes/CustomGameModeManager.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using MiraAPI.PluginLoading; -using Reactor.Utilities; namespace MiraAPI.GameModes; @@ -42,14 +41,13 @@ public static class CustomGameModeManager return false; } - if (!mode.HideMode) - { - IdToModeMap.Add(GetNextId(), mode); - pluginInfo.GameModes.Add(LastId, mode); - mode.ID = LastId; - GameModeOption.AddOption(mode); - } + if (mode.HideMode) + return true; + IdToModeMap.Add(GetNextId(), mode); + pluginInfo.GameModes.Add(LastId, mode); + mode.ID = LastId; + GameModeOption.AddOption(mode); return true; } @@ -135,6 +133,6 @@ public static class CustomGameModeManager } ActiveMode = IdToModeMap[0]; - Logger.Warning($"Unable to find game mode of id {id}!"); + Warning($"Unable to find game mode of id {id}!"); } } diff --git a/MiraAPI/GameModes/GameModeOption.cs b/MiraAPI/GameModes/GameModeOption.cs index a4f8fdb..f0fe6ad 100644 --- a/MiraAPI/GameModes/GameModeOption.cs +++ b/MiraAPI/GameModes/GameModeOption.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using HarmonyLib; using MiraAPI.GameOptions; @@ -26,20 +27,23 @@ public static class GameModeOption get => OptionBehaviour != null ? OptionBehaviour.GetInt() - : _lastValue; + : LastValue; private set { - _lastValue = value; + LastValue = value; if (OptionBehaviour == null) return; OptionBehaviour.Value = value; OptionBehaviour.UpdateValue(); - _lastValue = value; + LastValue = value; } } internal static StringOption OptionBehaviour { get; set; } = null!; - internal static int _lastValue; + [SuppressMessage("Critical Code Smell", "S2223:Non-constant static fields should not be visible", Justification = "Internal behaviour that does not need property-level validation.")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")] // why so many warnings??? + internal static int LastValue; + internal static readonly StringNames GamemodeName = MiraLocaleManager.GetOrCreateLocaleString("Gamemode"); internal static readonly StringNames CustomName = MiraLocaleManager.GetOrCreateLocaleString("Custom"); internal static readonly Dictionary Values = new() @@ -103,7 +107,7 @@ public static class GameModeOption Value = val; var previousMode = CustomGameModeManager.ActiveMode; CustomGameModeManager.GetAndSetGameMode(); - HudPatches.SetGameModeText(CustomGameModeManager.GetMode(Values.ElementAt(_lastValue).Key).ColoredName); + HudPatches.SetGameModeText(CustomGameModeManager.GetMode(Values.ElementAt(LastValue).Key).ColoredName); var gm = CustomGameModeManager.ActiveMode!; if (gm != previousMode) { @@ -112,8 +116,7 @@ public static class GameModeOption GamemodeName, gm.ColoredName, new Color(0.7333f, 0.7333f, 0.7333f, 1), - gm.TmpIcon, - true); + gm.TmpIcon); if (MenuState.Instance) { // should force reset roles for gamemodes properly @@ -130,21 +133,22 @@ public static class GameModeOption [HarmonyPrefix] private static bool ValueChanged(GameOptionsMenu __instance, OptionBehaviour option) { - if (OptionBehaviour.Equals(option)) + if (!OptionBehaviour.Equals(option)) + return true; + + Info($"Game mode changed to {option.GetInt()}"); + RpcSyncGamemode(PlayerControl.LocalPlayer, option.GetInt()); + + if (GameSettingMenu.Instance && CustomGameModeManager.ActiveMode != null) { - Info($"Game mode changed to {option.GetInt()}"); - RpcSyncGamemode(PlayerControl.LocalPlayer, option.GetInt()); - if (GameSettingMenu.Instance && CustomGameModeManager.ActiveMode != null) - { - GameOptionsMenuPatch.ToggleGamemodeOptions(CustomGameModeManager.ActiveMode, __instance); - GameSettingMenu.Instance.RoleSettingsButton.gameObject.SetActive(CustomGameModeManager.ActiveMode.ShowNormalRoleSettings); - } - return false; + GameOptionsMenuPatch.ToggleGamemodeOptions(CustomGameModeManager.ActiveMode, __instance); + GameSettingMenu.Instance.RoleSettingsButton.gameObject.SetActive(CustomGameModeManager.ActiveMode.ShowNormalRoleSettings); } - return true; + return false; } - [MethodRpc((uint) MiraRpc.SyncGamemodeOption)] + [MethodRpc((uint)MiraRpc.SyncGamemodeOption)] + [SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Intentionally unused because the main intent is for it to be used by dependent mods to add to a blacklist.")] internal static void RpcSyncGamemode(PlayerControl host, int data) { Set(data); diff --git a/MiraAPI/GameModes/HideAndSeekMode.cs b/MiraAPI/GameModes/HideAndSeekMode.cs index 705b29b..1f95c73 100644 --- a/MiraAPI/GameModes/HideAndSeekMode.cs +++ b/MiraAPI/GameModes/HideAndSeekMode.cs @@ -1,6 +1,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; using AmongUs.Data; using AmongUs.GameOptions; @@ -30,52 +32,70 @@ public class HideAndSeekMode : AbstractGameMode /// public override string Description => "MiraApi.Gamemode.HideAndSeek.Description"; + /// // TODO: Once the Hide n Seek port is ready for release, we will remove this. public override bool HideMode => !MiraApiPlugin.IsDevBuild; + /// public override Color Color { get; } = new Color32(255, 88, 90, 255); - public override LoadableAsset? Icon => MiraAssets.HnSGamemodeIcon; + + /// + public override LoadableAsset Icon => MiraAssets.HnSGamemodeIcon; + + /// + public override bool ShowGameModeIntroCutscene => true; + + /// + public override bool GameModeBodyTypeOverride => true; + + /// + public override bool ShowNormalGameSettings => false; + + /// + public override bool ShowNormalRoleSettings => false; + + /// + public override float DefaultImpostorKillCooldown => 1f; + + /// + public override bool ShowTaskBar => false; + + /// public override bool CanReport(DeadBody body) { return false; } + /// public override bool ShouldShowSabotageMap(MapBehaviour map) { return false; } - public override bool ShowGameModeIntroCutscene => true; - public override bool GameModeBodyTypeOverride => true; - public override bool ShowNormalGameSettings => false; - public override bool ShowNormalRoleSettings => false; - public override float DefaultImpostorKillCooldown => 1f; - - public override bool ShowTaskBar => false; - public static int ImpostorPlayerID() + private static int ImpostorPlayerID() { return OptionGroupSingleton.Instance.SelectedSeeker.Value; } - public static bool HasImpostorPlayerID() + private static bool HasImpostorPlayerID() { return ImpostorPlayerID() > -1; } - public static bool ValidateImpostorPlayerID(List players) + private static bool ValidateImpostorPlayerID(List players) { - return HasImpostorPlayerID() && players.Find((NetworkedPlayerInfo p) => (int)p.PlayerId == ImpostorPlayerID()) != null; + return HasImpostorPlayerID() && players.Find(p => p.PlayerId == ImpostorPlayerID()) != null; } + /// public override void AssignRoles(out bool runOriginal, LogicRoleSelectionNormal instance) { runOriginal = false; Il2CppSystem.Collections.Generic.List list = new(); AmongUsClient.Instance.GetAllClients(list); - List list2 = list.ToArray() + List list2 = [.. list.ToArray() .Where(c => c.Character != null && c.Character.Data != null && !c.Character.Data.Disconnected && - !c.Character.Data.IsDead).OrderBy(c => c.Id).Select(c => c.Character.Data) - .ToList(); + !c.Character.Data.IsDead).OrderBy(c => c.Id).Select(c => c.Character.Data)]; foreach (NetworkedPlayerInfo networkedPlayerInfo in GameData.Instance.AllPlayers) { @@ -90,7 +110,7 @@ public class HideAndSeekMode : AbstractGameMode AssignRolesForTeam(list2, currentGameOptions, RoleTeamTypes.Crewmate, int.MaxValue, RoleTypes.Engineer); } - public static void AssignRolesForTeam( + private static void AssignRolesForTeam( List players, IGameOptions opts, RoleTeamTypes team, @@ -102,7 +122,8 @@ public class HideAndSeekMode : AbstractGameMode IRoleOptionsCollection roleOptions = opts.RoleOptions; var source = RoleManager.Instance.AllRoles.ToArray() .Where(role => role.TeamType == team && !RoleManager.IsGhostRole(role.Role) && - CustomRoleUtils.CanSpawnOnCurrentMode(role)); + CustomRoleUtils.CanSpawnOnCurrentMode(role)) + .ToList(); var assignmentData = source.Where(x => !x.IsDead).Select(role => new RoleManager.RoleAssignmentData( role, @@ -110,7 +131,7 @@ public class HideAndSeekMode : AbstractGameMode roleOptions.GetChancePerGame(role.Role))).ToList(); var source2 = CustomRoleUtils.GetPossibleRoles(assignmentData, x => x.Chance == 100); var guaranteedRoles = source.Where(x => source2.Contains(((ushort)x.Role, 100))); - List list = new List(); + List list = []; if (team == RoleTeamTypes.Crewmate) { Error($"MiraAPI.Patches.Roles.LogicRoleSelectionHnsPatch - AssignRolesForTeam: Before Guaranteed Assignment"); @@ -168,10 +189,10 @@ public class HideAndSeekMode : AbstractGameMode var newImpostors = new List(); // Specified Seeker if (HasImpostorPlayerID() && - ValidateImpostorPlayerID(players) && + ValidateImpostorPlayerID(players) && !AmongUsClient.Instance.IsGamePublic) { - NetworkedPlayerInfo networkedPlayerInfo = players.ToArray() + NetworkedPlayerInfo networkedPlayerInfo = players .First(p => p.PlayerId == ImpostorPlayerID()); players.Remove(networkedPlayerInfo); newImpostors.Add(networkedPlayerInfo); @@ -183,8 +204,8 @@ public class HideAndSeekMode : AbstractGameMode int num2 = 0; while (num2 < teamMax && players.Count > 0) { - PseudoRandomList pseudoRandomList = new PseudoRandomList(AmongUsClient.Instance.GameId); - players.Do(x => pseudoRandomList.Add(x)); + PseudoRandomList pseudoRandomList = new(AmongUsClient.Instance.GameId); + players.Do(pseudoRandomList.Add); for (int i = 0; i < GameData.RoundsPlayedInSession; i++) { pseudoRandomList.PickRandom(); @@ -244,7 +265,7 @@ public class HideAndSeekMode : AbstractGameMode } } - public static void AssignRolesFromList(List players, int teamMax, List roleList, ref int rolesAssigned) + private static void AssignRolesFromList(List players, int teamMax, List roleList, ref int rolesAssigned) { while (roleList.Count > 0 && players.Count > 0 && rolesAssigned < teamMax) { @@ -252,62 +273,56 @@ public class HideAndSeekMode : AbstractGameMode RoleTypes roleType = roleList[index]; roleList.RemoveAt(index); int index2 = HashRandom.FastNext(players.Count); - players[index2].Object.RpcSetRole(roleType, false); + players[index2].Object.RpcSetRole(roleType); players.RemoveAt(index2); rolesAssigned++; } } - public override IEnumerator IntroCutscene(IntroCutscene __instance) + /// + public override IEnumerator IntroCutscene(IntroCutscene introCutscene) { - SoundManager.Instance.PlaySound(__instance.IntroStinger, false, 1f, null); - Logger.GlobalInstance.Info("IntroCutscene :: CoBegin() :: Game Mode: Hide and Seek (MiraAPI)", null); - __instance.LogPlayerRoleData(); - __instance.HideAndSeekPanels.SetActive(true); + SoundManager.Instance.PlaySound(introCutscene.IntroStinger, false); + Logger.GlobalInstance.Info("IntroCutscene :: CoBegin() :: Game Mode: Hide and Seek (MiraAPI)"); + introCutscene.LogPlayerRoleData(); + introCutscene.HideAndSeekPanels.SetActive(true); if (PlayerControl.LocalPlayer.Data.Role.IsImpostor) { - __instance.CrewmateRules.SetActive(false); - __instance.ImpostorRules.SetActive(true); + introCutscene.CrewmateRules.SetActive(false); + introCutscene.ImpostorRules.SetActive(true); } else { - __instance.CrewmateRules.SetActive(true); - __instance.ImpostorRules.SetActive(false); + introCutscene.CrewmateRules.SetActive(true); + introCutscene.ImpostorRules.SetActive(false); } - __instance.ImpostorName.gameObject.SetActive(true); - __instance.ImpostorTitle.gameObject.SetActive(true); - __instance.BackgroundBar.enabled = false; - __instance.TeamTitle.gameObject.SetActive(false); + introCutscene.ImpostorName.gameObject.SetActive(true); + introCutscene.ImpostorTitle.gameObject.SetActive(true); + introCutscene.BackgroundBar.enabled = false; + introCutscene.TeamTitle.gameObject.SetActive(false); var impostor = PlayerControl.AllPlayerControls.ToArray().FirstOrDefault(x => x.Data.Role.IsImpostor); if (impostor == null) { - Logger.GlobalInstance.Error("IntroCutscene :: CoBegin() :: impostor is NULL", null); + Logger.GlobalInstance.Error("IntroCutscene :: CoBegin() :: impostor is NULL"); } GameManager.Instance.SetSpecialCosmetics(impostor); - if (impostor != null) - { - __instance.ImpostorName.text = impostor.Data.PlayerName; - } - else - { - __instance.ImpostorName.text = "???"; - } + introCutscene.ImpostorName.text = impostor != null ? impostor.Data.PlayerName : "???"; yield return new WaitForSecondsRealtime(0.1f); if (impostor != null) { - __instance.ImpostorTitle.text = impostor.Data.Role.GetRoleName(); + introCutscene.ImpostorTitle.text = impostor.Data.Role.GetRoleName(); } - PoolablePlayer playerSlot = null; + PoolablePlayer? playerSlot = null; if (impostor != null) { - playerSlot = __instance.CreatePlayer(1, 1, impostor.Data, false); + playerSlot = introCutscene.CreatePlayer(1, 1, impostor.Data, false); playerSlot.SetBodyType(PlayerBodyTypes.Normal); playerSlot.SetFlipX(false); - playerSlot.transform.localPosition = __instance.impostorPos; - playerSlot.transform.localScale = Vector3.one * __instance.impostorScale; + playerSlot.transform.localPosition = introCutscene.impostorPos; + playerSlot.transform.localScale = Vector3.one * introCutscene.impostorScale; } yield return ShipStatus.Instance.CosmeticsCache.PopulateFromPlayers(); @@ -317,45 +332,43 @@ public class HideAndSeekMode : AbstractGameMode playerSlot.gameObject.SetActive(false); } - __instance.HideAndSeekPanels.SetActive(false); - __instance.CrewmateRules.SetActive(false); - __instance.ImpostorRules.SetActive(false); + introCutscene.HideAndSeekPanels.SetActive(false); + introCutscene.CrewmateRules.SetActive(false); + introCutscene.ImpostorRules.SetActive(false); HnsMusicHandler.Instance.StartMusicWithIntro(); var hideTimer = 10f; if (PlayerControl.LocalPlayer.Data.Role.IsImpostor) { - __instance.HideAndSeekTimerText.gameObject.SetActive(true); + introCutscene.HideAndSeekTimerText.gameObject.SetActive(true); PoolablePlayer poolablePlayer; AnimationClip anim; if (AprilFoolsMode.ShouldHorseAround()) { - poolablePlayer = __instance.HorseWrangleVisualSuit; + poolablePlayer = introCutscene.HorseWrangleVisualSuit; poolablePlayer.gameObject.SetActive(true); poolablePlayer.SetBodyType(PlayerBodyTypes.Seeker); - anim = __instance.HnSSeekerSpawnHorseAnim; - __instance.HorseWrangleVisualPlayer.SetBodyType(PlayerBodyTypes.Normal); - __instance.HorseWrangleVisualPlayer.UpdateFromPlayerData( + anim = introCutscene.HnSSeekerSpawnHorseAnim; + introCutscene.HorseWrangleVisualPlayer.SetBodyType(PlayerBodyTypes.Normal); + introCutscene.HorseWrangleVisualPlayer.UpdateFromPlayerData( PlayerControl.LocalPlayer.Data, PlayerControl.LocalPlayer.CurrentOutfitType, PlayerMaterial.MaskType.None, - false, - null, false); } else if (AprilFoolsMode.ShouldLongAround()) { - poolablePlayer = __instance.HideAndSeekPlayerVisual; + poolablePlayer = introCutscene.HideAndSeekPlayerVisual; poolablePlayer.gameObject.SetActive(true); poolablePlayer.SetBodyType(PlayerBodyTypes.LongSeeker); - anim = __instance.HnSSeekerSpawnLongAnim; + anim = introCutscene.HnSSeekerSpawnLongAnim; } else { - poolablePlayer = __instance.HideAndSeekPlayerVisual; + poolablePlayer = introCutscene.HideAndSeekPlayerVisual; poolablePlayer.gameObject.SetActive(true); poolablePlayer.SetBodyType(PlayerBodyTypes.Seeker); - anim = __instance.HnSSeekerSpawnAnim; + anim = introCutscene.HnSSeekerSpawnAnim; } poolablePlayer.SetBodyCosmeticsVisible(false); @@ -363,16 +376,14 @@ public class HideAndSeekMode : AbstractGameMode PlayerControl.LocalPlayer.Data, PlayerControl.LocalPlayer.CurrentOutfitType, PlayerMaterial.MaskType.None, - false, - null, false); SpriteAnim component = poolablePlayer.GetComponent(); poolablePlayer.gameObject.SetActive(true); poolablePlayer.ToggleName(false); - component.Play(anim, 1f); + component.Play(anim); while (hideTimer > 0f) { - __instance.HideAndSeekTimerText.text = Mathf.RoundToInt(hideTimer).ToString(); + introCutscene.HideAndSeekTimerText.text = Mathf.RoundToInt(hideTimer).ToString(CultureInfo.InvariantCulture); hideTimer -= Time.deltaTime; yield return null; } @@ -384,27 +395,29 @@ public class HideAndSeekMode : AbstractGameMode { if (impostor != null) { - impostor.AnimateCustom(__instance.HnSSeekerSpawnHorseInGameAnim); + impostor.AnimateCustom(introCutscene.HnSSeekerSpawnHorseInGameAnim); } } else if (AprilFoolsMode.ShouldLongAround()) { if (impostor != null) { - impostor.AnimateCustom(__instance.HnSSeekerSpawnLongInGameAnim); + impostor.AnimateCustom(introCutscene.HnSSeekerSpawnLongInGameAnim); } } else if (impostor != null) { - impostor.AnimateCustom(__instance.HnSSeekerSpawnAnim); + impostor.AnimateCustom(introCutscene.HnSSeekerSpawnAnim); impostor.cosmetics.SetBodyCosmeticsVisible(false); } } ShipStatus.Instance.StartSFX(); HnsMusicHandler.Instance.OnGameStart(); HnsDangerMeter.Instance.OnGameStart(); - UnityEngine.Object.Destroy(__instance.gameObject); + UnityEngine.Object.Destroy(introCutscene.gameObject); } + + /// public override void Initialize() { deadPlayerCount = 0; @@ -417,9 +430,11 @@ public class HideAndSeekMode : AbstractGameMode HudManager.Instance.gameObject.AddComponent(); } } + + /// public override MapOptions GetMapOptions() { - MapOptions mapOptions = new MapOptions + MapOptions mapOptions = new() { Mode = MapOptions.Modes.Normal, }; @@ -433,14 +448,16 @@ public class HideAndSeekMode : AbstractGameMode return mapOptions; } + /// public override void CheckGameEnd(out bool runOriginal, LogicGameFlowNormal instance) { runOriginal = false; - if (Helpers.GetAlivePlayers().Count(x => x.Data.Role.IsImpostor) == 0) + var players = Helpers.GetAlivePlayers(); + if (!players.Any(x => x.Data.Role.IsImpostor)) { instance.Manager.RpcEndGame(GameOverReason.ImpostorDisconnect, !DataManager.Player.Ads.HasPurchasedAdRemoval); } - if (Helpers.GetAlivePlayers().Count(x => !x.Data.Role.IsImpostor) != 0) + if (players.Any(x => !x.Data.Role.IsImpostor)) { if (HideAndSeekHudHelper.Instance.AllTimersExpired()) { @@ -451,6 +468,8 @@ public class HideAndSeekMode : AbstractGameMode instance.Manager.RpcEndGame(GameOverReason.HideAndSeek_ImpostorsByKills, !DataManager.Player.Ads.HasPurchasedAdRemoval); } + /// + [SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "Warning cascades into forcing the entire tree to be ternary operators.")] public override PlayerBodyTypes GetBodyType(PlayerControl player) { if (player == null || player.Data == null || player.Data.Role == null) @@ -490,6 +509,8 @@ public class HideAndSeekMode : AbstractGameMode return PlayerBodyTypes.Normal; } } + + /// public override void UpdateTaskPanel(TaskPanelBehaviour instance) { instance.background.transform.localScale = (instance.taskText.textBounds.size.x > 0f) @@ -513,14 +534,9 @@ public class HideAndSeekMode : AbstractGameMode var xPos = -instance.background.sprite.bounds.size.x * instance.background.transform.localScale.x; instance.closedPosition = new Vector3(xPos, yPos, instance.closedPosition.z); instance.openPosition = new Vector3(instance.openPosition.x, yPos, instance.openPosition.z); - if (instance.open) - { - instance.timer = Mathf.Min(1f, instance.timer + Time.deltaTime / instance.animationTimeSeconds); - } - else - { - instance.timer = Mathf.Max(0f, instance.timer - Time.deltaTime / instance.animationTimeSeconds); - } + instance.timer = instance.open + ? Mathf.Min(1f, instance.timer + Time.deltaTime / instance.animationTimeSeconds) + : Mathf.Max(0f, instance.timer - Time.deltaTime / instance.animationTimeSeconds); Vector3 relativePos = new( Mathf.SmoothStep(instance.closedPosition.x, instance.openPosition.x, instance.timer), @@ -529,7 +545,10 @@ public class HideAndSeekMode : AbstractGameMode instance.transform.localPosition = AspectPosition.ComputePosition(AspectPosition.EdgeAlignments.LeftTop, relativePos); } + private int deadPlayerCount; + + /// public override void OnPlayerDeath(PlayerControl player, bool assignGhostRole) { base.OnPlayerDeath(player, assignGhostRole); diff --git a/MiraAPI/GameOptions/AbstractOptionGroup.cs b/MiraAPI/GameOptions/AbstractOptionGroup.cs index 9ed2352..0045c52 100644 --- a/MiraAPI/GameOptions/AbstractOptionGroup.cs +++ b/MiraAPI/GameOptions/AbstractOptionGroup.cs @@ -87,11 +87,11 @@ public abstract class AbstractOptionGroup : AbstractOptionGroup where T : IOp get { var type = typeof(T); - if (type == typeof(BaseModifier)) + if (typeof(BaseModifier).IsAssignableFrom(type)) { return MenuCategory.Modifiers; } - else if (type == typeof(RoleBehaviour)) + else if (typeof(RoleBehaviour).IsAssignableFrom(type)) { return MenuCategory.Roles; } @@ -104,7 +104,7 @@ public abstract class AbstractOptionGroup : 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. /// /// The custom role that the group is for. -public abstract class AbstractRoleOptionGroup() : AbstractOptionGroup where T : ICustomRole +public abstract class AbstractRoleOptionGroup : AbstractOptionGroup where T : ICustomRole { /// public override Type OptionableType => typeof(T); diff --git a/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs b/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs index 8dc4b26..55bb9d1 100644 --- a/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs +++ b/MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs @@ -8,6 +8,9 @@ namespace MiraAPI.GameOptions.Attributes; /// /// Attribute for creating a . /// +/// The title of the option. +/// The type. +/// An option list of string values to use in place of the name. [AttributeUsage(AttributeTargets.Property)] public class ModdedEnumOptionAttribute(string title, Type enumType, string[]? values = null) : ModdedOptionAttribute(title) diff --git a/MiraAPI/GameOptions/Attributes/ModdedNumberOptionAttribute.cs b/MiraAPI/GameOptions/Attributes/ModdedNumberOptionAttribute.cs index d0b95d5..1d9e7da 100644 --- a/MiraAPI/GameOptions/Attributes/ModdedNumberOptionAttribute.cs +++ b/MiraAPI/GameOptions/Attributes/ModdedNumberOptionAttribute.cs @@ -9,6 +9,13 @@ namespace MiraAPI.GameOptions.Attributes; /// /// Attribute for a . /// +/// The option title. +/// The minimum value. +/// The maximum value. +/// The increment. +/// The suffix type. +/// Optional format string for the option screen. +/// Flag indicating whether 0 means infinity. [AttributeUsage(AttributeTargets.Property)] public class ModdedNumberOptionAttribute( string title, diff --git a/MiraAPI/GameOptions/ModdedOptionsManager.cs b/MiraAPI/GameOptions/ModdedOptionsManager.cs index 00af52b..f1dea2c 100644 --- a/MiraAPI/GameOptions/ModdedOptionsManager.cs +++ b/MiraAPI/GameOptions/ModdedOptionsManager.cs @@ -46,9 +46,8 @@ public static class ModdedOptionsManager /// A flag that indicates if a notification sound should be played. public static void AddSettingsChangeMessage(NotificationPopper notif, StringNames key, string value, Color textColor, TMP_SpriteAsset? sprite, bool playSound = true) { - string item; var text = textColor.ToTextColor(); - item = sprite != null + var item = sprite != null ? TranslationController.Instance.GetString( StringNames.LobbyChangeSettingNotification, string.Concat( @@ -187,7 +186,7 @@ public static class ModdedOptionsManager RegisterOption(option, group, property.Name, pluginInfo); } - internal static void RegisterOption( + private static void RegisterOption( IModdedOption option, AbstractOptionGroup group, string propertyName, diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs index a578ac1..3a96ca0 100644 --- a/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs +++ b/MiraAPI/GameOptions/OptionTypes/ModdedStringOption.cs @@ -30,14 +30,14 @@ public class ModdedStringOption : ModdedOption /// /// The option's string value. /// The option's value in the index. - public int GetIndex(string value, int location) + public int GetIndex(string value) { if (Values.Contains(value)) { - return Values.ToList().IndexOf(value); + return Array.IndexOf(Values, value); } - Info($"Cannot find a valid index for {value} in {location}. Returning 0 instead. Values: {string.Join(", ", Values)}"); - return 0; + Info($"Cannot find a valid index for {value}. Returning -1 instead. Values: {string.Join(", ", Values)}"); + return -1; } /// @@ -54,10 +54,10 @@ public class ModdedStringOption : ModdedOption var newVals = Values.ToList(); newVals.Insert(index, value); - Values = newVals.ToArray(); + Values = [.. newVals]; var newStrVals = StringNameValues.ToList(); newStrVals.Insert(index, MiraLocaleManager.GetOrCreateLocaleString(value)); - StringNameValues = newStrVals.ToArray(); + StringNameValues = [.. newStrVals]; } if (Data != null) @@ -65,14 +65,14 @@ public class ModdedStringOption : ModdedOption var data = (StringGameSetting)Data; data.Values = StringNameValues; - data.Index = GetIndex(Value, 1); + data.Index = GetIndex(Value); if (OptionBehaviour != null) { var strOpt = OptionBehaviour.TryCast(); if (strOpt != null) { strOpt.Values = StringNameValues; - strOpt.Value = GetIndex(Value, 2); + strOpt.Value = GetIndex(Value); Warning("StringOption is valid"); } else @@ -100,7 +100,7 @@ public class ModdedStringOption : ModdedOption /// The default value as a string. /// An option list of string values to use. /// Whether to include this option in the preset or not. - public ModdedStringOption(string title, string defaultValue, string[] values, bool includeInPreset=true) : base(title, defaultValue, includeInPreset) + public ModdedStringOption(string title, string defaultValue, string[] values, bool includeInPreset = true) : base(title, defaultValue, includeInPreset) { Values = values; Data = ScriptableObject.CreateInstance(); @@ -108,10 +108,10 @@ public class ModdedStringOption : ModdedOption data.Title = StringName; data.Type = global::OptionTypes.String; - StringNameValues = values.Select(MiraLocaleManager.GetOrCreateLocaleString).ToArray(); + StringNameValues = [.. values.Select(MiraLocaleManager.GetOrCreateLocaleString)]; data.Values = StringNameValues; - data.Index = GetIndex(Value, 3); + data.Index = GetIndex(Value); } /// @@ -124,10 +124,10 @@ public class ModdedStringOption : ModdedOption stringOption.SetUpFromData(Data, 20); stringOption.OnValueChanged = (Il2CppSystem.Action)ValueChanged; - // SetUpFromData method doesnt work correctly so we must set the values manually + // SetUpFromData method doesn't work correctly so we must set the values manually stringOption.Title = StringName; stringOption.Values = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray(0); - stringOption.Value = GetIndex(Value, 4); + stringOption.Value = GetIndex(Value); OptionBehaviour = stringOption; ModdedOptionsManager.CreatedStringOptions.TryAdd(stringOption, this); @@ -162,7 +162,7 @@ public class ModdedStringOption : ModdedOption /// protected override void OnValueChanged(string newValue) { - HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(GetIndex(newValue, 5)), false); + HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(GetIndex(newValue)), false); if (!OptionBehaviour) { return; @@ -170,7 +170,7 @@ public class ModdedStringOption : ModdedOption if (OptionBehaviour is StringOption opt) { - opt.Value = GetIndex(newValue, 5); + opt.Value = GetIndex(newValue); } } } diff --git a/MiraAPI/HnsReimplemented/HideAndSeekHudHelper.cs b/MiraAPI/HnsReimplemented/HideAndSeekHudHelper.cs index b708148..899f4ef 100644 --- a/MiraAPI/HnsReimplemented/HideAndSeekHudHelper.cs +++ b/MiraAPI/HnsReimplemented/HideAndSeekHudHelper.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Linq; using BepInEx.Unity.IL2CPP.Utils.Collections; using Il2CppInterop.Runtime.Attributes; @@ -10,44 +11,57 @@ using UnityEngine; namespace MiraAPI.HnsReimplemented; +/// +/// A Unity script designed to help manage the HUD during HnS mode. +/// +/// The pointer of this instance's equivalent in the Il2Cpp domain. [RegisterInIl2Cpp] +[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity Convention.")] public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) { + /// + /// Gets the instance of the HnS hud helper. + /// public static HideAndSeekHudHelper Instance { get; private set; } - public AudioClip FinalHideAlertSfx; + private AudioClip finalHideAlertSfx; + private AudioClip finalHideCountdownSfx; + [SuppressMessage("Style", "IDE0052:Remove unread private members", Justification = "Ignore for now; tentative code.")] + private AudioClip taskFinishedSound; - public AudioClip FinalHideCountdownSfx; - - private AudioClip TaskFinishedSound; - - private const int SECONDS_TO_BEEP = 10; - - private const float SECONDS_TO_SET_DIRTY = 1f; - - private HideAndSeekTimerBar timerBar; + // private const int SECONDS_TO_BEEP = 10; + // private const float SECONDS_TO_SET_DIRTY = 1f; private float totalHideTime = float.MaxValue; - private float currentHideTime = float.MaxValue; - private float totalFinalHideTime = float.MaxValue; - private float currentFinalHideTime = float.MaxValue; private float secondsSinceLastSetDirty; private Coroutine beepCoroutine; + private HideAndSeekTimerBar timerBar; + private float taskDirtyTimer; + + /// + /// Gets or sets the hide countdown timer. + /// + public float HideCountdown { get; set; } + + /// + /// Gets a value indicating whether the game has reached the final phase. + /// + public bool IsFinalCountdown => currentHideTime <= 0f; private void Awake() { Instance = this; } - public bool IsFinalCountdown - { - get { return currentHideTime <= 0f; } - } - + /// + /// Checks to see if the player can use the Seeker admin. + /// + /// The player to check. + /// true if the player can use the admin ability. public bool SeekerAdminMapEnabled(PlayerControl player) { int item = Helpers.GetAlivePlayers().Count(x => !x.Data.Role.IsImpostor); @@ -59,6 +73,10 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) (GameData.Instance.PlayerCount - 1) / 3)); } + /// + /// A event that is called when a task is completed. + /// + /// The amount of time to deduct from the timer. public void OnTaskComplete(float timeDeduction) { if (timerBar != null) @@ -69,24 +87,36 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) AdjustEscapeTimer(timeDeduction, true); } - public float GetTotalRoundTime() + /// + /// Gets the match duration. + /// + /// The match duration in seconds. + public static float GetTotalRoundTime() { float escapeTime = OptionGroupSingleton.Instance.HidingTime.Value; float finalCountdownTime = OptionGroupSingleton.Instance.FinalHideTime.Value; return escapeTime + finalCountdownTime; } + /// + /// Gets the amount of total time remaining in the current round. + /// + /// The remaining time in seconds. public float GetTotalTimeRemaining() { return currentHideTime + currentFinalHideTime; } + /// + /// Gets how much time has passed since the start of the round. + /// + /// The elapsed time in seconds. public float GetRoundTimeElapsed() { return GetTotalRoundTime() - GetTotalTimeRemaining(); } - public void Start() + private void Start() { totalHideTime = OptionGroupSingleton.Instance.HidingTime.Value; currentHideTime = totalHideTime; @@ -97,19 +127,19 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) Object.Destroy(timerBar); } - FinalHideAlertSfx = GameManagerCreator.Instance.HideAndSeekManagerPrefab.FinalHideAlertSFX; - FinalHideCountdownSfx = GameManagerCreator.Instance.HideAndSeekManagerPrefab.FinalHideCountdownSFX; - TaskFinishedSound = GameManagerCreator.Instance.HideAndSeekManagerPrefab.TaskFinishedSound; - timerBar = Object.Instantiate( + finalHideAlertSfx = GameManagerCreator.Instance.HideAndSeekManagerPrefab.FinalHideAlertSFX; + finalHideCountdownSfx = GameManagerCreator.Instance.HideAndSeekManagerPrefab.FinalHideCountdownSFX; + taskFinishedSound = GameManagerCreator.Instance.HideAndSeekManagerPrefab.TaskFinishedSound; + timerBar = Instantiate( GameManagerCreator.Instance.HideAndSeekManagerPrefab.TimerBarPrefab, HudManager.Instance.transform.parent); } - public void OnGameEnd() + private void OnGameEnd() { if (timerBar != null) { - Object.Destroy(timerBar.gameObject); + Destroy(timerBar.gameObject); } if (beepCoroutine != null) @@ -119,10 +149,8 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) beepCoroutine = null!; } - private float taskDirtyTimer; - public float HideCountdown { get; set; } - public void LateUpdate() + private void LateUpdate() { if (!HudManager.InstanceExists) { @@ -178,9 +206,11 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) HudManager.Instance.TaskPanel.SetTaskText(HudManager.Instance.tasksString.ToString()); } } - public void FixedUpdate() + + private void FixedUpdate() { secondsSinceLastSetDirty += Time.fixedDeltaTime; + if (IsFinalCountdown) { AdjustFinalEscapeTimer(Time.fixedDeltaTime); @@ -190,11 +220,11 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) AdjustEscapeTimer(Time.fixedDeltaTime, false); } - public void OnDestroy() + private void OnDestroy() { if (timerBar != null) { - Object.Destroy(timerBar); + Destroy(timerBar); } } @@ -205,7 +235,7 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) if (!playerControl.Data.Role.IsImpostor && !playerControl.Data.IsDead) { playerControl.ClearTasks(); - PlayerTask.GetOrCreateTask(playerControl, 0).Text = + PlayerTask.GetOrCreateTask(playerControl).Text = DestroyableSingleton.Instance.GetString(StringNames.HideActionButton); } } @@ -220,7 +250,7 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) } timerBar.StartFinalHide(); - SoundManager.Instance.PlaySound(FinalHideAlertSfx, false, 1f, null); + SoundManager.Instance.PlaySound(finalHideAlertSfx, false); DestroyableSingleton.Instance.SetAlertOverlay(true); } @@ -253,7 +283,7 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) { float num = currentHideTime / 10f; float pitch = 1.5f - num / 2f; - SoundManager.Instance.PlaySoundImmediate(FinalHideCountdownSfx, false, 1f, pitch, null); + SoundManager.Instance.PlaySoundImmediate(finalHideCountdownSfx, false, 1f, pitch); yield return new WaitForSeconds(1f); } @@ -262,11 +292,9 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) { float num2 = currentFinalHideTime / 10f; float pitch2 = 1.5f - num2 / 2f; - SoundManager.Instance.PlaySoundImmediate(FinalHideCountdownSfx, false, 1f, pitch2, null); + SoundManager.Instance.PlaySoundImmediate(finalHideCountdownSfx, false, 1f, pitch2); yield return new WaitForSeconds(1f); } - - yield break; } private void AdjustFinalEscapeTimer(float timeDeduction) @@ -280,6 +308,10 @@ public sealed class HideAndSeekHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) } } + /// + /// Checks to see if all timers have expired. + /// + /// true if all times have expired. public bool AllTimersExpired() { return currentHideTime <= 0f && currentFinalHideTime <= 0f; diff --git a/MiraAPI/HnsReimplemented/HnsDangerMeter.cs b/MiraAPI/HnsReimplemented/HnsDangerMeter.cs index d36c198..aa73fad 100644 --- a/MiraAPI/HnsReimplemented/HnsDangerMeter.cs +++ b/MiraAPI/HnsReimplemented/HnsDangerMeter.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using MiraAPI.GameOptions; using MiraAPI.HnsReimplemented.Options; @@ -8,19 +9,22 @@ using UnityEngine; namespace MiraAPI.HnsReimplemented; +/// +/// A Unity script designed to mimic the base game's player danger meter during Hide and Seek. +/// +/// The pointer of this instance's equivalent in the Il2Cpp domain. [RegisterInIl2Cpp] +[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity Convention.")] public sealed class HnsDangerMeter(nint cppPtr) : MonoBehaviour(cppPtr) { - public static HnsDangerMeter Instance; - - private void Awake() - { - Instance = this; - } + /// + /// Gets the instance of the danger meter. + /// + public static HnsDangerMeter Instance { get; private set; } private DangerMeter dangerMeter; - private List impostors = []; + private List? impostors = []; private float scaryMusicDistance; @@ -34,7 +38,12 @@ public sealed class HnsDangerMeter(nint cppPtr) : MonoBehaviour(cppPtr) private float firstCrossfadeCountdown; - public void FixedUpdate() + private void Awake() + { + Instance = this; + } + + private void FixedUpdate() { PlayerControl localPlayer = PlayerControl.LocalPlayer; if (impostors == null || localPlayer == null) @@ -50,13 +59,12 @@ public sealed class HnsDangerMeter(nint cppPtr) : MonoBehaviour(cppPtr) float num = float.MaxValue; foreach (PlayerControl playerControl in impostors) { - if (!(playerControl == null)) + if (playerControl == null) + continue; + float sqrMagnitude = (playerControl.transform.position - localPlayer.transform.position).sqrMagnitude; + if (sqrMagnitude < scaryMusicDistance && num > sqrMagnitude) { - float sqrMagnitude = (playerControl.transform.position - localPlayer.transform.position).sqrMagnitude; - if (sqrMagnitude < scaryMusicDistance && num > sqrMagnitude) - { - num = sqrMagnitude; - } + num = sqrMagnitude; } } @@ -71,7 +79,7 @@ public sealed class HnsDangerMeter(nint cppPtr) : MonoBehaviour(cppPtr) { firstMusicActivation = false; firstCrossfadeCountdown = 3f; - HnsMusicHandler.Instance.SetMusicCrossfadeSpeed(0.6f); + HnsMusicHandler.Instance.SetMusicCrossFadeSpeed(0.6f); } if (firstCrossfadeCountdown > 0f) @@ -79,7 +87,7 @@ public sealed class HnsDangerMeter(nint cppPtr) : MonoBehaviour(cppPtr) firstCrossfadeCountdown -= Time.deltaTime; if (firstCrossfadeCountdown <= 0f) { - HnsMusicHandler.Instance.SetMusicCrossfadeSpeed(5f); + HnsMusicHandler.Instance.SetMusicCrossFadeSpeed(5f); } } @@ -115,6 +123,9 @@ public sealed class HnsDangerMeter(nint cppPtr) : MonoBehaviour(cppPtr) dangerMeter.SetDangerValue(dangerLevel1, dangerLevel2); } + /// + /// An event that is executed when the game starts. + /// public void OnGameStart() { firstMusicActivation = true; @@ -124,19 +135,15 @@ public sealed class HnsDangerMeter(nint cppPtr) : MonoBehaviour(cppPtr) dangerMeter.gameObject.SetActive(true); } - impostors = Helpers.GetAlivePlayers().Where(x => x.Data.Role.IsImpostor).ToList(); + impostors = [.. Helpers.GetAlivePlayers().Where(x => x.Data.Role.IsImpostor)]; var baseSpeed = OptionGroupSingleton.Instance.PlayerSpeed.Value; - scaryMusicDistance = 55f * - baseSpeed; - veryScaryMusicDistance = 15f * - baseSpeed; - if (scaryMusicDistance < veryScaryMusicDistance) - { - float num = veryScaryMusicDistance; - float num2 = scaryMusicDistance; - scaryMusicDistance = num; - veryScaryMusicDistance = num2; - } + scaryMusicDistance = 55f * baseSpeed; + veryScaryMusicDistance = 15f * baseSpeed; + if (scaryMusicDistance >= veryScaryMusicDistance) return; + float num = veryScaryMusicDistance; + float num2 = scaryMusicDistance; + scaryMusicDistance = num; + veryScaryMusicDistance = num2; } } diff --git a/MiraAPI/HnsReimplemented/HnsMusicHandler.cs b/MiraAPI/HnsReimplemented/HnsMusicHandler.cs index e3b7d68..868ee9e 100644 --- a/MiraAPI/HnsReimplemented/HnsMusicHandler.cs +++ b/MiraAPI/HnsReimplemented/HnsMusicHandler.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Amongus.GameModes.HideAndSeek; using MiraAPI.GameOptions; using MiraAPI.HnsReimplemented.Options; @@ -7,15 +8,18 @@ using UnityEngine; namespace MiraAPI.HnsReimplemented; +/// +/// A Unity script designed to handle the music during Hide and Seek. +/// +/// The pointer of this instance's equivalent in the Il2Cpp domain. [RegisterInIl2Cpp] +[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity convention.")] public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr) { - public static HnsMusicHandler Instance; - - private void Awake() - { - Instance = this; - } + /// + /// Gets the instance of the music handler. + /// + public static HnsMusicHandler Instance { get; private set; } private HideAndSeekMusicCollection musicCollection; @@ -41,18 +45,46 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr) private float musicLerpSpeed = 5f; - public void Start() + private readonly Dictionary musicNames = new() + { + { + LogicHnSMusic.HideAndSeekMusicTrack.Normal, + "HnS_Music_Normal" + }, + { + LogicHnSMusic.HideAndSeekMusicTrack.Task, + "HnS_Music_Task" + }, + { + LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel1, + "HnS_Music_DangerLevel1" + }, + { + LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel2, + "HnS_Music_DangerLevel2" + }, + }; + + private void Awake() + { + Instance = this; + } + + private void Start() { musicCollection = GameManagerCreator.Instance.HideAndSeekManagerPrefab.MusicCollection; } + /// + /// An event that is executed when the round starts. + /// public void OnGameStart() { InitMusic(); ResetMusic(); } - public void OnDestroy() + private void OnDestroy() { ResetMusic(); } @@ -107,6 +139,9 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr) SyncMusic(); } + /// + /// Gets the music with the intro. + /// public void StartMusicWithIntro() { if (PlayerControl.LocalPlayer.Data.Role.IsImpostor) @@ -123,12 +158,16 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr) } } + /// + /// Sets the current task state to alter music behaviour. + /// + /// The new value of the state. public void SetTaskState(bool isDoingTask) { - isDoingTask = isDoingTask; + this.isDoingTask = isDoingTask; } - public void FixedUpdate() + private void FixedUpdate() { if (normalSource == null || taskSource == null || dangerLevel1Source == null || dangerLevel2Source == null) @@ -167,16 +206,28 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr) lastMusicSyncTime = Time.unscaledTime; } + /// + /// Resets the music currently playing. + /// public void ResetMusic() { SetMusicValues(0f, 0f); } - public void SetMusicCrossfadeSpeed(float lerpSpeed) + /// + /// Sets the music crossfade speed. + /// + /// The new speed. + public void SetMusicCrossFadeSpeed(float lerpSpeed) { musicLerpSpeed = lerpSpeed; } + /// + /// Sets the current music value based on the danger level. + /// + /// The first danger level. + /// The second danger level. public void SetMusicValues(float dangerLevel1, float dangerLevel2) { if (PlayerControl.LocalPlayer != null && PlayerControl.LocalPlayer.Data.Role.IsImpostor) @@ -190,8 +241,8 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr) return; } - normalVolume = (isDoingTask ? 0f : 1f); - taskVolume = (isDoingTask ? 1f : 0f); + normalVolume = isDoingTask ? 0f : 1f; + taskVolume = isDoingTask ? 1f : 0f; dangerLevel1Volume = 0f; dangerLevel2Volume = 0f; if (dangerLevel1 > 0f) @@ -213,25 +264,4 @@ public sealed class HnsMusicHandler(nint cppPtr) : MonoBehaviour(cppPtr) dangerLevel1Volume = 1f - dangerLevel2; } } - - private readonly Dictionary musicNames = - new Dictionary - { - { - LogicHnSMusic.HideAndSeekMusicTrack.Normal, - "HnS_Music_Normal" - }, - { - LogicHnSMusic.HideAndSeekMusicTrack.Task, - "HnS_Music_Task" - }, - { - LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel1, - "HnS_Music_DangerLevel1" - }, - { - LogicHnSMusic.HideAndSeekMusicTrack.DangerLevel2, - "HnS_Music_DangerLevel2" - }, - }; } diff --git a/MiraAPI/HnsReimplemented/Options/HnsCrewmateOptions.cs b/MiraAPI/HnsReimplemented/Options/HnsCrewmateOptions.cs index cf1a7c6..2dfcf3f 100644 --- a/MiraAPI/HnsReimplemented/Options/HnsCrewmateOptions.cs +++ b/MiraAPI/HnsReimplemented/Options/HnsCrewmateOptions.cs @@ -5,12 +5,17 @@ using MiraAPI.Utilities; namespace MiraAPI.HnsReimplemented.Options; -/// +/// +/// Gets or sets the crewmate options for Hide and Seek. +/// public class HnsCrewmateOptions : AbstractOptionGroup { /// public override string GroupName => "Crewmates"; + /// + /// Gets or sets the player speed. + /// public ModdedNumberOption PlayerSpeed { get; set; } = new( "Player Speed", 1f, @@ -22,6 +27,9 @@ public class HnsCrewmateOptions : AbstractOptionGroup MiraNumberSuffixes.Multiplier, "0.00"); + /// + /// Gets or sets the hiding time. + /// public ModdedNumberOption HidingTime { get; set; } = new( "Hiding Time", 200, @@ -32,6 +40,9 @@ public class HnsCrewmateOptions : AbstractOptionGroup "#", MiraNumberSuffixes.Seconds); + /// + /// Gets or sets the limits of a crewmate's vision. + /// public ModdedNumberOption CrewmateVision { get; set; } = new( "Crewmate Vision", 0.6f, @@ -43,33 +54,16 @@ public class HnsCrewmateOptions : AbstractOptionGroup MiraNumberSuffixes.Multiplier, "0.00"); - public ModdedNumberOption MaxVentUses { get; set; } = new( - "Max Vent Uses", - 1, - 0, - 5, - 1, - "#", - "#", - MiraNumberSuffixes.None); - - public ModdedNumberOption MaxTimeInVent { get; set; } = new( - "Max Time in Vent", - 3, - 1, - 10, - 1, - "#", - "#", - MiraNumberSuffixes.Seconds) - { - Visible = () => (int)OptionGroupSingleton.Instance.MaxVentUses.Value > 0, - }; - + /// + /// Gets or sets a flag that toggles flashlight vision. + /// public ModdedToggleOption FlashlightMode { get; set; } = new( "Flashlight Mode", true); + /// + /// Gets or sets the range of a crewmate's flashlight. + /// public ModdedNumberOption CrewmateFlashlightSize { get; set; } = new( "Crewmate Flashlight Size", 0.35f, @@ -83,6 +77,38 @@ public class HnsCrewmateOptions : AbstractOptionGroup Visible = () => OptionGroupSingleton.Instance.FlashlightMode.Value, }; + /// + /// Gets or sets the maximum number of times a crewmate can vent. + /// + public ModdedNumberOption MaxVentUses { get; set; } = new( + "Max Vent Uses", + 1, + 0, + 5, + 1, + "#", + "#", + MiraNumberSuffixes.None); + + /// + /// Gets or sets the maximum amount of time a crewmate can spend inside a vent. + /// + public ModdedNumberOption MaxTimeInVent { get; set; } = new( + "Max Time in Vent", + 3, + 1, + 10, + 1, + "#", + "#", + MiraNumberSuffixes.Seconds) + { + Visible = () => (int)OptionGroupSingleton.Instance.MaxVentUses.Value > 0, + }; + + /// + /// Gets or sets the visibility of player names. + /// public ModdedToggleOption ShowNames { get; set; } = new( "Show Names", false); diff --git a/MiraAPI/HnsReimplemented/Options/HnsFinalHideOptions.cs b/MiraAPI/HnsReimplemented/Options/HnsFinalHideOptions.cs index 009b248..cfecee7 100644 --- a/MiraAPI/HnsReimplemented/Options/HnsFinalHideOptions.cs +++ b/MiraAPI/HnsReimplemented/Options/HnsFinalHideOptions.cs @@ -5,12 +5,17 @@ using MiraAPI.Utilities; namespace MiraAPI.HnsReimplemented.Options; -/// +/// +/// Gets or sets the Final Hide options for Hide and Seek. +/// public class HnsFinalHideOptions : AbstractOptionGroup { /// public override string GroupName => "Final Hide"; + /// + /// Gets or sets the duration of the Final Hide phase. + /// public ModdedNumberOption FinalHideTime { get; set; } = new( "Hiding Time", 50, @@ -21,10 +26,9 @@ public class HnsFinalHideOptions : AbstractOptionGroup "#", MiraNumberSuffixes.Seconds); - public ModdedToggleOption FinalHidePings { get; set; } = new( - "Final Hide Pings", - true); - + /// + /// Gets or sets the Seeker's speed when the Final Hide phase begins. + /// public ModdedNumberOption FinalHideImpostorSpeed { get; set; } = new( "Final Hide Impostor Speed", 1.2f, @@ -36,6 +40,16 @@ public class HnsFinalHideOptions : AbstractOptionGroup MiraNumberSuffixes.Multiplier, "0.00"); + /// + /// Gets or sets whether the Seeker sees the Final hide player pings. + /// + public ModdedToggleOption FinalHidePings { get; set; } = new( + "Final Hide Pings", + true); + + /// + /// Gets or sets the interval between each ping. + /// public ModdedNumberOption PingInterval { get; set; } = new( "Ping Interval", 6, @@ -46,6 +60,9 @@ public class HnsFinalHideOptions : AbstractOptionGroup "#", MiraNumberSuffixes.Seconds); + /// + /// Gets or sets whether the Seeker can see players on an admin map. + /// public ModdedToggleOption FinalHideSeekMap { get; set; } = new( "Final Hide Seek Map", true); diff --git a/MiraAPI/HnsReimplemented/Options/HnsImpostorOptions.cs b/MiraAPI/HnsReimplemented/Options/HnsImpostorOptions.cs index c0c61b5..59adaf2 100644 --- a/MiraAPI/HnsReimplemented/Options/HnsImpostorOptions.cs +++ b/MiraAPI/HnsReimplemented/Options/HnsImpostorOptions.cs @@ -5,15 +5,23 @@ using MiraAPI.Utilities; namespace MiraAPI.HnsReimplemented.Options; -/// +/// +/// Gets or sets the seeker settings on Hide and Seek. +/// public class HnsImpostorOptions : AbstractOptionGroup { /// public override string GroupName => "Impostors"; + /// + /// Gets or sets the player who will be the seeker. + /// public ModdedPlayerOption SelectedSeeker { get; set; } = new( "Forced Impostor"); + /// + /// Gets or sets the range of a seeker's vision. + /// public ModdedNumberOption ImpostorVision { get; set; } = new( "Impostor Vision", 0.6f, @@ -25,6 +33,9 @@ public class HnsImpostorOptions : AbstractOptionGroup MiraNumberSuffixes.Multiplier, "0.00"); + /// + /// Gets or sets the range of a seeker's flashlight. + /// public ModdedNumberOption ImpostorFlashlightSize { get; set; } = new( "Impostor Flashlight Size", 0.35f, diff --git a/MiraAPI/HnsReimplemented/Options/HnsTaskOptions.cs b/MiraAPI/HnsReimplemented/Options/HnsTaskOptions.cs index 7be2864..923763d 100644 --- a/MiraAPI/HnsReimplemented/Options/HnsTaskOptions.cs +++ b/MiraAPI/HnsReimplemented/Options/HnsTaskOptions.cs @@ -5,12 +5,17 @@ using MiraAPI.Utilities; namespace MiraAPI.HnsReimplemented.Options; -/// +/// +/// Gets or sets the task options for Hide and Seek. +/// public class HnsTaskOptions : AbstractOptionGroup { /// public override string GroupName => "Tasks"; + /// + /// Gets or sets the umber of common tasks. + /// public ModdedNumberOption CommonTasks { get; set; } = new( "# Common Tasks", 1, @@ -21,6 +26,9 @@ public class HnsTaskOptions : AbstractOptionGroup "#", MiraNumberSuffixes.None); + /// + /// Gets or sets the number of long tasks. + /// public ModdedNumberOption LongTasks { get; set; } = new( "# Long Tasks", 1, @@ -31,6 +39,9 @@ public class HnsTaskOptions : AbstractOptionGroup "#", MiraNumberSuffixes.None); + /// + /// Gets or sets the number of short tasks. + /// public ModdedNumberOption ShortTasks { get; set; } = new( "# Short Tasks", 2, diff --git a/MiraAPI/Hud/CustomPlayerMenu.cs b/MiraAPI/Hud/CustomPlayerMenu.cs index c94e355..be5714c 100644 --- a/MiraAPI/Hud/CustomPlayerMenu.cs +++ b/MiraAPI/Hud/CustomPlayerMenu.cs @@ -9,7 +9,6 @@ using Reactor.Utilities.Attributes; using Reactor.Utilities.Extensions; using UnityEngine; using UnityEngine.Events; -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member namespace MiraAPI.Hud; @@ -21,6 +20,8 @@ namespace MiraAPI.Hud; [SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Unity Convention.")] [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Unity Convention.")] [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Unity Convention.")] +[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity convention.")] +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member (Justification: Unity fields to mirror base game ShapeshifterMinigame; not worth documenting) public class CustomPlayerMenu(IntPtr il2CppPtr) : Minigame(il2CppPtr) { public ShapeshifterPanel panelPrefab; @@ -68,7 +69,6 @@ public class CustomPlayerMenu(IntPtr il2CppPtr) : Minigame(il2CppPtr) return customMenu; } - [SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity convention.")] private void OnDisable() { ControllerManager.Instance.CloseOverlayMenu(name); diff --git a/MiraAPI/Hud/MiraHudHelper.cs b/MiraAPI/Hud/MiraHudHelper.cs index b072dc8..5f3ed20 100644 --- a/MiraAPI/Hud/MiraHudHelper.cs +++ b/MiraAPI/Hud/MiraHudHelper.cs @@ -1,4 +1,5 @@ -using BepInEx.Unity.IL2CPP.Utils.Collections; +using System.Diagnostics.CodeAnalysis; +using BepInEx.Unity.IL2CPP.Utils.Collections; using InnerNet; using MiraAPI.LocalSettings; using MiraAPI.Modifiers.ModifierDisplay; @@ -9,9 +10,13 @@ using UnityEngine; namespace MiraAPI.Hud; [RegisterInIl2Cpp] -public sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) +[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity Convention.")] +[SuppressMessage("Critical Code Smell", "S2223:Non-constant static fields should not be visible", Justification = "Is internal code. Property-level protections are not required.")] +[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")] +internal sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) { public static MiraHudHelper Instance { get; private set; } + public static GameObject ModifierDisplayObject; public static GameObject VanillaMatchInfoButton; public static bool ModifierDisplayOnRight; @@ -25,20 +30,25 @@ public sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) public static GameObject SubmergedFloorButton; public static SpriteRenderer SubmergedFloorButtonRenderer; public static SpriteRenderer SubmergedFloorButtonRendererHover; - public void Awake() + + public static readonly Vector3 BelowOptionPos = new(0.435f, 1.25f, 0f); + public static readonly Vector3 FullTopPos = new(0.435f, 0.475f, 0f); + + private void Awake() { Instance = this; } - public void Start() + private void Start() { MiraApiSettings.OldButtonScaleFactor = LocalSettingsTabSingleton.Instance.TopRightButtonsFactorSlider.Value; StartCoroutine(MiraApiSettings.CoResizeSettingsUI().WrapToIl2Cpp()); } -#pragma warning disable S2325 - #pragma warning disable CA1822 - public void FixedUpdate() + + [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Unity script method.")] + [SuppressMessage("Minor Code Smell", "S2325:Methods and properties that don't access instance data should be static", Justification = "Read above.")] + private void FixedUpdate() { if (!HudManager.InstanceExists || !PlayerControl.LocalPlayer || !PlayerControl.LocalPlayer.Data) { @@ -60,11 +70,7 @@ public sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) } UpdateSubmergedButtons(instance); } - #pragma warning restore CA1822 - #pragma warning restore S2325 - public static Vector3 BelowOptionPos = new(0.435f, 1.25f, 0f); - public static Vector3 FullTopPos = new(0.435f, 0.475f, 0f); public static void CreateUiRow(HudManager instance) { if (!UiTopRight) @@ -129,75 +135,74 @@ public sealed class MiraHudHelper(nint cppPtr) : MonoBehaviour(cppPtr) instance.Chat.chatNotifyDot = iconContainer.transform.GetChild(0).GetComponent(); } - if (UiTopRight && UiGrid) + if (!UiTopRight || !UiGrid) + return; + + var isChatButtonVisible = HudManager.Instance.Chat.isActiveAndEnabled; + instance.Chat.chatButton.gameObject.SetActive(isChatButtonVisible); + if (VanillaMatchInfoButton) { - var isChatButtonVisible = HudManager.Instance.Chat.isActiveAndEnabled; - instance.Chat.chatButton.gameObject.SetActive(isChatButtonVisible); - if (VanillaMatchInfoButton) - { - VanillaMatchInfoButton.SetActive(!GameSettingMenu.Instance && !Minigame.Instance); - } + VanillaMatchInfoButton.SetActive(!GameSettingMenu.Instance && !Minigame.Instance); } } + public static void UpdateSubmergedButtons(HudManager instance) { - if (ModCompatibility.IsSubmerged() && !SubmergedFloorButton && ExtraUiTopRight) - { - if (!SubmergedFloorButton && ExtraUiTopRight) - { - var transform = instance.MapButton.transform.parent.Find(instance.MapButton.name + "(Clone)"); - if (transform != null) - { - SubmergedFloorButton = transform.gameObject; - SubmergedFloorButton.transform.SetParent(ExtraUiTopRight.transform, false); + if (!ModCompatibility.IsSubmerged() || SubmergedFloorButton || !ExtraUiTopRight || SubmergedFloorButton || !ExtraUiTopRight) + return; - SubmergedFloorButtonRenderer = - SubmergedFloorButton.transform.Find("Inactive").GetComponent(); - SubmergedFloorButtonRendererHover = - SubmergedFloorButton.transform.Find("Active").GetComponent(); + var transform = instance.MapButton.transform.parent.Find(instance.MapButton.name + "(Clone)"); + if (transform == null) + return; - MiraApiSettings.SetUpButtonPositions(); - } - } - } + SubmergedFloorButton = transform.gameObject; + SubmergedFloorButton.transform.SetParent(ExtraUiTopRight.transform, false); + + SubmergedFloorButtonRenderer = + SubmergedFloorButton.transform.Find("Inactive").GetComponent(); + SubmergedFloorButtonRendererHover = + SubmergedFloorButton.transform.Find("Active").GetComponent(); + + MiraApiSettings.SetUpButtonPositions(); } public static void AdjustModifierTab() { - if (!ModifierDisplayObject && UiTopRight && ExtraUiTopRight && ModifierDisplayComponent.Instance) + if (ModifierDisplayObject || !UiTopRight || !ExtraUiTopRight || !ModifierDisplayComponent.Instance) + return; + + ModifierDisplayObject = ModifierDisplayComponent.Instance?.gameObject ?? null!; + ModifierDisplayOnRight = !LocalSettingsTabSingleton.Instance.ModifiersHudLeftSide.Value; + if (ModifierDisplayOnRight) { - ModifierDisplayObject = ModifierDisplayComponent.Instance?.gameObject ?? null!; - ModifierDisplayOnRight = !LocalSettingsTabSingleton.Instance.ModifiersHudLeftSide.Value; - if (ModifierDisplayOnRight) - { - ModifierDisplayObject.transform.SetParent(ExtraUiTopRight.transform, false); - ModifierDisplayObject.GetComponent().Destroy(); - var oldPos = ModifierDisplayObject.transform.GetChild(0).localPosition; - ModifierDisplayObject.transform.GetChild(0).localPosition = new Vector3(-1.1757f, -2.1633f, oldPos.z); - oldPos = ModifierDisplayObject.transform.GetChild(1).localPosition; - ModifierDisplayObject.transform.GetChild(1).localPosition = new Vector3(-0.45f, 0.3f, oldPos.z); - } - MiraApiSettings.SetUpButtonPositions(); + ModifierDisplayObject.transform.SetParent(ExtraUiTopRight.transform, false); + ModifierDisplayObject.GetComponent().Destroy(); + var oldPos = ModifierDisplayObject.transform.GetChild(0).localPosition; + ModifierDisplayObject.transform.GetChild(0).localPosition = new Vector3(-1.1757f, -2.1633f, oldPos.z); + oldPos = ModifierDisplayObject.transform.GetChild(1).localPosition; + ModifierDisplayObject.transform.GetChild(1).localPosition = new Vector3(-0.45f, 0.3f, oldPos.z); } + MiraApiSettings.SetUpButtonPositions(); } + public static void CreateNewUiRow(HudManager instance) { - if (!ExtraUiTopRight && UiTopRight) + if (ExtraUiTopRight || !UiTopRight) + return; + + ExtraUiTopRight = new GameObject("ExtraUiTopRight") { - ExtraUiTopRight = new GameObject("ExtraUiTopRight") - { - layer = UiTopRight.layer, - }; - ExtraUiTopRight.transform.SetParent(instance.MapButton.transform.parent.parent, false); + layer = UiTopRight.layer, + }; + ExtraUiTopRight.transform.SetParent(instance.MapButton.transform.parent.parent, false); - ExtraUiGrid = ExtraUiTopRight.AddComponent(); - ExtraUiAspectPos = ExtraUiTopRight.AddComponent(); + ExtraUiGrid = ExtraUiTopRight.AddComponent(); + ExtraUiAspectPos = ExtraUiTopRight.AddComponent(); - ExtraUiGrid.Alignment = GridArrange.StartAlign.Left; - ExtraUiGrid.CellSize = new Vector2(0.85f, 0.85f); - ExtraUiAspectPos.Alignment = AspectPosition.EdgeAlignments.RightTop; - ExtraUiAspectPos.DistanceFromEdge = BelowOptionPos; - ExtraUiGrid.Start(); - } + ExtraUiGrid.Alignment = GridArrange.StartAlign.Left; + ExtraUiGrid.CellSize = new Vector2(0.85f, 0.85f); + ExtraUiAspectPos.Alignment = AspectPosition.EdgeAlignments.RightTop; + ExtraUiAspectPos.DistanceFromEdge = BelowOptionPos; + ExtraUiGrid.Start(); } } diff --git a/MiraAPI/LocalSettings/Attributes/LocalToggleSettingAttribute.cs b/MiraAPI/LocalSettings/Attributes/LocalToggleSettingAttribute.cs index fb90f77..31d35a3 100644 --- a/MiraAPI/LocalSettings/Attributes/LocalToggleSettingAttribute.cs +++ b/MiraAPI/LocalSettings/Attributes/LocalToggleSettingAttribute.cs @@ -7,6 +7,8 @@ namespace MiraAPI.LocalSettings.Attributes; /// /// Creates a for the . /// +/// The name of the setting. +/// The description of the setting. [AttributeUsage(AttributeTargets.Property)] public class LocalToggleSettingAttribute( string? name = null, diff --git a/MiraAPI/LocalSettings/LocalSettingsButton.cs b/MiraAPI/LocalSettings/LocalSettingsButton.cs index 747b1ce..f89329e 100644 --- a/MiraAPI/LocalSettings/LocalSettingsButton.cs +++ b/MiraAPI/LocalSettings/LocalSettingsButton.cs @@ -59,9 +59,9 @@ public class LocalSettingsButton(string text, Action onClick) button.name = Text; button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); rollover.OutColor = Tab!.TabAppearance.ButtonColor; - rollover.OverColor = Tab!.TabAppearance.ButtonHoverColor; + rollover.OverColor = Tab.TabAppearance.ButtonHoverColor; rollover.Target = background; - background.color = Tab!.TabAppearance.ButtonColor; + background.color = Tab.TabAppearance.ButtonColor; button.OnClick.AddListener((UnityAction)OnClick); background.transform.localScale = new Vector3(1, 1.25f, 1); @@ -79,6 +79,9 @@ public class LocalSettingsButton(string text, Action onClick) return button.gameObject; } + /// + /// Refreshes the button. + /// public void RefreshButton() { _btnText.text = Text.Translate(); diff --git a/MiraAPI/LocalSettings/LocalSettingsTab.cs b/MiraAPI/LocalSettings/LocalSettingsTab.cs index 5cfd25f..b4dab91 100644 --- a/MiraAPI/LocalSettings/LocalSettingsTab.cs +++ b/MiraAPI/LocalSettings/LocalSettingsTab.cs @@ -197,7 +197,7 @@ public abstract class LocalSettingsTab(ConfigFile config) ref contentOrder, contentIndex == Buttons.Count); - obj!.GetComponentsInChildren(true).Do(x => + obj.GetComponentsInChildren(true).Do(x => { x.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; x.sortingOrder = 150; @@ -277,10 +277,8 @@ public abstract class LocalSettingsTab(ConfigFile config) { if (!tabButtonObject.Content.gameObject.activeSelf) { -#pragma warning disable S125 // Sections of code should not be commented out // tabButtonObject.Button.color = TabColor; // tabButtonObject.Rollover.OutColor = TabColor; -#pragma warning restore S125 // Sections of code should not be commented out } tabButton.transform.localPosition = new Vector3(2.4f, 2.1f - tabOffset, 5.5f); diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs index 231ba86..74d88ef 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalEnumSetting.cs @@ -80,8 +80,8 @@ public class LocalEnumSetting( button.name = Name; button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); rollover.OutColor = Tab!.TabAppearance.EnumColor; - rollover.OverColor = Tab!.TabAppearance.EnumHoverColor; - background.color = Tab!.TabAppearance.EnumColor; + rollover.OverColor = Tab.TabAppearance.EnumHoverColor; + background.color = Tab.TabAppearance.EnumColor; button.OnClick.AddListener((UnityAction)(() => { diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs index 24bffae..2ef007a 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalNumberSetting.cs @@ -90,8 +90,8 @@ public class LocalNumberSetting( button.name = Name; button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); rollover.OutColor = Tab!.TabAppearance.NumberColor; - rollover.OverColor = Tab!.TabAppearance.NumberHoverColor; - background.color = Tab!.TabAppearance.NumberColor; + rollover.OverColor = Tab.TabAppearance.NumberHoverColor; + background.color = Tab.TabAppearance.NumberColor; button.OnClick.AddListener((UnityAction)(() => { diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs b/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs index e26f6ce..8e9517a 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalSettingBase.cs @@ -58,7 +58,7 @@ public abstract class LocalSettingBase : ILocalSetting public abstract void RefreshOption(); /// - /// Returns the formated string to use in the text of the setting. + /// Returns the formatted string to use in the text of the setting. /// /// The value text. protected virtual string GetValueText() diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs index 63d17e2..dc4df36 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalSliderSetting.cs @@ -79,8 +79,8 @@ public class LocalSliderSetting( newSlider.name = Name; newSlider.Range = new FloatRange(-1.5f, 1.5f); newSlider.SetValue(Mathf.InverseLerp(SliderRange.min, SliderRange.max, GetValue())); - rollover.OutColor = Tab!.TabAppearance.SliderColor; - rollover.OverColor = Tab!.TabAppearance.SliderHoverColor; + rollover.OutColor = Tab.TabAppearance.SliderColor; + rollover.OverColor = Tab.TabAppearance.SliderHoverColor; newSlider.Title.transform.localPosition = new Vector3(0.5f, 0, -1f); newSlider.Title.horizontalAlignment = DisplayValue ? HorizontalAlignmentOptions.Left : HorizontalAlignmentOptions.Center; newSlider.Title.text = GetValueText(); diff --git a/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs b/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs index ad7a868..db47e82 100644 --- a/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs +++ b/MiraAPI/LocalSettings/SettingTypes/LocalToggleSetting.cs @@ -50,13 +50,13 @@ public class LocalToggleSetting( toggleObject.name = Name.Translate(); toggleObject.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor; passiveButton.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); - rollover.OverColor = Tab!.TabAppearance.ToggleHoverColor; + rollover.OverColor = Tab.TabAppearance.ToggleHoverColor; passiveButton.OnClick.AddListener((UnityAction)(() => { SetValue(!GetValue()); toggleObject.UpdateText(GetValue()); - toggleObject.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor; + toggleObject.Background.color = GetValue() ? Tab.TabAppearance.ToggleActiveColor : Tab.TabAppearance.ToggleInactiveColor; })); passiveButton.OnMouseOver.AddListener((UnityAction)(() => { @@ -68,7 +68,7 @@ public class LocalToggleSetting( passiveButton.OnMouseOut.AddListener((UnityAction)(() => { toggleObject.UpdateText(GetValue()); - toggleObject.Background.color = GetValue() ? Tab!.TabAppearance.ToggleActiveColor : Tab!.TabAppearance.ToggleInactiveColor; + toggleObject.Background.color = GetValue() ? Tab.TabAppearance.ToggleActiveColor : Tab.TabAppearance.ToggleInactiveColor; })); Helpers.DivideSize(toggleObject.gameObject, 1.1f); diff --git a/MiraAPI/MeetingAbilities/MeetingAbilityBehaviour.cs b/MiraAPI/MeetingAbilities/MeetingAbilityBehaviour.cs index 3661b30..f26e0df 100644 --- a/MiraAPI/MeetingAbilities/MeetingAbilityBehaviour.cs +++ b/MiraAPI/MeetingAbilities/MeetingAbilityBehaviour.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Globalization; using Il2CppInterop.Runtime.Attributes; using Reactor.Utilities.Attributes; @@ -11,6 +12,7 @@ namespace MiraAPI.MeetingAbilities; /// A component for handling targeted meeting buttons. /// [RegisterInIl2Cpp] +[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity convention.")] public class MeetingAbilityBehaviour : MonoBehaviour { /// @@ -24,29 +26,29 @@ public class MeetingAbilityBehaviour : MonoBehaviour private TargetedMeetingButton _button = null!; /// - /// The of this component. + /// Gets he of this component. /// - public PassiveButton Button; + public PassiveButton Button { get; internal set; } /// - /// The parent . + /// Gets he parent . /// - public PlayerVoteArea VoteArea; + public PlayerVoteArea VoteArea { get; internal set; } /// - /// The button's component. + /// Gets he button's component. /// - public SpriteRenderer Renderer; + public SpriteRenderer Renderer { get; internal set; } /// - /// The label used for showing the ability's cooldown. + /// Gets he label used for showing the ability's cooldown. /// - public TextMeshPro CooldownText; + public TextMeshPro CooldownText { get; internal set; } /// - /// The label used for showing the ability's remaining uses. + /// Gets the label used for showing the ability's remaining uses. /// - public TextMeshPro UsesText; + public TextMeshPro UsesText { get; internal set; } /// /// Initializes the various properties of this component. @@ -61,12 +63,13 @@ public class MeetingAbilityBehaviour : MonoBehaviour _button = button; Renderer = GetComponent(); SetFillUp(1, 1); - if (!TryGetComponent(out Button)) + if (!TryGetComponent(out var but)) { Error($"Could not initialize MeetingButtonBehaviour for {Button.GetType().Name}, Destroying..."); Destroy(this); } _init = true; + Button = but; CooldownText = Instantiate(HudManager.Instance.KillButton.cooldownTimerText, transform); CooldownText.GetComponent().Destroy(); CooldownText.transform.localPosition = new Vector3(0, 0, -10); @@ -112,6 +115,11 @@ public class MeetingAbilityBehaviour : MonoBehaviour SetFillUp(_button.Timer, _button.InitialCooldown); } + /// + /// Sets the button fill up coloring based on the ratio between the time remaining and the maximum time of the button. + /// + /// The remaining timer. + /// The maximum timer. public void SetFillUp(float timer, float maxTimer) { float percentCool = Mathf.Clamp(timer / maxTimer, 0.001f, 1f); diff --git a/MiraAPI/MeetingAbilities/MeetingActionButton.cs b/MiraAPI/MeetingAbilities/MeetingActionButton.cs index 9eeb0fa..aa48f6d 100644 --- a/MiraAPI/MeetingAbilities/MeetingActionButton.cs +++ b/MiraAPI/MeetingAbilities/MeetingActionButton.cs @@ -73,17 +73,17 @@ public abstract class MeetingActionButton public int UsesSoFar { get; set; } /// - /// Gets a value determining if the abiity is disabled upon being used. + /// Gets a value indicating whether the ability is disabled upon being used. /// public virtual bool DisableUponUse => false; /// - /// Gets a value determining if the abiity is disabled upon voting. + /// Gets a value indicating whether the ability is disabled upon voting. /// public virtual bool DisableUponVoting => false; /// - /// Gets a value determining if the abiity is hidden when votes wrapping up. + /// Gets a value indicating whether the ability is hidden when votes wrapping up. /// public virtual bool HideUponWrapUp => false; diff --git a/MiraAPI/MeetingAbilities/MeetingButtonManager.cs b/MiraAPI/MeetingAbilities/MeetingButtonManager.cs index 4f5b207..02af7f5 100644 --- a/MiraAPI/MeetingAbilities/MeetingButtonManager.cs +++ b/MiraAPI/MeetingAbilities/MeetingButtonManager.cs @@ -15,12 +15,12 @@ public static class MeetingButtonManager /// /// Gets a list if==of all registered . /// - public static List TargetedButtons { get; internal set; } = new(); + public static List TargetedButtons { get; internal set; } = []; /// /// Gets a list if==of all registered . /// - public static List UntargetedButtons { get; internal set; } = new(); + public static List UntargetedButtons { get; internal set; } = []; internal static bool RegisterTargetedMeetingButton(Type type, MiraPluginInfo info) { @@ -29,7 +29,7 @@ public static class MeetingButtonManager return false; } - var button = Activator.CreateInstance(type) as TargetedMeetingButton; + var button = (Activator.CreateInstance(type) as TargetedMeetingButton)!; info.InternalTargetedMeetingButtons.Add(button); TargetedButtons.Add(button); return true; @@ -42,14 +42,15 @@ public static class MeetingButtonManager return false; } - var button = Activator.CreateInstance(type) as MeetingActionButton; + var button = (Activator.CreateInstance(type) as MeetingActionButton)!; info.InternalMeetingButtons.Add(button); UntargetedButtons.Add(button); return true; } - private static CenteredGridArrange? actionButtonsParent = null!; - + /// + /// Called on and /. + /// public static void OnGameStart() { foreach (var ability in TargetedButtons.Where(x => x.UsesMode == MeetingButtonUsesMode.PerGame)) @@ -69,7 +70,7 @@ public static class MeetingButtonManager public static void OnMeetingStart(MeetingHud meetingHud) { // Untargeted buttons parent. - actionButtonsParent = new GameObject("ActionsButtonParent").AddComponent(); + var actionButtonsParent = new GameObject("ActionsButtonParent").AddComponent(); actionButtonsParent.transform.SetParent(meetingHud.MeetingAbilityButton.transform.parent, meetingHud.MeetingAbilityButton.transform.parent); actionButtonsParent.CellSize = new Vector2(0.7f, 0.7f); actionButtonsParent.transform.localPosition = new Vector3(0, -2.1f, -10); @@ -104,7 +105,7 @@ public static class MeetingButtonManager btn2.transform.SetParent(meetingHud.SkipVoteButton.Buttons.transform); if (ability.UsesMode == MeetingButtonUsesMode.PerMeeting) ability.UsesLeft = ability.MaxUses; - if (ability is MultiTargetMeetingButton multiAbility) multiAbility.Targets = new(); + if (ability is MultiTargetMeetingButton multiAbility) multiAbility.Targets = []; } catch (Exception e) { diff --git a/MiraAPI/MeetingAbilities/MeetingButtonUsesMode.cs b/MiraAPI/MeetingAbilities/MeetingButtonUsesMode.cs index a4ddb40..4ba87b7 100644 --- a/MiraAPI/MeetingAbilities/MeetingButtonUsesMode.cs +++ b/MiraAPI/MeetingAbilities/MeetingButtonUsesMode.cs @@ -1,7 +1,17 @@ namespace MiraAPI.MeetingAbilities; +/// +/// The use mode of the meeting button. +/// public enum MeetingButtonUsesMode { + /// + /// Sets the uses to be limited per game. + /// PerGame, - PerMeeting -} \ No newline at end of file + + /// + /// Sets the uses to be limited per meeting. + /// + PerMeeting, +} diff --git a/MiraAPI/MeetingAbilities/MultiTargetMeetingButton.cs b/MiraAPI/MeetingAbilities/MultiTargetMeetingButton.cs index 7dcec24..586e3f6 100644 --- a/MiraAPI/MeetingAbilities/MultiTargetMeetingButton.cs +++ b/MiraAPI/MeetingAbilities/MultiTargetMeetingButton.cs @@ -7,12 +7,12 @@ using UnityEngine.UI; namespace MiraAPI.MeetingAbilities; /// -/// Abstract class for creating multi target meeting abilities +/// Abstract class for creating multi target meeting abilities. /// public abstract class MultiTargetMeetingButton : TargetedMeetingButton { /// - /// The used for when the button is on. + /// Gets he used for when the button is on. /// public abstract LoadableAsset SpriteActive { get; } @@ -24,7 +24,7 @@ public abstract class MultiTargetMeetingButton : TargetedMeetingButton /// /// Gets or sets all selected targets. /// - public Dictionary Targets { get; set; } = new(); + public Dictionary Targets { get; set; } = []; /// public override void ClickHandler(MeetingAbilityBehaviour button, PlayerVoteArea playerVoteArea) @@ -56,7 +56,7 @@ public abstract class MultiTargetMeetingButton : TargetedMeetingButton Timer = Cooldown; UsesLeft -= 1; OnFinish(); - Targets = new(); + Targets = []; } /// @@ -83,7 +83,7 @@ public abstract class MultiTargetMeetingButton : TargetedMeetingButton /// public override MeetingAbilityBehaviour CreateButton(PlayerVoteArea playerVoteArea) { - Targets = new(); + Targets = []; var button = base.CreateButton(playerVoteArea); button.Button.OnClick = new Button.ButtonClickedEvent(); button.Button.OnClick.AddListener(new System.Action(() => { ClickHandler(button, playerVoteArea); })); diff --git a/MiraAPI/MiraAPI.csproj b/MiraAPI/MiraAPI.csproj index 2da2adb..22e128a 100644 --- a/MiraAPI/MiraAPI.csproj +++ b/MiraAPI/MiraAPI.csproj @@ -17,5 +17,4 @@ - diff --git a/MiraAPI/MiraApiPlugin.cs b/MiraAPI/MiraApiPlugin.cs index fc3c8f1..60a2e99 100644 --- a/MiraAPI/MiraApiPlugin.cs +++ b/MiraAPI/MiraApiPlugin.cs @@ -27,14 +27,8 @@ namespace MiraAPI; [ReactorModFlags(ModFlags.RequireOnAllClients)] public partial class MiraApiPlugin : BasePlugin, IMiraPlugin { - /// - public ConfigFile GetConfigFile() - { - return Config; - } - /// - /// Gets the specified Culture for string manipulations. + /// Gets the specified Culture for string manipulations. /// public static CultureInfo Culture { get; internal set; } = new("en-US"); @@ -86,4 +80,10 @@ public partial class MiraApiPlugin : BasePlugin, IMiraPlugin ModCompatibility .Initialize; // Initialise AFTER the mods are loaded to ensure maximum parity (no need for the soft dependency either then) } + + /// + public ConfigFile GetConfigFile() + { + return Config; + } } diff --git a/MiraAPI/MiraApiSettings.cs b/MiraAPI/MiraApiSettings.cs index f14877f..ef776f0 100644 --- a/MiraAPI/MiraApiSettings.cs +++ b/MiraAPI/MiraApiSettings.cs @@ -84,16 +84,17 @@ public class MiraApiSettings(ConfigFile config) : LocalSettingsTab(config) { var topUi = MiraHudHelper.UiTopRight; var extraTopUi = MiraHudHelper.ExtraUiTopRight; - if (topUi && extraTopUi) - { - var genericEvent = new UiButtonResetEvent(); - MiraEventManager.InvokeEvent(genericEvent); - var genericEvent2 = new UiButtonPostResetEvent(topUi, extraTopUi); - MiraEventManager.InvokeEvent(genericEvent2); - MiraHudHelper.UiGrid.ArrangeChilds(); - MiraHudHelper.ExtraUiGrid.ArrangeChilds(); - } + if (!topUi || !extraTopUi) + return; + + var genericEvent = new UiButtonResetEvent(); + MiraEventManager.InvokeEvent(genericEvent); + + var genericEvent2 = new UiButtonPostResetEvent(topUi, extraTopUi); + MiraEventManager.InvokeEvent(genericEvent2); + MiraHudHelper.UiGrid.ArrangeChilds(); + MiraHudHelper.ExtraUiGrid.ArrangeChilds(); } /// diff --git a/MiraAPI/ModCompatibility.cs b/MiraAPI/ModCompatibility.cs index ebb1081..ed40be4 100644 --- a/MiraAPI/ModCompatibility.cs +++ b/MiraAPI/ModCompatibility.cs @@ -14,26 +14,44 @@ public static class ModCompatibility /// public const string SubmergedId = "Submerged"; + /// + /// Gets the of the Submerged mod. + /// public static Version SubVersion { get; private set; } + + /// + /// Gets a value indicating whether Submerged is loaded. + /// public static bool SubLoaded { get; private set; } + + /// + /// Gets the of the Submerged mod. + /// public static BasePlugin SubPlugin { get; private set; } + + /// + /// Gets the of the Submerged mod. + /// public static Assembly SubAssembly { get; private set; } + /// + /// The map ID of Submerged. + /// public const ShipStatus.MapType SubmergedMapType = (ShipStatus.MapType)6; - public static void Initialize() + internal static void Initialize() { InitSubmerged(); } - public static void InitSubmerged() + internal static void InitSubmerged() { if (!IL2CPPChainloader.Instance.Plugins.TryGetValue(SubmergedId, out var plugin)) { return; } - SubPlugin = (plugin!.Instance as BasePlugin)!; + SubPlugin = (plugin.Instance as BasePlugin)!; SubVersion = plugin.Metadata.Version; SubAssembly = SubPlugin.GetType().Assembly; @@ -42,6 +60,10 @@ public static class ModCompatibility Message("Submerged was detected"); } + /// + /// Checks to see if the current map is the Submerged map. + /// + /// true if the current map is Submerged. public static bool IsSubmerged() { return SubLoaded && ShipStatus.Instance && ShipStatus.Instance.Type == SubmergedMapType; diff --git a/MiraAPI/Modifiers/ModifierManager.cs b/MiraAPI/Modifiers/ModifierManager.cs index dc1a250..ea60a34 100644 --- a/MiraAPI/Modifiers/ModifierManager.cs +++ b/MiraAPI/Modifiers/ModifierManager.cs @@ -4,8 +4,8 @@ using System.Linq; using System.Runtime.Serialization; using MiraAPI.Modifiers.Types; using MiraAPI.PluginLoading; -using MiraAPI.Translation; using MiraAPI.Roles; +using MiraAPI.Translation; using MiraAPI.Utilities; using Reactor.Utilities.Extensions; using Random = System.Random; diff --git a/MiraAPI/Patches/Accessibility/HudManagerFlashPatches.cs b/MiraAPI/Patches/Accessibility/HudManagerFlashPatches.cs index 1043709..2ea1bdd 100644 --- a/MiraAPI/Patches/Accessibility/HudManagerFlashPatches.cs +++ b/MiraAPI/Patches/Accessibility/HudManagerFlashPatches.cs @@ -50,7 +50,7 @@ public static class HudManagerFlashPatches hudManager.FullScreen.gameObject.SetActive(settings.EnableSabotageFlashes.Value && !hudManager.FullScreen.gameObject.activeSelf); if (settings.EnableSabotageBlares.Value) { - SoundManager.Instance.PlaySound(ShipStatus.Instance.SabotageSound, false, 1f, null); + SoundManager.Instance.PlaySound(ShipStatus.Instance.SabotageSound, false); } light = !light; diff --git a/MiraAPI/Patches/DetectiveNotesMinigamePatch.cs b/MiraAPI/Patches/DetectiveNotesMinigamePatch.cs index c0b4dd0..5986675 100644 --- a/MiraAPI/Patches/DetectiveNotesMinigamePatch.cs +++ b/MiraAPI/Patches/DetectiveNotesMinigamePatch.cs @@ -1,6 +1,6 @@ -namespace MiraAPI.Patches; +/*namespace MiraAPI.Patches; -/*[HarmonyPatch(typeof(DetectiveNotesMinigame), nameof(DetectiveNotesMinigame.SetImpostorPopup))] +[HarmonyPatch(typeof(DetectiveNotesMinigame), nameof(DetectiveNotesMinigame.SetImpostorPopup))] public static class DetectiveNotesMinigamePatch { public static void Prefix(DetectiveNotesMinigame __instance, bool active) diff --git a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs index 2a58937..be33948 100644 --- a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs +++ b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs @@ -310,16 +310,12 @@ public static class TaskAdderPatches switch (task.TaskType) { case TaskTypes.DivertPower: -#pragma warning disable IDE0055 // Fix formatting - { var targetSystem = task.Cast().TargetSystem; taskAddButton.Text.text = TranslationController.Instance.GetString( StringNames.DivertPowerTo, TranslationController.Instance.GetString(targetSystem)); break; - } case TaskTypes.FixWeatherNode: - { var nodeId = task.Cast().NodeId; taskAddButton.Text.text = TranslationController.Instance.GetString( @@ -327,20 +323,16 @@ public static class TaskAdderPatches TranslationController.Instance.GetString( WeatherSwitchGame.ControlNames[nodeId]); break; - } default: - { taskAddButton.Text.text = TranslationController.Instance.GetString(task.TaskType); break; - } -#pragma warning restore IDE0055 // Fix formatting } __instance.AddFileAsChildCustom(taskAddButton, ref num, ref num2, ref num3); if (taskAddButton != null && taskAddButton.Button != null) { - ControllerManager.Instance.AddSelectableUiElement(taskAddButton.Button, false); + ControllerManager.Instance.AddSelectableUiElement(taskAddButton.Button); } } diff --git a/MiraAPI/Patches/GameModes/ConsolePatches.cs b/MiraAPI/Patches/GameModes/ConsolePatches.cs index 4427b16..b80e2b2 100644 --- a/MiraAPI/Patches/GameModes/ConsolePatches.cs +++ b/MiraAPI/Patches/GameModes/ConsolePatches.cs @@ -36,7 +36,7 @@ internal static class ConsolePatches } [HarmonyPrefix, HarmonyPatch(typeof(SystemConsole), nameof(SystemConsole.CanUse))] - public static bool SystemCanUsePatch(SystemConsole __instance, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [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) { @@ -55,7 +55,7 @@ internal static class ConsolePatches } [HarmonyPrefix, HarmonyPatch(typeof(MapConsole), nameof(MapConsole.CanUse))] - public static bool MapCanUsePatch(MapConsole __instance, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [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) { @@ -76,36 +76,21 @@ internal static class ConsolePatches [HarmonyPrefix, HarmonyPatch(typeof(MapConsole), nameof(MapConsole.Use))] public static bool MapUsePatch(MapConsole __instance) { - if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance) - { - return CustomGameModeManager.ActiveMode == null || + return AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started || !ShipStatus.Instance || CustomGameModeManager.ActiveMode == null || CustomGameModeManager.ActiveMode.CanUseMapConsole(__instance); - } - - return true; } [HarmonyPrefix, HarmonyPatch(typeof(SystemConsole), nameof(SystemConsole.Use))] public static bool SystemUsePatch(SystemConsole __instance) { - if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance) - { - return CustomGameModeManager.ActiveMode == null || + return AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started || !ShipStatus.Instance || CustomGameModeManager.ActiveMode == null || CustomGameModeManager.ActiveMode.CanUseSystemConsole(__instance); - } - - return true; } [HarmonyPrefix, HarmonyPatch(typeof(Console), nameof(Console.Use))] public static bool ConsoleUsePatch(Console __instance) { - if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance) - { - return CustomGameModeManager.ActiveMode == null || + return AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started || !ShipStatus.Instance || CustomGameModeManager.ActiveMode == null || CustomGameModeManager.ActiveMode.CanUseTasks(__instance); - } - - return true; } } diff --git a/MiraAPI/Patches/GameModes/CreateOptionsPatch.cs b/MiraAPI/Patches/GameModes/CreateOptionsPatch.cs index 7e8144e..166c2e4 100644 --- a/MiraAPI/Patches/GameModes/CreateOptionsPatch.cs +++ b/MiraAPI/Patches/GameModes/CreateOptionsPatch.cs @@ -15,4 +15,4 @@ internal static class CreateOptionsPatch // TODO: finish this return false; } -} \ No newline at end of file +} diff --git a/MiraAPI/Patches/GameModes/GameLogicPatches.cs b/MiraAPI/Patches/GameModes/GameLogicPatches.cs index 742a56c..0a482c1 100644 --- a/MiraAPI/Patches/GameModes/GameLogicPatches.cs +++ b/MiraAPI/Patches/GameModes/GameLogicPatches.cs @@ -9,22 +9,22 @@ internal static class GameLogicPatches [HarmonyPrefix, HarmonyPatch(typeof(GameManager), nameof(GameManager.DidHumansWin))] public static bool DidHumansWin(GameOverReason reason, ref bool __result) { - __result = reason == GameOverReason.CrewmatesByTask || reason == GameOverReason.CrewmatesByVote || - reason == GameOverReason.ImpostorDisconnect || reason == GameOverReason.HideAndSeek_CrewmatesByTimer; + __result = reason is GameOverReason.CrewmatesByTask or GameOverReason.CrewmatesByVote or + GameOverReason.ImpostorDisconnect or GameOverReason.HideAndSeek_CrewmatesByTimer; return false; } [HarmonyPrefix, HarmonyPatch(typeof(GameManager), nameof(GameManager.DidImpostorsWin))] public static bool DidImpostorsWin(GameOverReason reason, ref bool __result) { - __result = reason == GameOverReason.ImpostorsByKill || reason == GameOverReason.ImpostorsBySabotage || - reason == GameOverReason.ImpostorsByVote || reason == GameOverReason.HideAndSeek_ImpostorsByKills || - reason == GameOverReason.CrewmateDisconnect; + __result = reason is GameOverReason.ImpostorsByKill or GameOverReason.ImpostorsBySabotage or + GameOverReason.ImpostorsByVote or GameOverReason.HideAndSeek_ImpostorsByKills or + GameOverReason.CrewmateDisconnect; return false; } [HarmonyPrefix, HarmonyPatch(typeof(NormalGameManager), nameof(NormalGameManager.GetBodyType))] - public static bool BodyTypePatch(NormalGameManager __instance, PlayerControl player, ref PlayerBodyTypes __result) + public static bool BodyTypePatch(PlayerControl player, ref PlayerBodyTypes __result) { if (CustomGameModeManager.ActiveMode == null || !CustomGameModeManager.ActiveMode.GameModeBodyTypeOverride) { @@ -68,7 +68,7 @@ internal static class GameLogicPatches [HarmonyPostfix] [HarmonyPatch(typeof(LogicGameFlowNormal), nameof(LogicGameFlowNormal.IsGameOverDueToDeath))] - public static void IsGameOverDueToDeathPatch(LogicGameFlowNormal __instance, ref bool __result) + public static void IsGameOverDueToDeathPatch(ref bool __result) { if (CustomGameModeManager.IsActiveGameMode()) { diff --git a/MiraAPI/Patches/GameModes/GameManagerPatches.cs b/MiraAPI/Patches/GameModes/GameManagerPatches.cs index 3f56e82..e8f4500 100644 --- a/MiraAPI/Patches/GameModes/GameManagerPatches.cs +++ b/MiraAPI/Patches/GameModes/GameManagerPatches.cs @@ -53,4 +53,4 @@ internal static class GameStartManagerPatches __instance.MinPlayers = 1; } } -} \ No newline at end of file +} diff --git a/MiraAPI/Patches/GameModes/HudPatches.cs b/MiraAPI/Patches/GameModes/HudPatches.cs index dd235ed..d237967 100644 --- a/MiraAPI/Patches/GameModes/HudPatches.cs +++ b/MiraAPI/Patches/GameModes/HudPatches.cs @@ -23,7 +23,6 @@ internal static class HudPatches } } - [HarmonyPatch(typeof(HudManager), nameof(HudManager.Start))] [HarmonyPostfix] public static void PostHudStart(HudManager __instance) diff --git a/MiraAPI/Patches/GameModes/ProgressTrackerPatch.cs b/MiraAPI/Patches/GameModes/ProgressTrackerPatch.cs index 53620e0..340f1f7 100644 --- a/MiraAPI/Patches/GameModes/ProgressTrackerPatch.cs +++ b/MiraAPI/Patches/GameModes/ProgressTrackerPatch.cs @@ -2,6 +2,7 @@ using MiraAPI.GameModes; namespace MiraAPI.Patches.GameModes; + [HarmonyPatch(typeof(ProgressTracker), nameof(ProgressTracker.Start))] internal static class ProgressTrackerPatch { diff --git a/MiraAPI/Patches/GameModes/TaskPanelPatch.cs b/MiraAPI/Patches/GameModes/TaskPanelPatch.cs index 30a30cc..17ae848 100644 --- a/MiraAPI/Patches/GameModes/TaskPanelPatch.cs +++ b/MiraAPI/Patches/GameModes/TaskPanelPatch.cs @@ -2,6 +2,7 @@ using MiraAPI.GameModes; namespace MiraAPI.Patches.GameModes; + [HarmonyPatch(typeof(TaskPanelBehaviour), nameof(TaskPanelBehaviour.Update))] internal static class TaskPanelPatch { diff --git a/MiraAPI/Patches/HudManagerPatches.cs b/MiraAPI/Patches/HudManagerPatches.cs index 327fff3..f814847 100644 --- a/MiraAPI/Patches/HudManagerPatches.cs +++ b/MiraAPI/Patches/HudManagerPatches.cs @@ -112,16 +112,13 @@ public static class HudManagerPatches } catch { -#pragma warning disable S125 // Sections of code should not be commented out // Error($"Error arranging child objects in GridArrange: {e}"); -#pragma warning restore S125 // Sections of code should not be commented out } } } } } -#pragma warning disable S125 // Sections of code should not be commented out /* /// /// Trigger HudStart on current custom gamemode @@ -133,7 +130,6 @@ public static class HudManagerPatches CustomGameModeManager.ActiveMode?.HudStart(__instance); } */ -#pragma warning restore S125 // Sections of code should not be commented out [HarmonyPrefix] [HarmonyPriority(Priority.First)] @@ -371,10 +367,7 @@ public static class HudManagerPatches } } - // suppressed warning because we want minimum allocations here -#pragma warning disable S3267 foreach (var entry in KeybindManager.VanillaKeybinds.Values) -#pragma warning restore S3267 { if (player.GetButtonDown(entry.Id)) { diff --git a/MiraAPI/Patches/IntroCutscenePatches.cs b/MiraAPI/Patches/IntroCutscenePatches.cs index c42ce9f..b70964d 100644 --- a/MiraAPI/Patches/IntroCutscenePatches.cs +++ b/MiraAPI/Patches/IntroCutscenePatches.cs @@ -3,8 +3,8 @@ using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using MiraAPI.Events; using MiraAPI.Events.Vanilla.Gameplay; -using MiraAPI.MeetingAbilities; using MiraAPI.GameModes; +using MiraAPI.MeetingAbilities; using MiraAPI.Roles; using MiraAPI.Translation; using MiraAPI.Utilities; diff --git a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs index 0f526d2..4172758 100644 --- a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs +++ b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs @@ -25,12 +25,12 @@ namespace MiraAPI.Patches.Options; [HarmonyPatch(typeof(GameOptionsMenu))] internal static class GameOptionsMenuPatch { - private static List _vanillaHeaders = new(); - private static List _vanillaOptions = new(); - private static List _mainOptions = new(); - private static System.Collections.Generic.Dictionary> _gameModeGroups = new(); - private static System.Collections.Generic.Dictionary> _gameModeOptions = new(); - private static System.Collections.Generic.Dictionary> _gameModeHeaders = new(); + private static readonly List _vanillaHeaders = new(); + private static readonly List _vanillaOptions = new(); + private static readonly List _mainOptions = new(); + private static readonly System.Collections.Generic.Dictionary> _gameModeGroups = []; + private static readonly System.Collections.Generic.Dictionary> _gameModeOptions = []; + private static readonly System.Collections.Generic.Dictionary> _gameModeHeaders = []; private static TextMeshPro _gamemodeDescription = null!; private static SpriteRenderer _modIcon = null!; @@ -77,7 +77,8 @@ internal static class GameOptionsMenuPatch return false; } - public static float AdditionalVanillaScrollNum; + private static float additionalVanillaScrollNum; + internal static void ToggleGamemodeOptions(AbstractGameMode gameMode, GameOptionsMenu instance) { float num = -1.217f; @@ -185,7 +186,6 @@ internal static class GameOptionsMenuPatch instance.scrollBar.SetYBoundsMax(-num - 1.65f); } - private static void CreateSettings(GameOptionsMenu instance, Transform container) { float num = 0.713f; @@ -200,21 +200,17 @@ internal static class GameOptionsMenuPatch gmCategory.SetHeader(GameModeOption.CustomName, 20); gmCategory.transform.localScale = Vector3.one * 0.63f; gmCategory.transform.localPosition = new Vector3(-0.903f, num, -2f); - GameModeOption.OptionBehaviour = Object.Instantiate( - instance.stringOptionOrigin, - Vector3.zero, - Quaternion.identity, - container); + GameModeOption.OptionBehaviour = Object.Instantiate(instance.stringOptionOrigin, container); num -= 0.63f; GameModeOption.OptionBehaviour.transform.localPosition = new Vector3(0.952f, num, -2f); GameModeOption.OptionBehaviour.SetClickMask(instance.ButtonClickMask); StringGameSetting setting = ScriptableObject.CreateInstance(); setting.Type = OptionTypes.MultipleChoice; setting.Title = GameModeOption.GamemodeName; - setting.Index = GameModeOption._lastValue; + setting.Index = GameModeOption.LastValue; setting.Values = new Il2CppStructArray([GameModeOption.Values[0]]); GameModeOption.OptionBehaviour.SetUpFromData(setting, 20); - GameModeOption.Set(GameModeOption._lastValue); + GameModeOption.Set(GameModeOption.LastValue); GameModeOption.OptionBehaviour.TitleText.fontSize = 3; instance.Children.Add(GameModeOption.OptionBehaviour); foreach (var optionBehaviour in instance.Children) @@ -267,81 +263,47 @@ internal static class GameOptionsMenuPatch _gamemodeDescription.alignment = TextAlignmentOptions.Left; num -= 1.3f; - AdditionalVanillaScrollNum = 0f; + additionalVanillaScrollNum = 0f; foreach (RulesCategory rulesCategory in GameManager.Instance.GameSettingsList.AllCategories) { - CategoryHeaderMasked categoryHeaderMasked = Object.Instantiate( - instance.categoryHeaderOrigin, - Vector3.zero, - Quaternion.identity, - container); + var categoryHeaderMasked = Object.Instantiate(instance.categoryHeaderOrigin, container); categoryHeaderMasked.SetHeader(rulesCategory.CategoryName, 20); categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f; categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, num, -2f); _vanillaHeaders.Add(categoryHeaderMasked); num -= 0.63f; - AdditionalVanillaScrollNum -= 0.63f; + additionalVanillaScrollNum -= 0.63f; foreach (BaseGameSetting baseGameSetting in rulesCategory.AllGameSettings) { + OptionBehaviour? optionBehaviour = null; + switch (baseGameSetting.Type) { case OptionTypes.Checkbox: - { - OptionBehaviour optionBehaviour = Object.Instantiate( - instance.checkboxOrigin, - Vector3.zero, - Quaternion.identity, - container); - optionBehaviour.transform.localPosition = new Vector3(0.952f, num, -2f); - optionBehaviour.SetClickMask(instance.ButtonClickMask); - optionBehaviour.SetUpFromData(baseGameSetting, 20); - _vanillaOptions.Add(optionBehaviour); + optionBehaviour = Object.Instantiate(instance.checkboxOrigin, container); break; - } case OptionTypes.String: - { - OptionBehaviour optionBehaviour = Object.Instantiate( - instance.stringOptionOrigin, - Vector3.zero, - Quaternion.identity, - container); - optionBehaviour.transform.localPosition = new Vector3(0.952f, num, -2f); - optionBehaviour.SetClickMask(instance.ButtonClickMask); - optionBehaviour.SetUpFromData(baseGameSetting, 20); - _vanillaOptions.Add(optionBehaviour); + optionBehaviour = Object.Instantiate(instance.stringOptionOrigin, container); break; - } case OptionTypes.Float: case OptionTypes.Int: - { - OptionBehaviour optionBehaviour = Object.Instantiate( - instance.numberOptionOrigin, - Vector3.zero, - Quaternion.identity, - container); - optionBehaviour.transform.localPosition = new Vector3(0.952f, num, -2f); - optionBehaviour.SetClickMask(instance.ButtonClickMask); - optionBehaviour.SetUpFromData(baseGameSetting, 20); - _vanillaOptions.Add(optionBehaviour); + optionBehaviour = Object.Instantiate(instance.numberOptionOrigin, container); break; - } case OptionTypes.Player: - { - OptionBehaviour optionBehaviour = Object.Instantiate( - instance.playerOptionOrigin, - Vector3.zero, - Quaternion.identity, - container); - optionBehaviour.transform.localPosition = new Vector3(0.952f, num, -2f); - optionBehaviour.SetClickMask(instance.ButtonClickMask); - optionBehaviour.SetUpFromData(baseGameSetting, 20); - _vanillaOptions.Add(optionBehaviour); + optionBehaviour = Object.Instantiate(instance.playerOptionOrigin, container); break; - } } + if (!optionBehaviour) + continue; + + optionBehaviour!.transform.localPosition = new Vector3(0.952f, num, -2f); + optionBehaviour.SetClickMask(instance.ButtonClickMask); + optionBehaviour.SetUpFromData(baseGameSetting, 20); + _vanillaOptions.Add(optionBehaviour); + num -= 0.45f; - AdditionalVanillaScrollNum -= 0.45f; + additionalVanillaScrollNum -= 0.45f; } } foreach (var optionBehaviour in _vanillaOptions) @@ -363,11 +325,11 @@ internal static class GameOptionsMenuPatch var filteredGroups = ModdedOptionsManager.GameModeOptionGroups .Where(x => x.Key == mode.GetType()).Select(y => y.Value).SelectMany(y => y) ?? []; - _gameModeGroups.Add(mode, filteredGroups.ToList()); + _gameModeGroups.Add(mode, [.. filteredGroups]); var optionBehaviours = new System.Collections.Generic.List(); var categoryHeaders = new System.Collections.Generic.List(); - var newNum = mode.ShowNormalGameSettings ? num : num - AdditionalVanillaScrollNum; + var newNum = mode.ShowNormalGameSettings ? num : num - additionalVanillaScrollNum; foreach (var group in filteredGroups) { CreateGroup(instance, group, container, ref newNum, ref optionBehaviours, ref categoryHeaders); @@ -550,7 +512,7 @@ internal static class GameOptionsMenuPatch foreach (var option in group.Options) { if (option.OptionBehaviour != null && option.OptionBehaviour.gameObject != null) - option.OptionBehaviour?.gameObject.SetActive(false); + option.OptionBehaviour.gameObject.SetActive(false); } return; @@ -601,7 +563,7 @@ internal static class GameOptionsMenuPatch if (mode.ShowNormalGameSettings) { - num += AdditionalVanillaScrollNum; + num += additionalVanillaScrollNum; } if (!_gameModeGroups.TryGetValue(mode, out var groups) || groups.Count == 0) diff --git a/MiraAPI/Patches/Options/LobbyViewPanePatches.cs b/MiraAPI/Patches/Options/LobbyViewPanePatches.cs index d802921..6456a78 100644 --- a/MiraAPI/Patches/Options/LobbyViewPanePatches.cs +++ b/MiraAPI/Patches/Options/LobbyViewPanePatches.cs @@ -35,12 +35,7 @@ public static class LobbyViewPanePatches private static AbstractGameMode? GetCustomGamemode() { - if (!CustomGameModeManager.IsClassic() && !CustomGameModeManager.IsHideNSeek()) - { - return CustomGameModeManager.ActiveMode; - } - - return null; + return !CustomGameModeManager.IsClassic() && !CustomGameModeManager.IsHideNSeek() ? CustomGameModeManager.ActiveMode : null; } private static IEnumerable? GetCustomGamemodeOptions() diff --git a/MiraAPI/Patches/Options/MenuState.cs b/MiraAPI/Patches/Options/MenuState.cs index cdecfc5..e50efa7 100644 --- a/MiraAPI/Patches/Options/MenuState.cs +++ b/MiraAPI/Patches/Options/MenuState.cs @@ -7,8 +7,8 @@ using MiraAPI.GameOptions; using MiraAPI.Modifiers; using MiraAPI.PluginLoading; using MiraAPI.Presets; -using MiraAPI.Translation; using MiraAPI.Roles; +using MiraAPI.Translation; using MiraAPI.Utilities.Assets; using Reactor.Utilities.Attributes; using Reactor.Utilities.Extensions; diff --git a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs index b91e792..4790817 100644 --- a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs +++ b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs @@ -205,7 +205,7 @@ public static class RoleSettingMenuPatches foreach (var grouping in sortedRoleGroups) { if (!grouping.Any() || - grouping.All(x=> x.Configuration.HideSettings || !x.VisibleInSettings() || !x.Configuration.AssociatedGameMode.IsInstanceOfType(CustomGameModeManager.ActiveMode))) + grouping.All(x => x.Configuration.HideSettings || !x.VisibleInSettings() || !x.Configuration.AssociatedGameMode.IsInstanceOfType(CustomGameModeManager.ActiveMode))) { continue; } diff --git a/MiraAPI/Patches/RoleGuidePatches.cs b/MiraAPI/Patches/RoleGuidePatches.cs index a4878e4..5adbc9e 100644 --- a/MiraAPI/Patches/RoleGuidePatches.cs +++ b/MiraAPI/Patches/RoleGuidePatches.cs @@ -117,15 +117,15 @@ public static class RoleGuidePatches ControllerManager instance = ControllerManager.Instance; ControllerUiElementsState currentUiState = ControllerManager.Instance.CurrentUiState; Il2CppSystem.Collections.Generic.List controllerSelectable = __instance.ControllerSelectable; - instance.SetUpSelectables(currentUiState, controllerSelectable[controllerSelectable.Count - 1], __instance.ControllerSelectable); + instance.SetUpSelectables(currentUiState, controllerSelectable[^1], __instance.ControllerSelectable); ControllerManager instance2 = ControllerManager.Instance; Il2CppSystem.Collections.Generic.List controllerSelectable2 = __instance.ControllerSelectable; - instance2.SetCurrentSelected(controllerSelectable2[controllerSelectable2.Count - 1]); + instance2.SetCurrentSelected(controllerSelectable2[^1]); __instance.SetActiveTab(0); return false; } - private static Dictionary _rolePanels = []; + private static readonly Dictionary _rolePanels = []; public static void DisplayNormalRoleSettings(MatchInfoGuide instance, bool reset) { @@ -158,9 +158,9 @@ public static class RoleGuidePatches GameManager.Instance.LogicOptions.GetTaskBarMode().ToString()); foreach (RoleBehaviour roleBehaviour in RoleManager.Instance.AllRoles) { - if (roleBehaviour.Role != RoleTypes.Crewmate && roleBehaviour.Role != RoleTypes.Impostor && - roleBehaviour.Role is not RoleTypes.CrewmateGhost && - roleBehaviour.Role is not RoleTypes.ImpostorGhost) + if (roleBehaviour.Role is not RoleTypes.Crewmate and not RoleTypes.Impostor and + not RoleTypes.CrewmateGhost and + not RoleTypes.ImpostorGhost) { var panel = Object.Instantiate( instance.MatchInfoRolePanelPrefab, diff --git a/MiraAPI/Patches/Roles/HowToPlayPatch.cs b/MiraAPI/Patches/Roles/HowToPlayPatch.cs index c7cc2e5..5f4dd32 100644 --- a/MiraAPI/Patches/Roles/HowToPlayPatch.cs +++ b/MiraAPI/Patches/Roles/HowToPlayPatch.cs @@ -39,11 +39,11 @@ internal static class HowToPlayPatch { uiElement.ReceiveMouseOut(); } - ControllerManager.Instance.NewScene(__instance.name, __instance.closeButton, __instance.defaultButtonSelected, __instance.controllerSelectables, false); + ControllerManager.Instance.NewScene(__instance.name, __instance.closeButton, __instance.defaultButtonSelected, __instance.controllerSelectables); } __instance.DisableAllScenes(); __instance.roleSelectionScene.SetActive(true); - ControllerManager.Instance.SetDefaultSelection(__instance.defaultButtonSelected, null); + ControllerManager.Instance.SetDefaultSelection(__instance.defaultButtonSelected); } public static void OpenRolePage(HowToPlayScene instance, RoleTypes roleType) { diff --git a/MiraAPI/Patches/Roles/LogicRoleSelectionHnsPatch.cs b/MiraAPI/Patches/Roles/LogicRoleSelectionHnsPatch.cs index f2210ce..e297106 100644 --- a/MiraAPI/Patches/Roles/LogicRoleSelectionHnsPatch.cs +++ b/MiraAPI/Patches/Roles/LogicRoleSelectionHnsPatch.cs @@ -175,7 +175,7 @@ public static class LogicRoleSelectionHnsPatch RoleTypes roleType = roleList[index]; roleList.RemoveAt(index); int index2 = HashRandom.FastNext(players.Count); - players[index2].Object.RpcSetRole(roleType, false); + players[index2].Object.RpcSetRole(roleType); players.RemoveAt(index2); rolesAssigned++; } diff --git a/MiraAPI/Patches/Roles/SelectRolesPatch.cs b/MiraAPI/Patches/Roles/SelectRolesPatch.cs index 71c18f5..149efdf 100644 --- a/MiraAPI/Patches/Roles/SelectRolesPatch.cs +++ b/MiraAPI/Patches/Roles/SelectRolesPatch.cs @@ -123,7 +123,7 @@ public static class SelectRolesPatch RoleTypes roleType = roleList[index]; roleList.RemoveAt(index); int index2 = HashRandom.FastNext(players.Count); - players[index2].Object.RpcSetRole(roleType, false); + players[index2].Object.RpcSetRole(roleType); players.RemoveAt(index2); rolesAssigned++; } diff --git a/MiraAPI/Patches/Stubs/MinigameStubs.cs b/MiraAPI/Patches/Stubs/MinigameStubs.cs index b2e62cd..64668ea 100644 --- a/MiraAPI/Patches/Stubs/MinigameStubs.cs +++ b/MiraAPI/Patches/Stubs/MinigameStubs.cs @@ -31,6 +31,7 @@ public static class MinigameStubs [HarmonyReversePatch] [HarmonyPatch(typeof(Minigame), nameof(Minigame.Close), [])] [MethodImpl(MethodImplOptions.NoInlining)] + [SuppressMessage("Minor Code Smell", "S3878:Arrays should not be created for params parameters", Justification = "Prevents ambiguity errors.")] public static void Close(Minigame instance) { // nothing needed diff --git a/MiraAPI/PluginLoading/IMiraPlugin.cs b/MiraAPI/PluginLoading/IMiraPlugin.cs index 5cb3b99..00e3c85 100644 --- a/MiraAPI/PluginLoading/IMiraPlugin.cs +++ b/MiraAPI/PluginLoading/IMiraPlugin.cs @@ -15,9 +15,9 @@ public interface IMiraPlugin virtual bool DisplayOnOptionsMenu => true; /// - /// Gets or sets a value for the localization id to use for anything registered under this mod. + /// Gets the localization id to use for anything registered under this mod. /// - public virtual string ParentLocaleId => GetType().Name.ToLower(CultureInfo.InvariantCulture); + virtual string ParentLocaleId => GetType().Name.ToLower(CultureInfo.InvariantCulture); /// /// Gets the name to display on the options menu. diff --git a/MiraAPI/PluginLoading/MiraPluginManager.cs b/MiraAPI/PluginLoading/MiraPluginManager.cs index a56523f..36fff5e 100644 --- a/MiraAPI/PluginLoading/MiraPluginManager.cs +++ b/MiraAPI/PluginLoading/MiraPluginManager.cs @@ -41,8 +41,8 @@ public sealed class MiraPluginManager internal Dictionary> QueuedRoleRegistrations { get; } = []; internal static MiraPluginManager Instance { get; private set; } = new(); - public static ConfigFile MiraApiConfig { get; private set; } = null!; - public static MiraPluginInfo MiraApiPluginInfo { get; private set; } = null!; + internal static ConfigFile MiraApiConfig { get; private set; } = null!; + internal static MiraPluginInfo MiraApiPluginInfo { get; private set; } = null!; internal void Initialize(BasePlugin miraApiPlugin, IMiraPlugin apiPlugin) { @@ -222,7 +222,6 @@ public sealed class MiraPluginManager continue; } - if (RegisterMeetingAbility(type, info)) { continue; @@ -266,7 +265,7 @@ public sealed class MiraPluginManager // Cache all the registered plugins into an array for easy access RegisteredPlugins = [.. _registeredPlugins.Values]; RegisteredPluginsWithOptions = [.. RegisteredPlugins.Where(m => m.MiraPlugin.DisplayOnOptionsMenu)]; - PluginsWithOptionsOrGameModes = [..RegisteredPlugins.Where(m => m.MiraPlugin.DisplayOnOptionsMenu || m.GameModes.Count > 0)]; + PluginsWithOptionsOrGameModes = [.. RegisteredPlugins.Where(m => m.MiraPlugin.DisplayOnOptionsMenu || m.GameModes.Count > 0)]; ModifierManager.Modifiers = new ReadOnlyCollection(ModifierManager.InternalModifiers); }; diff --git a/MiraAPI/Presets/PresetManager.cs b/MiraAPI/Presets/PresetManager.cs index 2abe74f..9ac9a1b 100644 --- a/MiraAPI/Presets/PresetManager.cs +++ b/MiraAPI/Presets/PresetManager.cs @@ -111,17 +111,16 @@ public static class PresetManager /// public static void LoadMasterPreset() { -#pragma warning disable S125 // Sections of code should not be commented out /*foreach (var btn in plugin.InternalPresets.Select(x => x.PresetButton)) - { - if (btn != null) - { - Object.DestroyImmediate(btn); - } - } + { + if (btn != null) + { + Object.DestroyImmediate(btn); + } + } + + plugin.InternalPresets.Clear();*/ - plugin.InternalPresets.Clear();*/ -#pragma warning restore S125 // Sections of code should not be commented out if (!Directory.Exists(PresetDirectory)) { Directory.CreateDirectory(PresetDirectory); @@ -138,9 +137,7 @@ public static class PresetManager var fileName = Path.GetFileName(file); Info($"Loading preset file {fileName}"); -#pragma warning disable S125 // Sections of code should not be commented out // var presetName = Path.GetFileNameWithoutExtension(file); -#pragma warning restore S125 // Sections of code should not be commented out var presetConfig = new ConfigFile(file, false) { SaveOnConfigSet = false, @@ -160,9 +157,7 @@ public static class PresetManager presetConfig.Save(); -#pragma warning disable S125 // Sections of code should not be commented out // InternalMasterPresets.Add(new OptionPreset(presetName, plugin, presetConfig)); -#pragma warning restore S125 // Sections of code should not be commented out } MasterPresets = [.. InternalMasterPresets]; } diff --git a/MiraAPI/Translation/MiraLanguage.cs b/MiraAPI/Translation/MiraLanguage.cs index d6d2624..1c6ab83 100644 --- a/MiraAPI/Translation/MiraLanguage.cs +++ b/MiraAPI/Translation/MiraLanguage.cs @@ -6,25 +6,108 @@ namespace MiraAPI.Translation; /// public enum MiraLanguage { + /// + /// English. + /// English, + + /// + /// Latam. + /// Latam, + + /// + /// Brazilian. + /// Brazilian, + + /// + /// Portuguese. + /// Portuguese, + + /// + /// Korean. + /// Korean, + + /// + /// Russian. + /// Russian, + + /// + /// Dutch. + /// Dutch, + + /// + /// Filipino. + /// Filipino, + + /// + /// French. + /// French, + + /// + /// German. + /// German, + + /// + /// Italian. + /// Italian, + + /// + /// Japanese. + /// Japanese, + + /// + /// Spanish. + /// Spanish, + + /// + /// SChinese. + /// SChinese, + + /// + /// TChinese. + /// TChinese, + + /// + /// Irish. + /// Irish, + + /// + /// Polish. + /// Polish, + + /// + /// Turkish. + /// Turkish, + + /// + /// Swedish. + /// Swedish, + + /// + /// Lithuanian. + /// Lithuanian, + + /// + /// Czech. + /// Czech, } diff --git a/MiraAPI/Translation/MiraLocaleManager.cs b/MiraAPI/Translation/MiraLocaleManager.cs index 90f0df4..50560f1 100644 --- a/MiraAPI/Translation/MiraLocaleManager.cs +++ b/MiraAPI/Translation/MiraLocaleManager.cs @@ -5,23 +5,39 @@ using System.Linq; using System.Reflection; using System.Xml; using MiraAPI.Utilities; -using MonoMod.Utils; using Reactor.Localization.Utilities; using UnityEngine; namespace MiraAPI.Translation; +/// +/// The locale manager to handle translations and more. +/// public static class MiraLocaleManager { private const string LangDirectory = "mira_languages"; // Language, Xml Name, then Value + + /// + /// Gets the dictionary containing all loaded localization strings, organized by language and XML name. + /// public static Dictionary> Locale { get; } = []; + + /// + /// Gets the list of mod GUIDs that have been registered with the localization manager. + /// public static readonly List RegisteredModIds = []; + /// + /// Gets a dictionary mapping registered string keys to their corresponding enum values. + /// public static readonly Dictionary RegisteredStringNames = []; internal static readonly Dictionary StringNamesLookup = []; + /// + /// Gets a dictionary mapping values to their standard language codes. + /// public static Dictionary LangList { get; } = new() { { MiraLanguage.English, "en_US" }, @@ -46,6 +62,10 @@ public static class MiraLocaleManager { MiraLanguage.Lithuanian, "lt_LT" }, // Custom { MiraLanguage.Czech, "cs_CZ" }, // Custom }; + + /// + /// Gets a dictionary mapping values to their standard language codes. + /// public static Dictionary LangCultureList { get; } = new() { { MiraLanguage.English, "en-US" }, @@ -135,19 +155,13 @@ public static class MiraLocaleManager /// A based on the key provided. public static string Get(MiraLanguage language, string key, string fallback = "") { - if (Locale.TryGetValue(language, out var translations) && - translations.TryGetValue(key, out var translation)) - { - return translation; - } - - if (Locale.TryGetValue(MiraLanguage.English, out var translationsEng) && - translationsEng.TryGetValue(key, out var translationEng)) - { - return translationEng; - } - - return fallback; + return Locale.TryGetValue(language, out var translations) && + translations.TryGetValue(key, out var translation) + ? translation + : Locale.TryGetValue(MiraLanguage.English, out var translationsEng) && + translationsEng.TryGetValue(key, out var translationEng) + ? translationEng + : fallback; } /// @@ -202,11 +216,24 @@ public static class MiraLocaleManager return text; } + /// + /// Builds a formatted translation ID string using a mod ID, a specific ID part, and a suffix. + /// + /// The mod GUID. + /// The core part of the ID. If it starts with '#', the character is stripped. + /// The suffix to append to the ID. + /// A formatted translation ID . public static string BuildTranslationId(string modId, string idPart, string suffix) { return idPart.StartsWith('#') ? idPart[1..] : $"{modId}.{idPart}.{suffix}"; } + /// + /// Builds a formatted translation ID string using a mod ID and a specific ID part. + /// + /// The mod GUID. + /// The core part of the ID. If it starts with '#', the character is stripped. + /// A formatted translation ID . public static string BuildTranslationId(string modId, string idPart) { return idPart.StartsWith('#') ? idPart[1..] : $"{modId}.{idPart}"; @@ -217,6 +244,11 @@ public static class MiraLocaleManager return Path.Combine(Application.persistentDataPath, LangDirectory, modGuid); } + /// + /// Retrieves the value for a given locale string name, creating and registering a new one if it does not already exist. + /// + /// The name of the locale string. + /// The corresponding value. public static StringNames GetOrCreateLocaleString(string name) { if (RegisteredStringNames.TryGetValue(name, out var stringName)) @@ -230,6 +262,9 @@ public static class MiraLocaleManager return newString; } + /// + /// Loads external locale XML files by checking predefined directories, including the plugin path, BepInEx root, game root, and registered mod directories. + /// public static void LoadExternalLocale() { CheckExternalDirectory("mira.api", BepInEx.Paths.PluginPath); @@ -241,6 +276,11 @@ public static class MiraLocaleManager } } + /// + /// Checks a specific directory for XML language files and parses their contents into the dictionary. + /// + /// The mod GUID associated with the directory. + /// The directory path to search for XML files. public static void CheckExternalDirectory(string modGuid, string dir) { Directory.CreateDirectory(dir); @@ -262,7 +302,7 @@ public static class MiraLocaleManager } catch (Exception e) { - Error($"Failed to load external translation {filePath}: {e.Message}"); + Error($"Failed to load external translation {filePath} for mod {modGuid}: {e.Message}"); } } } @@ -313,40 +353,45 @@ public static class MiraLocaleManager xmlDoc.LoadXml(xmlContent); XmlNodeList? stringNodes = xmlDoc.SelectNodes("/resources/string"); - if (stringNodes != null) + if (stringNodes == null) { - var total = 0; - foreach (XmlNode node in stringNodes) - { - if (node.Attributes?["name"] != null) - { - string name = node.Attributes["name"]!.Value; - string value = node.InnerText; - - if (string.IsNullOrEmpty(name)) continue; - - if (value.Contains('[')) - { - value = value.Replace("[", "<"); - } - - if (value.Contains(']')) - { - value = value.Replace("]", ">"); - } - - value = value.Replace("", "\n").Replace("", "&"); - - if (loadingInternal && Locale[language].ContainsKey(name)) - { - Error($"String for \"{name}\" in {language} was overwritten by duplicate!"); - } - dict[name] = value; - total++; - } - } - Info($"Loaded {language.ToDisplayString()} translation with ({total} keys)"); + return; } + + var total = 0; + + foreach (XmlNode node in stringNodes) + { + if (node.Attributes?["name"] == null) + { + continue; + } + + string name = node.Attributes["name"]!.Value; + string value = node.InnerText; + + if (string.IsNullOrEmpty(name)) continue; + + if (value.Contains('[')) + { + value = value.Replace("[", "<"); + } + + if (value.Contains(']')) + { + value = value.Replace("]", ">"); + } + + value = value.Replace("", "\n").Replace("", "&"); + + if (loadingInternal && Locale[language].ContainsKey(name)) + { + Error($"String for \"{name}\" in {language} was overwritten by duplicate!"); + } + dict[name] = value; + total++; + } + Info($"Loaded {language.ToDisplayString()} translation with ({total} keys)"); } catch (XmlException ex) { diff --git a/MiraAPI/Translation/MiraLocalizationProvider.cs b/MiraAPI/Translation/MiraLocalizationProvider.cs index 3ac1133..4c99933 100644 --- a/MiraAPI/Translation/MiraLocalizationProvider.cs +++ b/MiraAPI/Translation/MiraLocalizationProvider.cs @@ -7,12 +7,17 @@ using Reactor.Utilities; namespace MiraAPI.Translation; +/// +/// Provides customized localization support, integrating MiraAPI translations into Reactor's localization system. +/// public class MiraLocalizationProvider : LocalizationProvider { + /// public override int Priority => ReactorPriority.Normal; private static LocalizationProvider? _reactorProvider; private static bool _loadedStrings; + /// public override bool TryGetText(StringNames stringName, out string? result) { if (MiraLocaleManager.StringNamesLookup.TryGetValue(stringName, out var key)) @@ -24,6 +29,7 @@ public class MiraLocalizationProvider : LocalizationProvider return false; } + /// public override bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray parts, out string? result) { if (!TryGetText(stringName, out result)) return false; @@ -32,6 +38,7 @@ public class MiraLocalizationProvider : LocalizationProvider return true; } + /// public override void OnLanguageChanged(SupportedLangs newLanguage) { _reactorProvider ??= LocalizationManager.Providers.First(x => x is HardCodedLocalizationProvider); diff --git a/MiraAPI/Translation/TranslationExtensions.cs b/MiraAPI/Translation/TranslationExtensions.cs index 5f0edbd..8b45b48 100644 --- a/MiraAPI/Translation/TranslationExtensions.cs +++ b/MiraAPI/Translation/TranslationExtensions.cs @@ -8,6 +8,8 @@ public static class TranslationExtensions /// /// Translates a key to the current language. /// + /// The translation key. + /// The corresponding translation. public static string Translate(this string key) { return MiraLocaleManager.Get(key); diff --git a/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs b/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs index 561bfd0..1c14435 100644 --- a/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs +++ b/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs @@ -67,10 +67,8 @@ public static class TmpSpriteUtils }; material.SetTexture(ShaderUtilities.ID_MainTex, sourceTexture); // TODO: Using these values, the icons will NOT clip through chat boxes. However, this breaks quite literally every other tmp text that isn't masked. Please fix this if a good solution is found. -#pragma warning disable S125 // Sections of code should not be commented out /*material.SetFloat(ShaderUtilities.ID_StencilComp, 4); material.SetFloat(ShaderUtilities.ID_StencilID, 1);*/ -#pragma warning restore S125 // Sections of code should not be commented out material.SetFloat(ShaderUtilities.ID_StencilComp, 0); material.SetFloat(ShaderUtilities.ID_StencilID, 0); material.SetFloat(ShaderUtilities.ID_StencilOp, 0); diff --git a/MiraAPI/Utilities/Components/CenteredGridArrange.cs b/MiraAPI/Utilities/Components/CenteredGridArrange.cs index ef71fef..17d1cf4 100644 --- a/MiraAPI/Utilities/Components/CenteredGridArrange.cs +++ b/MiraAPI/Utilities/Components/CenteredGridArrange.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Reactor.Utilities.Attributes; using UnityEngine; @@ -11,24 +12,25 @@ namespace MiraAPI.Utilities.Components; /// /// The for the component. [RegisterInIl2Cpp] +[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity Convention.")] public class CenteredGridArrange(IntPtr iPtr) : MonoBehaviour(iPtr) { /// /// Gets or sets the cell size, which is used for spacing. /// - public Vector2 CellSize; + public Vector2 CellSize { get; set; } /// /// Gets or sets the maximum amount of columns. /// - public int MaxColumns = 6; + public int MaxColumns { get; set; } = 6; private List cells; - private static List currentChildren = new List(); + private static readonly List CurrentChildren = []; private void Start() { - cells = new List(); + cells = []; GetChildsActive(); CheckCurrentChildren(); } @@ -41,23 +43,23 @@ public class CenteredGridArrange(IntPtr iPtr) : MonoBehaviour(iPtr) private void CheckCurrentChildren() { GetChildsActive(); - if (cells.SequenceEqual(currentChildren)) + if (cells.SequenceEqual(CurrentChildren)) return; cells.Clear(); - foreach (Transform currentChild in currentChildren) + foreach (Transform currentChild in CurrentChildren) cells.Add(currentChild); ArrangeChilds(); } private void GetChildsActive() { - currentChildren.Clear(); + CurrentChildren.Clear(); foreach (var obj in transform) { var child = obj.TryCast(); if (child == null) continue; if (child.gameObject.activeSelf) - currentChildren.Add(child); + CurrentChildren.Add(child); } } diff --git a/MiraAPI/Utilities/Extensions.cs b/MiraAPI/Utilities/Extensions.cs index e1fd75d..93d548a 100644 --- a/MiraAPI/Utilities/Extensions.cs +++ b/MiraAPI/Utilities/Extensions.cs @@ -62,7 +62,7 @@ public static class Extensions } if (self.CloseSound && Constants.ShouldPlaySfx()) { - SoundManager.Instance.PlaySound(self.CloseSound, false, 1f, null); + SoundManager.Instance.PlaySound(self.CloseSound, false); } if (PlayerControl.LocalPlayer.Data.Role.TeamType == RoleTeamTypes.Crewmate) { @@ -222,9 +222,7 @@ public static class Extensions public static void DeepDestroy(this GameObject obj, bool clearGc = true) { obj.Destroy(); -#pragma warning disable S125 // Sections of code should not be commented out // Nuke(obj, clearGc); -#pragma warning restore S125 // Sections of code should not be commented out } /// @@ -528,7 +526,7 @@ public static class Extensions /// A proper string for the . public static string ToDisplayString(this Enum @enum) { - var regex = new Regex(@"([^\^])([A-Z][a-z$])"); + var regex = new Regex(@"([^\^])([A-Z][a-z$])", default, default); return regex.Replace(@enum.ToString(), m => $"{m.Groups[1].Value} {m.Groups[2].Value}"); } diff --git a/MiraAPI/Utilities/Helpers.cs b/MiraAPI/Utilities/Helpers.cs index 7b39dcd..0aa4a81 100644 --- a/MiraAPI/Utilities/Helpers.cs +++ b/MiraAPI/Utilities/Helpers.cs @@ -536,11 +536,7 @@ public static class Helpers /// The 's intro blurb. public static string GetRoleIntroBlurb(this RoleBehaviour role) { - if (role is ICustomRole custom) - { - return custom.RoleDescription; - } - return role.Blurb; + return role is ICustomRole custom ? custom.RoleDescription : role.Blurb; } /// @@ -550,11 +546,7 @@ public static class Helpers /// The 's medium description. public static string GetRoleMedDescription(this RoleBehaviour role) { - if (role is ICustomRole custom) - { - return custom.RoleDescription; - } - return role.BlurbMed; + return role is ICustomRole custom ? custom.RoleDescription : role.BlurbMed; } /// @@ -564,11 +556,7 @@ public static class Helpers /// The 's long description. public static string GetRoleLongDescription(this RoleBehaviour role) { - if (role is ICustomRole custom) - { - return custom.RoleLongDescription; - } - return role.BlurbLong; + return role is ICustomRole custom ? custom.RoleLongDescription : role.BlurbLong; } /// diff --git a/MiraAPI/VanillaEvents/JudgeEvents.cs b/MiraAPI/VanillaEvents/JudgeEvents.cs index 4a20c6e..fa18d6b 100644 --- a/MiraAPI/VanillaEvents/JudgeEvents.cs +++ b/MiraAPI/VanillaEvents/JudgeEvents.cs @@ -4,12 +4,12 @@ using MiraAPI.Roles; namespace MiraAPI.VanillaEvents; -public static class JudgeEvents +internal static class JudgeEvents { public static void Initialize() { // This is required because MiraAPI isn't an IMiraPlugin (besides in the gamemodes branch) - MiraEventManager.RegisterEventHandler(@event => ProcessVotesEventHandler(@event), -1000); + MiraEventManager.RegisterEventHandler(ProcessVotesEventHandler, -1000); } public static void ProcessVotesEventHandler(ProcessVotesEvent @event) diff --git a/MiraAPI/VanillaEvents/UiResetEvents.cs b/MiraAPI/VanillaEvents/UiResetEvents.cs index fe0e6e5..931af4e 100644 --- a/MiraAPI/VanillaEvents/UiResetEvents.cs +++ b/MiraAPI/VanillaEvents/UiResetEvents.cs @@ -5,17 +5,17 @@ using MiraAPI.LocalSettings; namespace MiraAPI.VanillaEvents; -public static class UiResetEvents +internal static class UiResetEvents { public static void Initialize() { - MiraEventManager.RegisterEventHandler(@event => ResetButtonParents(@event)); - MiraEventManager.RegisterEventHandler(@event => PlaceWikiButton(@event), -900); - MiraEventManager.RegisterEventHandler(@event => PlaceSubmergedButton(@event), -800); - MiraEventManager.RegisterEventHandler(@event => PlaceModifierUi(@event), -700); + MiraEventManager.RegisterEventHandler(ResetButtonParents); + MiraEventManager.RegisterEventHandler(PlaceWikiButton, -900); + MiraEventManager.RegisterEventHandler(PlaceSubmergedButton, -800); + MiraEventManager.RegisterEventHandler(PlaceModifierUi, -700); } - public static void ResetButtonParents(UiButtonResetEvent @event) + public static void ResetButtonParents(UiButtonResetEvent _) { var wikiButton = MiraHudHelper.VanillaMatchInfoButton; var subButton = MiraHudHelper.SubmergedFloorButton; diff --git a/MiraAPI/Voting/VotingUtils.cs b/MiraAPI/Voting/VotingUtils.cs index e2bd965..bb33d0f 100644 --- a/MiraAPI/Voting/VotingUtils.cs +++ b/MiraAPI/Voting/VotingUtils.cs @@ -42,6 +42,7 @@ public static class VotingUtils /// /// The player's . /// Who the player voted for. + /// Flag that indicates that the vote was done by a Judge. /// Whether you want the vote to commence or not. private static void HandleVote(PlayerVoteData voteData, byte suspectIdx, bool byJudge, out bool cancelVote) { @@ -117,11 +118,22 @@ public static class VotingUtils /// The voted player's id. /// Data that is checked by the Judge role to determine which Judge takes priority. [MethodRpc((uint)MiraRpc.QueueOverruleVotes)] + [SuppressMessage( + "Style", + "IDE0060:Remove unused parameter", + Justification = "Required parameter: The MethodRpc system mandates an InnerNetObject (or its derived class) as the first parameter for sender context, even if unused in the method body." + )] public static void RpcQueueOverruleVotes(PlayerControl source, byte srcPlayerId, byte suspectPlayerId, ushort overruleNonce) { CustomCastJudgeVote(srcPlayerId, suspectPlayerId, overruleNonce); } + /// + /// Casts a custom Judge vote. + /// + /// The Judge's player ID. + /// The unfortunate soul's player ID. + /// Overruled. public static void CustomCastJudgeVote(PlayerId judgePlayerId, PlayerId targetPlayerId, ushort overruleNonce) { var plr = GameData.Instance.GetPlayerById(judgePlayerId.Value); @@ -187,6 +199,11 @@ public static class VotingUtils CustomCastVote(srcPlayerId, suspectPlayerId); } + /// + /// Casts a custom vote. + /// + /// The casting player's ID. + /// The voted player's ID. public static void CustomCastVote(byte srcPlayerId, byte suspectPlayerId) { var plr = GameData.Instance.GetPlayerById(srcPlayerId); diff --git a/stylecop.json b/stylecop.json index 21a7e94..4cb4b89 100644 --- a/stylecop.json +++ b/stylecop.json @@ -13,4 +13,4 @@ "documentInterfaces": false } } -} \ No newline at end of file +}