diff --git a/HNSRevamped.cs b/HNSRevamped.cs index 3b5ccc4..c4e6595 100644 --- a/HNSRevamped.cs +++ b/HNSRevamped.cs @@ -5,6 +5,7 @@ global using System.Linq; using BepInEx; using BepInEx.Configuration; using BepInEx.Unity.IL2CPP; +using UnityEngine; namespace HNSRevamped; @@ -34,6 +35,7 @@ public partial class Main : BasePlugin public static void Prefix(ModManager __instance) { __instance.ShowModStamp(); + LateTask.Update(Time.deltaTime); } } } diff --git a/Modules/CustomOptionsHolder.cs b/Modules/CustomOptionsHolder.cs index 17ec813..d995a0f 100644 --- a/Modules/CustomOptionsHolder.cs +++ b/Modules/CustomOptionsHolder.cs @@ -40,6 +40,8 @@ namespace HNSRevamped //Mod public static OptionItem DisableTasks; + // HNS + public static OptionItem NumSeekers; public static bool IsLoaded = false; @@ -68,6 +70,11 @@ namespace HNSRevamped .SetColor(Color.red) .SetHeader(true); + + + NumSeekers = IntegerOptionItem.Create(70000, "# Seekers", new(0, 15, 1), 1, TabGroup.HNSSettings, false) + .SetValueFormat(OptionFormat.Level) + .SetHeader(true); IsLoaded = true; } } diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 1a6ba5d..d6d85a8 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -19,10 +19,11 @@ namespace HNSRevamped; public static class Utils { - public static bool isHideNSeek => GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.HideNSeek; + public static bool InGame => AmongUsClient.Instance && AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started; + public static bool isHideNSeek => GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.HideNSeek; - public static string ColorString(Color32 color, string str) => $"<#{color.r:x2}{color.g:x2}{color.b:x2}{color.a:x2}>{str}"; - public static string ColorToHex(Color32 color) => $"#{color.r:x2}{color.g:x2}{color.b:x2}{color.a:x2}"; + public static string ColorString(Color32 color, string str) => $"<#{color.r:x2}{color.g:x2}{color.b:x2}{color.a:x2}>{str}"; + public static string ColorToHex(Color32 color) => $"#{color.r:x2}{color.g:x2}{color.b:x2}{color.a:x2}"; public static bool IsPlayerModerator(string friendCode) { diff --git a/Patches/OnGameStartedPatch.cs b/Patches/OnGameStartedPatch.cs new file mode 100644 index 0000000..b0dc0f4 --- /dev/null +++ b/Patches/OnGameStartedPatch.cs @@ -0,0 +1,53 @@ +using System; +using InnerNet; +using UnityEngine; + +namespace HNSRevamped; + +[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.CoStartGame))] +internal class ApplyCustomImpostorCount +{ + public static void Postfix(AmongUsClient __instance) + { + if (!AmongUsClient.Instance.AmHost || !Utils.isHideNSeek) return; + + int seekersCount = Options.NumSeekers.GetInt(); + + int toAdd = Math.Max(0, seekersCount - 1); + + var candidates = new List(); + foreach (var p in PlayerControl.AllPlayerControls) + { + if (p.Data.Role.TeamType != RoleTeamTypes.Impostor) + candidates.Add(p); + } + + toAdd = Math.Min(toAdd, candidates.Count); + + System.Random rand = new System.Random(); + for (int i = candidates.Count - 1; i > 0; i--) + { + int j = rand.Next(i + 1); + (candidates[i], candidates[j]) = (candidates[j], candidates[i]); + } + + // 1st RpcSetRole forces the role on that user. 2nd is needed to allow them to kill. + for (int i = 0; i < toAdd; i++) + { + var player = candidates[i]; + + player.RpcSetRole(AmongUs.GameOptions.RoleTypes.Impostor, false); + + foreach (var p in PlayerControl.AllPlayerControls) + { + if (p.Data.Role.TeamType == RoleTeamTypes.Impostor) + { + new LateTask(() => + { + p.RpcSetRole(AmongUs.GameOptions.RoleTypes.Impostor, false); + }, 9f, "Secondary RPCSetRole"); + } + } + } + } +} \ No newline at end of file