From 50fdd6bb7eae9e2dbd9c973bf85687572f96d2ec Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Sun, 17 Mar 2024 13:44:19 +0100 Subject: [PATCH] Fix Add-on display & You're gonna be stumped when I finish custom h&s today --- GameMode/CustomHideAndSeekManager.cs | 65 +++++++++ GameMode/HideAndSeekRoles/Fox.cs | 46 ++++++ GameMode/HideAndSeekRoles/Hider.cs | 43 ++++++ GameMode/HideAndSeekRoles/Seeker.cs | 67 +++++++++ GameMode/HideAndSeekRoles/Troll.cs | 46 ++++++ Modules/CustomRoleSelector.cs | 18 +-- Modules/DevManager.cs | 1 + .../PlayerGameOptionsSender.cs | 3 + Modules/NameColorManager.cs | 2 + Modules/OptionHolder.cs | 5 +- Modules/Utils.cs | 133 ++++++++++-------- Patches/CheckGameEndPatch.cs | 17 ++- Patches/ExilePatch.cs | 2 +- Patches/GameOptionsMenuPatch.cs | 10 ++ Patches/HudPatch.cs | 15 +- Patches/IntroPatch.cs | 15 +- Patches/OutroPatch.cs | 13 +- Patches/PlayerControlPatch.cs | 15 +- Patches/SabotageSystemPatch.cs | 2 +- Patches/ShipStatusPatch.cs | 6 +- Patches/TextBoxPatch.cs | 4 +- Patches/UsablesPatch.cs | 2 +- Patches/onGameStartedPatch.cs | 5 +- Resources/Lang/en_US.json | 27 +++- Roles/AddOns/Impostor/LastImpostor.cs | 4 +- main.cs | 12 ++ 26 files changed, 475 insertions(+), 103 deletions(-) create mode 100644 GameMode/CustomHideAndSeekManager.cs create mode 100644 GameMode/HideAndSeekRoles/Fox.cs create mode 100644 GameMode/HideAndSeekRoles/Hider.cs create mode 100644 GameMode/HideAndSeekRoles/Seeker.cs create mode 100644 GameMode/HideAndSeekRoles/Troll.cs diff --git a/GameMode/CustomHideAndSeekManager.cs b/GameMode/CustomHideAndSeekManager.cs new file mode 100644 index 000000000..802c533e1 --- /dev/null +++ b/GameMode/CustomHideAndSeekManager.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AmongUs.GameOptions; + +namespace TOHE +{ + internal static class CustomHideAndSeekManager + { + public static void SetupCustomOption() + { + } + + public static void Init() + { + } + + public static void AssignRoles(ref Dictionary result) + { + } + + public static void ApplyGameOptions(IGameOptions opt, PlayerControl pc) + { + } + + public static bool KnowTargetRoleColor(PlayerControl seer, PlayerControl target, ref string color) + { + } + + public static bool HasTasks(GameData.PlayerInfo playerInfo) + { + } + + public static bool IsRoleTextEnabled(PlayerControl seer, PlayerControl target) + { + } + + public static string GetSuffixText(PlayerControl seer, PlayerControl target, bool isHUD = false) + { + } + + public static string GetRoleInfoText(PlayerControl seer) + { + } + + public static bool CheckForGameEnd(out GameOverReason reason) + { + reason = GameOverReason.ImpostorByKill; + } + + public static string GetTaskBarText() + { + } + + public static void OnCheckMurder(PlayerControl killer, PlayerControl target) + { + } + + public static void OnCoEnterVent(PlayerPhysics physics, int ventId) + { + } + } +} diff --git a/GameMode/HideAndSeekRoles/Fox.cs b/GameMode/HideAndSeekRoles/Fox.cs new file mode 100644 index 000000000..e5cf06076 --- /dev/null +++ b/GameMode/HideAndSeekRoles/Fox.cs @@ -0,0 +1,46 @@ +using AmongUs.GameOptions; + +namespace TOHE.GameMode.HideAndSeekRoles +{ + internal class Fox : RoleBase + { + public static bool On; + public override bool IsEnable => On; + + public static OptionItem Vision; + public static OptionItem Speed; + + public static void SetupCustomOption() + { + Options.SetupRoleOptions(69_211_301, TabGroup.NeutralRoles, CustomRoles.Fox, CustomGameMode.HideAndSeek); + Vision = FloatOptionItem.Create(69_211_303, "FoxVision", new(0.05f, 5f, 0.05f), 1.25f, TabGroup.NeutralRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(0, 255, 0, byte.MaxValue)) + .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Fox]); + Speed = FloatOptionItem.Create(69_213_304, "FoxSpeed", new(0.05f, 5f, 0.05f), 1.25f, TabGroup.NeutralRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(0, 255, 0, byte.MaxValue)) + .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Fox]); + } + + public override void Add(byte playerId) + { + On = true; + } + + public override void Init() + { + On = false; + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + Main.AllPlayerSpeed[playerId] = Speed.GetFloat(); + opt.SetFloat(FloatOptionNames.CrewLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.ImpostorLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.PlayerSpeedMod, Speed.GetFloat()); + } + } +} diff --git a/GameMode/HideAndSeekRoles/Hider.cs b/GameMode/HideAndSeekRoles/Hider.cs new file mode 100644 index 000000000..062428872 --- /dev/null +++ b/GameMode/HideAndSeekRoles/Hider.cs @@ -0,0 +1,43 @@ +using AmongUs.GameOptions; + +namespace TOHE.GameMode.HideAndSeekRoles +{ + internal class Hider : RoleBase + { + public static bool On; + public override bool IsEnable => On; + + public static OptionItem Vision; + public static OptionItem Speed; + + public static void SetupCustomOption() + { + Vision = FloatOptionItem.Create(69_211_101, "HiderVision", new(0.05f, 5f, 0.05f), 1.25f, TabGroup.CrewmateRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(52, 94, 235, byte.MaxValue)); + Speed = FloatOptionItem.Create(69_211_102, "HiderSpeed", new(0.05f, 5f, 0.05f), 1.25f, TabGroup.CrewmateRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(52, 94, 235, byte.MaxValue)); + } + + public override void Add(byte playerId) + { + On = true; + } + + public override void Init() + { + On = false; + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + Main.AllPlayerSpeed[playerId] = Speed.GetFloat(); + opt.SetFloat(FloatOptionNames.CrewLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.ImpostorLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.PlayerSpeedMod, Speed.GetFloat()); + } + } +} diff --git a/GameMode/HideAndSeekRoles/Seeker.cs b/GameMode/HideAndSeekRoles/Seeker.cs new file mode 100644 index 000000000..20645b8c1 --- /dev/null +++ b/GameMode/HideAndSeekRoles/Seeker.cs @@ -0,0 +1,67 @@ +using AmongUs.GameOptions; + +namespace TOHE.GameMode.HideAndSeekRoles +{ + internal class Seeker : RoleBase + { + public static bool On; + public override bool IsEnable => On; + + public static OptionItem Vision; + public static OptionItem Speed; + public static OptionItem KillCooldown; + public static OptionItem CanVent; + + public static void SetupCustomOption() + { + Vision = FloatOptionItem.Create(69_211_201, "SeekerVision", new(0.05f, 5f, 0.05f), 0.5f, TabGroup.ImpostorRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(255, 25, 25, byte.MaxValue)); + Speed = FloatOptionItem.Create(69_211_202, "SeekerSpeed", new(0.05f, 5f, 0.05f), 1.5f, TabGroup.ImpostorRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(255, 25, 25, byte.MaxValue)); + KillCooldown = FloatOptionItem.Create(69_211_203, "KillCooldown", new(0f, 90f, 1f), 10f, TabGroup.ImpostorRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Seconds) + .SetColor(new(255, 25, 25, byte.MaxValue)); + CanVent = BooleanOptionItem.Create(69_211_204, "SeekerCanVent", false, TabGroup.ImpostorRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetColor(new(255, 25, 25, byte.MaxValue)); + } + + public override void Add(byte playerId) + { + On = true; + } + + public override void Init() + { + On = false; + } + + public override bool CanUseKillButton(PlayerControl pc) + { + return pc.IsAlive(); + } + + public override bool CanUseImpostorVentButton(PlayerControl pc) + { + return CanVent.GetBool(); + } + + public override void SetKillCooldown(byte id) + { + Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat(); + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + Main.AllPlayerSpeed[playerId] = Speed.GetFloat(); + opt.SetFloat(FloatOptionNames.CrewLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.ImpostorLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.PlayerSpeedMod, Speed.GetFloat()); + } + } +} diff --git a/GameMode/HideAndSeekRoles/Troll.cs b/GameMode/HideAndSeekRoles/Troll.cs new file mode 100644 index 000000000..f97452100 --- /dev/null +++ b/GameMode/HideAndSeekRoles/Troll.cs @@ -0,0 +1,46 @@ +using AmongUs.GameOptions; + +namespace TOHE.GameMode.HideAndSeekRoles +{ + internal class Troll : RoleBase + { + public static bool On; + public override bool IsEnable => On; + + public static OptionItem Vision; + public static OptionItem Speed; + + public static void SetupCustomOption() + { + Options.SetupRoleOptions(69_211_401, TabGroup.NeutralRoles, CustomRoles.Troll, CustomGameMode.HideAndSeek); + Vision = FloatOptionItem.Create(69_211_403, "TrollVision", new(0.05f, 5f, 0.05f), 1.25f, TabGroup.NeutralRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(255, 0, 255, byte.MaxValue)) + .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Troll]); + Speed = FloatOptionItem.Create(69_211_404, "TrollSpeed", new(0.05f, 5f, 0.05f), 1.25f, TabGroup.NeutralRoles, false) + .SetGameMode(CustomGameMode.HideAndSeek) + .SetValueFormat(OptionFormat.Multiplier) + .SetColor(new(255, 0, 255, byte.MaxValue)) + .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Troll]); + } + + public override void Add(byte playerId) + { + On = true; + } + + public override void Init() + { + On = false; + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + Main.AllPlayerSpeed[playerId] = Speed.GetFloat(); + opt.SetFloat(FloatOptionNames.CrewLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.ImpostorLightMod, Vision.GetFloat()); + opt.SetFloat(FloatOptionNames.PlayerSpeedMod, Speed.GetFloat()); + } + } +} diff --git a/Modules/CustomRoleSelector.cs b/Modules/CustomRoleSelector.cs index ea98514a3..1b7aba9dc 100644 --- a/Modules/CustomRoleSelector.cs +++ b/Modules/CustomRoleSelector.cs @@ -87,43 +87,43 @@ internal static class CustomRoleSelector public static void SelectCustomRoles() { + RoleResult = []; + switch (Options.CurrentGameMode) { case CustomGameMode.SoloKombat: - RoleResult = []; foreach (PlayerControl pc in Main.AllAlivePlayerControls) { - RoleResult.Add(pc, CustomRoles.KB_Normal); + RoleResult[pc] = CustomRoles.KB_Normal; } return; case CustomGameMode.FFA: - RoleResult = []; foreach (PlayerControl pc in Main.AllAlivePlayerControls) { - RoleResult.Add(pc, CustomRoles.Killer); + RoleResult[pc] = CustomRoles.Killer; } return; case CustomGameMode.MoveAndStop: - RoleResult = []; foreach (PlayerControl pc in Main.AllAlivePlayerControls) { - RoleResult.Add(pc, CustomRoles.Tasker); + RoleResult[pc] = CustomRoles.Tasker; } return; case CustomGameMode.HotPotato: - RoleResult = []; foreach (PlayerControl pc in Main.AllAlivePlayerControls) { - RoleResult.Add(pc, CustomRoles.Potato); + RoleResult[pc] = CustomRoles.Potato; } + return; + case CustomGameMode.HideAndSeek: + CustomHideAndSeekManager.AssignRoles(ref RoleResult); return; } - RoleResult = []; var rd = IRandom.Instance; int playerCount = Main.AllAlivePlayerControls.Length; int optImpNum = Main.RealOptionsData.GetInt(Int32OptionNames.NumImpostors); diff --git a/Modules/DevManager.cs b/Modules/DevManager.cs index 6e0a241f5..b57f9c14f 100644 --- a/Modules/DevManager.cs +++ b/Modules/DevManager.cs @@ -89,6 +89,7 @@ public static class DevManager DevUserList.Add(new(code: "pinsrustic#5496", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "FHgameplay")); DevUserList.Add(new(code: "opaquedot#5610", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Deh_66")); DevUserList.Add(new(code: "furpolitic#3380", color: "#a020f0", tag: "EuOncologico o impostor", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "EuOncologico")); + DevUserList.Add(new(code: "pithfierce#5073", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "OrigeTv")); // Sponsor DevUserList.Add(new(code: "recentduct#6068", color: "#FF00FF", tag: "高冷男模法师", isUp: false, isDev: false, colorCmd: false, deBug: true, upName: null)); diff --git a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs index 75637210d..4684f05e6 100644 --- a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs +++ b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs @@ -144,6 +144,9 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender opt.SetFloat(FloatOptionNames.CrewLightMod, 1.25f); opt.SetFloat(FloatOptionNames.ImpostorLightMod, 1.25f); break; + case CustomGameMode.HideAndSeek: + CustomHideAndSeekManager.ApplyGameOptions(opt, player); + break; } switch (player.GetCustomRoleTypes()) diff --git a/Modules/NameColorManager.cs b/Modules/NameColorManager.cs index 9f2007419..3e5f97042 100644 --- a/Modules/NameColorManager.cs +++ b/Modules/NameColorManager.cs @@ -47,6 +47,8 @@ public static class NameColorManager else if (target.PlayerId == LastHolderID) color = "#00ffff"; else color = "#ffffff"; return true; + case CustomGameMode.HideAndSeek: + return CustomHideAndSeekManager.KnowTargetRoleColor(seer, target, ref color); } // Global (low priority) diff --git a/Modules/OptionHolder.cs b/Modules/OptionHolder.cs index e616e786d..1c744f14c 100644 --- a/Modules/OptionHolder.cs +++ b/Modules/OptionHolder.cs @@ -19,6 +19,7 @@ public enum CustomGameMode FFA = 0x03, MoveAndStop = 0x04, HotPotato = 0x05, + HideAndSeek = 0x06, All = int.MaxValue } @@ -63,6 +64,7 @@ public static class Options 2 => CustomGameMode.FFA, 3 => CustomGameMode.MoveAndStop, 4 => CustomGameMode.HotPotato, + 5 => CustomGameMode.HideAndSeek, _ => CustomGameMode.Standard }; @@ -72,7 +74,8 @@ public static class Options "SoloKombat", "FFA", "MoveAndStop", - "HotPotato" + "HotPotato", + "HideAndSeek" ]; // 役職数・確率 diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 4bcd601bc..65bddadd9 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -553,6 +553,7 @@ public static class Utils case CustomGameMode.FFA: return false; case CustomGameMode.MoveAndStop: return true; case CustomGameMode.HotPotato: return false; + case CustomGameMode.HideAndSeek: return CustomHideAndSeekManager.HasTasks(p); } var role = States.MainRole; @@ -719,7 +720,7 @@ public static class Utils public static bool IsRoleTextEnabled(PlayerControl __instance) { - bool result = __instance.AmOwner || Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.SoloKombat or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato || Main.VisibleTasksCount && PlayerControl.LocalPlayer.Data.IsDead && Options.GhostCanSeeOtherRoles.GetBool() || PlayerControl.LocalPlayer.Is(CustomRoles.Mimic) && Main.VisibleTasksCount && __instance.Data.IsDead && Options.MimicCanSeeDeadRoles.GetBool(); + bool result = __instance.AmOwner || Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.SoloKombat or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato || Options.CurrentGameMode == CustomGameMode.HideAndSeek && CustomHideAndSeekManager.IsRoleTextEnabled(PlayerControl.LocalPlayer, __instance) || Main.VisibleTasksCount && PlayerControl.LocalPlayer.Data.IsDead && Options.GhostCanSeeOtherRoles.GetBool() || PlayerControl.LocalPlayer.Is(CustomRoles.Mimic) && Main.VisibleTasksCount && __instance.Data.IsDead && Options.MimicCanSeeDeadRoles.GetBool(); switch (__instance.GetCustomRole()) { @@ -751,7 +752,6 @@ public static class Utils if (Executioner.KnowRole(PlayerControl.LocalPlayer, __instance)) result = true; if (Succubus.KnowRole(PlayerControl.LocalPlayer, __instance)) result = true; if (Necromancer.KnowRole(PlayerControl.LocalPlayer, __instance)) result = true; - //if (CursedSoul.KnowRole(PlayerControl.LocalPlayer, __instance)) result = true; if (Amnesiac.KnowRole(PlayerControl.LocalPlayer, __instance)) result = true; if (Virus.KnowRole(PlayerControl.LocalPlayer, __instance)) result = true; if (PlayerControl.LocalPlayer.IsRevealedPlayer(__instance)) result = true; @@ -1147,10 +1147,10 @@ public static class Utils { case CustomGameMode.SoloKombat: List<(int, byte)> list = []; - list.AddRange(cloneRoles.ToArray().Select(id => (SoloKombatManager.GetRankOfScore(id), id))); + list.AddRange(cloneRoles.Select(id => (SoloKombatManager.GetRankOfScore(id), id))); list.Sort(); - foreach ((int, byte) id in list.ToArray()) + foreach ((int, byte) id in list) { sb.Append("\n\u3000 ").Append(EndGamePatch.SummaryText[id.Item2]); } @@ -1158,10 +1158,10 @@ public static class Utils break; case CustomGameMode.FFA: List<(int, byte)> list2 = []; - list2.AddRange(cloneRoles.ToArray().Select(id => (FFAManager.GetRankOfScore(id), id))); + list2.AddRange(cloneRoles.Select(id => (FFAManager.GetRankOfScore(id), id))); list2.Sort(); - foreach ((int, byte) id in list2.ToArray()) + foreach ((int, byte) id in list2) { sb.Append("\n\u3000 ").Append(EndGamePatch.SummaryText[id.Item2]); } @@ -1169,30 +1169,33 @@ public static class Utils break; case CustomGameMode.MoveAndStop: List<(int, byte)> list3 = []; - list3.AddRange(cloneRoles.ToArray().Select(id => (MoveAndStopManager.GetRankOfScore(id), id))); + list3.AddRange(cloneRoles.Select(id => (MoveAndStopManager.GetRankOfScore(id), id))); list3.Sort(); - foreach ((int, byte) id in list3.ToArray()) + foreach ((int, byte) id in list3) { sb.Append("\n\u3000 ").Append(EndGamePatch.SummaryText[id.Item2]); } break; case CustomGameMode.HotPotato: - List list4 = []; - list4.AddRange(cloneRoles); + foreach (byte id in cloneRoles) + { + sb.Append("\n\u3000 ").Append(EndGamePatch.SummaryText[id]); + } - foreach (byte id in list4.ToArray()) + break; + case CustomGameMode.HideAndSeek: + foreach (byte id in cloneRoles) { sb.Append("\n\u3000 ").Append(EndGamePatch.SummaryText[id]); } break; default: - foreach (byte id in cloneRoles.ToArray()) + foreach (byte id in cloneRoles) { - if (EndGamePatch.SummaryText[id].Contains("")) - continue; + if (EndGamePatch.SummaryText[id].Contains("")) continue; sb.Append("\n\u3000 ").Append(EndGamePatch.SummaryText[id]); } @@ -1223,10 +1226,12 @@ public static class Utils return; } + if (Options.CurrentGameMode != CustomGameMode.Standard) return; + var sb = new StringBuilder(); if (SetEverythingUpPatch.LastWinsText != string.Empty) sb.Append($"{GetString("LastResult")} {SetEverythingUpPatch.LastWinsText}"); if (SetEverythingUpPatch.LastWinsReason != string.Empty) sb.Append($"\n{GetString("LastEndReason")} {SetEverythingUpPatch.LastWinsReason}"); - if (sb.Length > 0 && Options.CurrentGameMode is not CustomGameMode.SoloKombat and not CustomGameMode.FFA and not CustomGameMode.MoveAndStop and not CustomGameMode.HotPotato) SendMessage("\n", PlayerId, sb.ToString()); + if (sb.Length > 0) SendMessage("\n", PlayerId, sb.ToString()); } public static void ShowLastAddOns(byte PlayerId = byte.MaxValue) @@ -1237,9 +1242,9 @@ public static class Utils return; } - var result = Main.PlayerStates - .Where(s => s.Value.SubRoles.Count > 0) - .Join(s => $"{ColorString(Main.PlayerColors.GetValueOrDefault(s.Key, Color.white), Main.AllPlayerNames.GetValueOrDefault(s.Key, $"ID {s.Key}"))}: {s.Value.SubRoles.Join(x => GetString($"{x}"))}", "\n"); + if (Options.CurrentGameMode != CustomGameMode.Standard) return; + + var result = Main.LastAddOns.Values.Join(delimiter: "\n"); SendMessage("\n", PlayerId, result); } @@ -1622,24 +1627,16 @@ public static class Utils if (GameStates.IsOnlineGame || GameStates.IsLocalGame) name = $"{GetString("HostText")}{GetString("Icon")}{name}"; - - //name = $"{GetString("HostText")}♥" + name; - - switch (Options.CurrentGameMode) + string modeText = GetString($"Mode{Options.CurrentGameMode}"); + name = Options.CurrentGameMode switch { - case CustomGameMode.SoloKombat: - name = $"{GetString("ModeSoloKombat")}\r\n" + name; - break; - case CustomGameMode.FFA: - name = $"{GetString("ModeFFA")}\r\n" + name; - break; - case CustomGameMode.MoveAndStop: - name = $"{GetString("ModeMoveAndStop")}\r\n" + name; - break; - case CustomGameMode.HotPotato: - name = $"{GetString("ModeHotPotato")}\r\n" + name; - break; - } + CustomGameMode.SoloKombat => $"{modeText}\r\n" + name, + CustomGameMode.FFA => $"{modeText}\r\n" + name, + CustomGameMode.MoveAndStop => $"{modeText}\r\n" + name, + CustomGameMode.HotPotato => $"{modeText}\r\n" + name, + CustomGameMode.HideAndSeek => $"{modeText}\r\n" + name, + _ => name + }; } DevUser devUser = player.FriendCode.GetDevUser(); @@ -1754,7 +1751,7 @@ public static class Utils string SelfTaskText = GetProgressText(seer); SelfMark.Clear(); - if (Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) goto GameMode0; + if (Options.CurrentGameMode != CustomGameMode.Standard) goto GameMode0; SelfMark.Append(Snitch.GetWarningArrow(seer)); if (seer.Is(CustomRoles.Lovers)) SelfMark.Append(ColorString(GetRoleColor(CustomRoles.Lovers), "♥")); @@ -1771,7 +1768,7 @@ public static class Utils SelfSuffix.Clear(); - if (Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) goto GameMode; + if (Options.CurrentGameMode != CustomGameMode.Standard) goto GameMode; if (!isForMeeting) { @@ -1908,30 +1905,40 @@ public static class Utils case CustomGameMode.HotPotato when seer.IsAlive() && !seer.IsModClient(): SelfSuffix.Append(HotPotatoManager.GetSuffixText(seer.PlayerId)); break; + case CustomGameMode.HideAndSeek: + SelfSuffix.Append(CustomHideAndSeekManager.GetSuffixText(seer, seer)); + break; } string SeerRealName = seer.GetRealName(isForMeeting); if (!isForMeeting && MeetingStates.FirstMeeting && Options.ChangeNameToRoleInfo.GetBool() && Options.CurrentGameMode is not CustomGameMode.FFA and not CustomGameMode.MoveAndStop and not CustomGameMode.HotPotato) { - if (seer.GetCustomRole().IsMadmate() || seer.Is(CustomRoles.Madmate)) + if (Options.CurrentGameMode == CustomGameMode.HideAndSeek) { - SeerRealName = $"{GetString("YouAreMadmate")}\n{seer.GetRoleInfo()}"; + SeerRealName = CustomHideAndSeekManager.GetRoleInfoText(seer); } - - else if (seer.IsCrewmate()) + else { - SeerRealName = $"{GetString("YouAreCrewmate")}\n{seer.GetRoleInfo()}"; - } + if (seer.GetCustomRole().IsMadmate() || seer.Is(CustomRoles.Madmate)) + { + SeerRealName = $"{GetString("YouAreMadmate")}\n{seer.GetRoleInfo()}"; + } - else if (seer.GetCustomRole().IsImpostor()) - { - SeerRealName = $"\n{seer.GetRoleInfo()}"; - } + else if (seer.IsCrewmate()) + { + SeerRealName = $"{GetString("YouAreCrewmate")}\n{seer.GetRoleInfo()}"; + } - else if (seer.GetCustomRole().IsNeutral()) - { - SeerRealName = $"{GetString("YouAreNeutral")}\n{seer.GetRoleInfo()}"; + else if (seer.GetCustomRole().IsImpostor()) + { + SeerRealName = $"\n{seer.GetRoleInfo()}"; + } + + else if (seer.GetCustomRole().IsNeutral()) + { + SeerRealName = $"{GetString("YouAreNeutral")}\n{seer.GetRoleInfo()}"; + } } } @@ -1940,7 +1947,7 @@ public static class Utils string SelfDeathReason = seer.KnowDeathReason(seer) ? $"\n({ColorString(GetRoleColor(CustomRoles.Doctor), GetVitalText(seer.PlayerId))})" : string.Empty; string SelfName = $"{ColorString(seer.GetRoleColor(), SeerRealName)}{SelfDeathReason}{SelfMark}"; - if (Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) goto GameMode2; + if (Options.CurrentGameMode != CustomGameMode.Standard) goto GameMode2; SelfName = seer.GetCustomRole() switch { @@ -2001,7 +2008,7 @@ public static class Utils { TargetMark.Clear(); - if (Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) goto BeforeEnd2; + if (Options.CurrentGameMode != CustomGameMode.Standard) goto BeforeEnd2; TargetMark.Append(Witch.GetSpelledMark(target.PlayerId, isForMeeting)); @@ -2111,6 +2118,7 @@ public static class Utils Virus.KnowRole(seer, target) || Markseeker.PlayerIdList.Any(x => Main.PlayerStates[x].Role is Markseeker { IsEnable: true, TargetRevealed: true } ms && ms.MarkedId == target.PlayerId) || Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato || + (Options.CurrentGameMode == CustomGameMode.HideAndSeek && CustomHideAndSeekManager.IsRoleTextEnabled(seer, target)) || (seer.IsRevealedPlayer(target) && !target.Is(CustomRoles.Trickster)) || seer.Is(CustomRoles.God) || target.Is(CustomRoles.GM) @@ -2128,7 +2136,7 @@ public static class Utils string TargetPlayerName = target.GetRealName(isForMeeting); - if (Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) goto BeforeEnd; + if (Options.CurrentGameMode != CustomGameMode.Standard) goto BeforeEnd; switch (seer.GetCustomRole()) { @@ -2229,7 +2237,7 @@ public static class Utils TargetPlayerName = TargetPlayerName.ApplyNameColorData(seer, target, isForMeeting); - if (Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) goto End; + if (Options.CurrentGameMode != CustomGameMode.Standard) goto End; if (seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoles.Snitch) && target.Is(CustomRoles.Madmate) && target.GetTaskState().IsTaskFinished) TargetMark.Append(ColorString(GetRoleColor(CustomRoles.Impostor), "★")); @@ -2258,8 +2266,15 @@ public static class Utils TargetSuffix.Clear(); - if (Options.CurrentGameMode == CustomGameMode.SoloKombat) - TargetSuffix.Append(SoloKombatManager.GetDisplayHealth(target)); + switch (Options.CurrentGameMode) + { + case CustomGameMode.SoloKombat: + TargetSuffix.Append(SoloKombatManager.GetDisplayHealth(target)); + break; + case CustomGameMode.HideAndSeek: + TargetSuffix.Append(CustomHideAndSeekManager.GetSuffixText(seer, target)); + break; + } TargetSuffix.Append(PlagueDoctor.GetLowerTextOthers(seer, target)); TargetSuffix.Append(Stealth.GetSuffix(seer, target)); @@ -2285,8 +2300,6 @@ public static class Utils target.RpcSetNamePrivate(TargetName, true, seer, force: NoCache); } - - //Logger.Info($"NotifyRoles-Loop2-{target.GetNameWithRole().RemoveHtmlTags()}:END", "NotifyRoles"); } } } @@ -2294,8 +2307,6 @@ public static class Utils { Logger.Error($"Error for {seer.GetNameWithRole()}: {ex}", "NR"); } - - //Logger.Info($"NotifyRoles-Loop1-{seer.GetNameWithRole().RemoveHtmlTags()}:END", "NotifyRoles"); } return Task.CompletedTask; @@ -2549,7 +2560,7 @@ public static class Utils if (sendLog) { var sb = new StringBuilder(100); - if (Options.CurrentGameMode is not CustomGameMode.FFA and not CustomGameMode.MoveAndStop and not CustomGameMode.HotPotato) + if (Options.CurrentGameMode == CustomGameMode.Standard) { foreach (var countTypes in Enum.GetValues(typeof(CountTypes)).Cast()) { diff --git a/Patches/CheckGameEndPatch.cs b/Patches/CheckGameEndPatch.cs index e61a19641..e4a9727cd 100644 --- a/Patches/CheckGameEndPatch.cs +++ b/Patches/CheckGameEndPatch.cs @@ -31,7 +31,7 @@ class GameEndChecker predicate.CheckForEndGame(out GameOverReason reason); - if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) + if (Options.CurrentGameMode != CustomGameMode.Standard) { if (WinnerIds.Count > 0 || WinnerTeam != CustomWinner.Default) { @@ -329,6 +329,7 @@ class GameEndChecker public static void SetPredicateToFFA() => predicate = new FFAGameEndPredicate(); public static void SetPredicateToMoveAndStop() => predicate = new MoveAndStopGameEndPredicate(); public static void SetPredicateToHotPotato() => predicate = new HotPotatoGameEndPredicate(); + public static void SetPredicateToHideAndSeek() => predicate = new HideAndSeekGameEndPredicate(); class NormalGameEndPredicate : GameEndPredicate { @@ -624,6 +625,20 @@ class GameEndChecker } } + class HideAndSeekGameEndPredicate : GameEndPredicate + { + public override bool CheckForEndGame(out GameOverReason reason) + { + reason = GameOverReason.ImpostorByKill; + return WinnerIds.Count <= 0 && CheckGameEndByLivingPlayers(out reason); + } + + private static bool CheckGameEndByLivingPlayers(out GameOverReason reason) + { + return CustomHideAndSeekManager.CheckForGameEnd(out reason); + } + } + public abstract class GameEndPredicate { /// Checks the game ending condition and stores the value in CustomWinnerHolder. diff --git a/Patches/ExilePatch.cs b/Patches/ExilePatch.cs index 3ce59ba20..982abbac3 100644 --- a/Patches/ExilePatch.cs +++ b/Patches/ExilePatch.cs @@ -149,7 +149,7 @@ class ExileControllerWrapUpPatch PetsPatch.RpcRemovePet(pc); } - if (Options.RandomSpawn.GetBool() || Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) + if (Options.RandomSpawn.GetBool() || Options.CurrentGameMode != CustomGameMode.Standard) { RandomSpawn.SpawnMap map = Main.NormalOptions.MapId switch { diff --git a/Patches/GameOptionsMenuPatch.cs b/Patches/GameOptionsMenuPatch.cs index afbb0acd3..cfcc6ddab 100644 --- a/Patches/GameOptionsMenuPatch.cs +++ b/Patches/GameOptionsMenuPatch.cs @@ -406,6 +406,16 @@ public static class SetRecommendationsPatch __instance.NumEmergencyMeetings = 0; __instance.VisualTasks = true; break; + case CustomGameMode.HideAndSeek: + __instance.CrewLightMod = 1.25f; + __instance.ImpostorLightMod = 0.5f; + __instance.KillCooldown = 10f; + __instance.NumCommonTasks = 2; + __instance.NumLongTasks = 3; + __instance.NumShortTasks = 5; + __instance.NumEmergencyMeetings = 0; + __instance.VisualTasks = true; + break; } return false; diff --git a/Patches/HudPatch.cs b/Patches/HudPatch.cs index 2abbc6a91..0eacdd721 100644 --- a/Patches/HudPatch.cs +++ b/Patches/HudPatch.cs @@ -159,7 +159,7 @@ class HudManagerPatch if (SetHudActivePatch.IsActive) { - if (player.IsAlive() || Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) + if (player.IsAlive() || Options.CurrentGameMode != CustomGameMode.Standard) { bool usesPetInsteadOfKill = player.GetCustomRole().UsesPetInsteadOfKill(); if (usesPetInsteadOfKill) @@ -364,6 +364,7 @@ class HudManagerPatch CustomGameMode.FFA when player.PlayerId == 0 => FFAManager.GetHudText(), CustomGameMode.MoveAndStop when player.PlayerId == 0 => MoveAndStopManager.HUDText, CustomGameMode.HotPotato when player.PlayerId == 0 => HotPotatoManager.GetSuffixText(player.PlayerId), + CustomGameMode.HideAndSeek when player.PlayerId == 0 => CustomHideAndSeekManager.GetSuffixText(player, player, isHUD: true), CustomGameMode.Standard => player.GetCustomRole() switch { CustomRoles.BountyHunter => BountyHunter.GetTargetText(player, true), @@ -548,6 +549,10 @@ class SetHudActivePatch __instance.SabotageButton?.ToggleVisible(false); __instance.AbilityButton?.ToggleVisible(false); return; + case CustomGameMode.HideAndSeek: + __instance.ReportButton?.ToggleVisible(false); + __instance.SabotageButton?.ToggleVisible(false); + return; } var player = PlayerControl.LocalPlayer; @@ -776,10 +781,16 @@ class TaskPanelBehaviourPatch case CustomGameMode.HotPotato: List SummaryText4 = []; - SummaryText4.AddRange(from id in Main.PlayerStates.Keys.ToArray() let pc = Utils.GetPlayerById(id) let name = pc.GetRealName().RemoveHtmlTags().Replace("\r\n", string.Empty) let alive = pc.IsAlive() select $"{(!alive ? "<#777777>" : "")}{HotPotatoManager.GetIndicator(id)}{Utils.ColorString(Main.PlayerColors[id], name)}{(!alive ? " <#ff0000>DEAD" : "")}"); + SummaryText4.AddRange(from id in Main.PlayerStates.Keys let pc = Utils.GetPlayerById(id) let name = pc.GetRealName().RemoveHtmlTags().Replace("\r\n", string.Empty) let alive = pc.IsAlive() select $"{(!alive ? "<#777777>" : "")}{HotPotatoManager.GetIndicator(id)}{Utils.ColorString(Main.PlayerColors[id], name)}{(!alive ? " <#ff0000>DEAD" : "")}"); AllText += $"\r\n\r\n{string.Join('\n', SummaryText4)}"; + break; + + case CustomGameMode.HideAndSeek: + + AllText += $"\r\n\r\n{CustomHideAndSeekManager.GetTaskBarText()}"; + break; } diff --git a/Patches/IntroPatch.cs b/Patches/IntroPatch.cs index a3e38e1e5..0222197d8 100644 --- a/Patches/IntroPatch.cs +++ b/Patches/IntroPatch.cs @@ -72,13 +72,11 @@ class SetUpRoleTextPatch __instance.RoleBlurbText.text = "" + PlayerControl.LocalPlayer.GetRoleInfo() + ""; } - foreach (CustomRoles subRole in Main.PlayerStates[PlayerControl.LocalPlayer.PlayerId].SubRoles.ToArray()) + foreach (CustomRoles subRole in Main.PlayerStates[PlayerControl.LocalPlayer.PlayerId].SubRoles) { __instance.RoleBlurbText.text += "\n" + Utils.ColorString(Utils.GetRoleColor(subRole), GetString($"{subRole}Info")); } - //if (!PlayerControl.LocalPlayer.Is(CustomRoles.Lovers) && !PlayerControl.LocalPlayer.Is(CustomRoles.Ntr) && CustomRolesHelper.RoleExist(CustomRoles.Ntr)) - // __instance.RoleBlurbText.text += "\n" + Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), GetString($"{CustomRoles.Lovers}Info")); __instance.RoleText.text += Utils.GetSubRolesText(PlayerControl.LocalPlayer.PlayerId, false, true); break; } @@ -436,6 +434,13 @@ class BeginCrewmatePatch __instance.ImpostorText.gameObject.SetActive(true); __instance.ImpostorText.text = GetString("PotatoInfo"); break; + case CustomGameMode.HideAndSeek: + __instance.TeamTitle.text = GetString("HideAndSeek"); + __instance.TeamTitle.color = __instance.BackgroundBar.material.color = new Color32(52, 94, 235, byte.MaxValue); + PlayerControl.LocalPlayer.Data.Role.IntroSound = GetIntroSound(RoleTypes.Impostor); + __instance.ImpostorText.gameObject.SetActive(true); + __instance.ImpostorText.text = GetString("SubText.HideAndSeek"); + break; } if (Input.GetKey(KeyCode.RightShift)) @@ -553,7 +558,7 @@ class IntroCutsceneDestroyPatch Main.AllPlayerControls.Do(pc => pc.SetKillCooldown(Options.StartingKillCooldown.GetInt() - 2)); }, 2f, "FixKillCooldownTask"); } - else if (Options.FixFirstKillCooldown.GetBool() && Options.CurrentGameMode is not CustomGameMode.SoloKombat and not CustomGameMode.FFA and not CustomGameMode.MoveAndStop and not CustomGameMode.HotPotato) + else if (Options.FixFirstKillCooldown.GetBool() && Options.CurrentGameMode == CustomGameMode.Standard) { _ = new LateTask(() => { @@ -623,7 +628,7 @@ class IntroCutsceneDestroyPatch Main.PlayerStates[PlayerControl.LocalPlayer.PlayerId].SetDead(); } - if (Options.RandomSpawn.GetBool() || Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) + if (Options.RandomSpawn.GetBool() || Options.CurrentGameMode != CustomGameMode.Standard) { RandomSpawn.SpawnMap map = Main.NormalOptions.MapId switch { diff --git a/Patches/OutroPatch.cs b/Patches/OutroPatch.cs index b0ac3a4ca..25bf194f1 100644 --- a/Patches/OutroPatch.cs +++ b/Patches/OutroPatch.cs @@ -32,26 +32,25 @@ class EndGamePatch Main.SetRoles = []; Main.SetAddOns = []; SummaryText = []; + Main.LastAddOns = []; Main.ChangedRole = false; - foreach (var id in Main.PlayerStates.Keys) + foreach ((byte id, PlayerState state) in Main.PlayerStates) { if (Doppelganger.playerIdList.Count > 0 && Doppelganger.DoppelVictim.ContainsKey(id)) { var dpc = Utils.GetPlayerById(id); if (dpc != null) { - //if (id == PlayerControl.LocalPlayer.PlayerId) Main.nickName = Doppelganger.DoppelVictim[id]; - //else - //{ dpc.RpcSetName(Doppelganger.DoppelVictim[id]); - //} Main.AllPlayerNames[id] = Doppelganger.DoppelVictim[id]; } } SummaryText[id] = Utils.SummaryTexts(id, disableColor: false); + if (state.SubRoles.Count == 0) continue; + Main.LastAddOns[id] = $"{Utils.ColorString(Main.PlayerColors.GetValueOrDefault(id, Color.white), Main.AllPlayerNames.GetValueOrDefault(id, $"ID {id}"))}: {state.SubRoles.Join(x => Utils.ColorString(Utils.GetRoleColor(x), GetString($"{x}")))}"; } if (Options.DumpLogAfterGameEnd.GetBool()) @@ -65,9 +64,9 @@ class EndGamePatch var date = value.RealKiller.TIMESTAMP; if (date == DateTime.MinValue) continue; var killerId = value.GetRealKiller(); - sb.Append($"\n{date:T} {Main.AllPlayerNames[key]} ({(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato ? string.Empty : Utils.GetDisplayRoleName(key, true))}{(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop ? string.Empty : Utils.GetSubRolesText(key, summary: true))}) [{Utils.GetVitalText(key)}]"); + sb.Append($"\n{date:T} {Main.AllPlayerNames[key]} ({(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato or CustomGameMode.HideAndSeek ? string.Empty : Utils.GetDisplayRoleName(key, true))}{(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop ? string.Empty : Utils.GetSubRolesText(key, summary: true))}) [{Utils.GetVitalText(key)}]"); if (killerId != byte.MaxValue && killerId != key) - sb.Append($"\n\t⇐ {Main.AllPlayerNames[killerId]} ({(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato ? string.Empty : Utils.GetDisplayRoleName(killerId, true))}{(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop ? string.Empty : Utils.GetSubRolesText(killerId, summary: true))})"); + sb.Append($"\n\t⇐ {Main.AllPlayerNames[killerId]} ({(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato or CustomGameMode.HideAndSeek ? string.Empty : Utils.GetDisplayRoleName(killerId, true))}{(Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop ? string.Empty : Utils.GetSubRolesText(killerId, summary: true))})"); } KillLog = sb.ToString(); diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index ec9f78354..72d2f4efc 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -162,7 +162,7 @@ class CheckMurderPatch return false; } - var divice = Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato ? 3000f : 2000f; + var divice = Options.CurrentGameMode != CustomGameMode.Standard ? 3000f : 2000f; float minTime = Mathf.Max(0.02f, AmongUsClient.Instance.Ping / divice * 6f); // The value of AmongUsClient.Instance.Ping is in milliseconds (ms), so ÷1000 // No value is stored in TimeSinceLastKill || Stored time is greater than or equal to minTime => Allow kill // ↓ If not allowed @@ -213,6 +213,9 @@ class CheckMurderPatch case CustomGameMode.MoveAndStop: case CustomGameMode.HotPotato: return false; + case CustomGameMode.HideAndSeek: + CustomHideAndSeekManager.OnCheckMurder(killer, target); + return false; } if (Mastermind.ManipulatedPlayers.ContainsKey(killer.PlayerId)) @@ -720,7 +723,7 @@ class ReportDeadBodyPatch { if (GameStates.IsMeeting) return false; if (Options.DisableMeeting.GetBool()) return false; - if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) return false; + if (Options.CurrentGameMode != CustomGameMode.Standard) return false; if (!CanReport[__instance.PlayerId]) { WaitReport[__instance.PlayerId].Add(target); @@ -1203,7 +1206,7 @@ class FixedUpdatePatch RoleText.text = RoleTextData.Item1; RoleText.color = RoleTextData.Item2; - if (Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.SoloKombat or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) RoleText.text = string.Empty; + if (Options.CurrentGameMode != CustomGameMode.Standard) RoleText.text = string.Empty; RoleText.enabled = IsRoleTextEnabled(__instance); @@ -1493,6 +1496,9 @@ class FixedUpdatePatch case CustomGameMode.HotPotato when !seer.IsModClient() && seer.PlayerId == target.PlayerId && seer.IsAlive(): Suffix.Append(HotPotatoManager.GetSuffixText(seer.PlayerId)); break; + case CustomGameMode.HideAndSeek: + Suffix.Append(CustomHideAndSeekManager.GetSuffixText(seer, target)); + break; } if (Vulture.ArrowsPointingToDeadBody.GetBool()) @@ -1776,6 +1782,9 @@ class CoEnterVentPatch case CustomGameMode.HotPotato: _ = new LateTask(() => { __instance.myPlayer?.MyPhysics?.RpcBootFromVent(id); }, 0.5f); return true; + case CustomGameMode.HideAndSeek: + CustomHideAndSeekManager.OnCoEnterVent(__instance, id); + return true; } if (Glitch.hackedIdList.ContainsKey(__instance.myPlayer.PlayerId)) diff --git a/Patches/SabotageSystemPatch.cs b/Patches/SabotageSystemPatch.cs index e1528e066..d0f2738f5 100644 --- a/Patches/SabotageSystemPatch.cs +++ b/Patches/SabotageSystemPatch.cs @@ -252,7 +252,7 @@ public static class SabotageSystemTypeRepairDamagePatch public static bool Prefix([HarmonyArgument(0)] PlayerControl player) { - if (Options.DisableSabotage.GetBool() || Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) return false; + if (Options.DisableSabotage.GetBool() || Options.CurrentGameMode != CustomGameMode.Standard) return false; if (SecurityGuard.BlockSabo.Count > 0) return false; if (Glitch.hackedIdList.ContainsKey(player.PlayerId)) { diff --git a/Patches/ShipStatusPatch.cs b/Patches/ShipStatusPatch.cs index a347a8274..d410444fe 100644 --- a/Patches/ShipStatusPatch.cs +++ b/Patches/ShipStatusPatch.cs @@ -75,7 +75,7 @@ class RepairSystemPatch IsComms = PlayerControl.LocalPlayer.myTasks.ToArray().Any(x => x.TaskType == TaskTypes.FixComms); - if ((Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) && systemType == SystemTypes.Sabotage) return false; + if ((Options.CurrentGameMode != CustomGameMode.Standard) && systemType == SystemTypes.Sabotage) return false; if (Options.DisableSabotage.GetBool() && systemType == SystemTypes.Sabotage) return false; @@ -117,7 +117,7 @@ class RepairSystemPatch if (Options.DisableAirshipCargoLightsPanel.GetBool() && Vector2.Distance(player.transform.position, new(30.56f, 2.12f)) <= 2f) return false; break; case SystemTypes.Sabotage when AmongUsClient.Instance.NetworkMode != NetworkModes.FreePlay: - if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) return false; + if (Options.CurrentGameMode != CustomGameMode.Standard) return false; if (SecurityGuard.BlockSabo.Count > 0) return false; if (Glitch.hackedIdList.ContainsKey(player.PlayerId)) { @@ -289,7 +289,7 @@ class CheckTaskCompletionPatch { public static bool Prefix(ref bool __result) { - if (Options.DisableTaskWin.GetBool() || Options.NoGameEnd.GetBool() || TaskState.InitialTotalTasks == 0 || (Options.DisableTaskWinIfAllCrewsAreDead.GetBool() && !Main.AllAlivePlayerControls.Any(x => x.Is(CustomRoleTypes.Crewmate))) || Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) + if (Options.DisableTaskWin.GetBool() || Options.NoGameEnd.GetBool() || TaskState.InitialTotalTasks == 0 || (Options.DisableTaskWinIfAllCrewsAreDead.GetBool() && !Main.AllAlivePlayerControls.Any(x => x.Is(CustomRoleTypes.Crewmate))) || Options.CurrentGameMode != CustomGameMode.Standard) { __result = false; return false; diff --git a/Patches/TextBoxPatch.cs b/Patches/TextBoxPatch.cs index ee1533020..106230c6e 100644 --- a/Patches/TextBoxPatch.cs +++ b/Patches/TextBoxPatch.cs @@ -1,4 +1,4 @@ -using HarmonyLib; +using HarmonyLib; namespace TOHE.Patches; @@ -7,7 +7,7 @@ class TextBoxTMPCharAllowedPatch { public static bool Prefix([HarmonyArgument(0)] char i, ref bool __result) { - if (i is not ('+' or '<' or '>' or '"' or '*' or '#' or '@' or '$' or '%' or '^' or '&' or '(' or ')' or '-' or '=' or '_' or '{' or '}' or '[' or ']' or ':' or ';' or ',' or '.' or '?' or '/' or '|' or '\\' or '`' or '~')) return true; + if (i is not ('+' or '<' or '>' or '"' or '*' or '#' or '@' or '$' or '%' or '^' or '&' or '(' or ')' or '-' or '=' or '_' or '{' or '}' or '[' or ']' or ':' or ';' or ',' or '.' or '?' or '/' or '|' or '\\' or '`' or '~' or 'Н' or 'Г' or 'З' or 'В' or 'А' or 'П' or 'О' or 'Л' or 'Д' or 'Ж' or 'М' or 'И' or 'Б' or 'å' or 'ø' or 'æ' or 'ñ' or 'ä' or 'ö' or 'ü' or 'ß')) return true; __result = true; return false; diff --git a/Patches/UsablesPatch.cs b/Patches/UsablesPatch.cs index 46588879e..4b38ad959 100644 --- a/Patches/UsablesPatch.cs +++ b/Patches/UsablesPatch.cs @@ -20,7 +20,7 @@ class EmergencyMinigamePatch { public static void Postfix(EmergencyMinigame __instance) { - if (Options.DisableMeeting.GetBool() || Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) + if (Options.DisableMeeting.GetBool() || Options.CurrentGameMode != CustomGameMode.Standard) __instance.Close(); } } diff --git a/Patches/onGameStartedPatch.cs b/Patches/onGameStartedPatch.cs index e7958e4d9..6334ef074 100644 --- a/Patches/onGameStartedPatch.cs +++ b/Patches/onGameStartedPatch.cs @@ -451,7 +451,7 @@ internal class SelectRolesPatch } // For other gamemodes: - if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato) + if (Options.CurrentGameMode != CustomGameMode.Standard) { foreach (var pair in Main.PlayerStates) ExtendedPlayerControl.RpcSetCustomRole(pair.Key, pair.Value.MainRole); @@ -569,6 +569,9 @@ internal class SelectRolesPatch case CustomGameMode.HotPotato: GameEndChecker.SetPredicateToHotPotato(); break; + case CustomGameMode.HideAndSeek: + GameEndChecker.SetPredicateToHideAndSeek(); + break; } GameOptionsSender.AllSenders.Clear(); diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index bf5bceead..02b1efa80 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -3225,6 +3225,30 @@ "Potato": "Player", "PotatoInfo": "AVOID HAVING THE HOT POTATO", "PotatoInfoLong": "AVOID HAVING THE HOT POTATO", + "HideAndSeek": "HIDE AND SEEK", + "ModeHideAndSeek": "Gamemode: Hide And Seek", + "ModeDescribe.HideAndSeek": "In the Hide And Seek gamemode, seekers have to kill all hiders, while hiders have to complete all tasks without being killed in order to win.", + "HideAndSeek_MaxGameTime": "Maximum Game Length", + "SeekerVision": "Seeker Vision", + "HiderVision": "Hider Vision", + "SeekerSpeed": "Seeker Speed", + "HiderSpeed": "Hider Speed", + "Hider": "HIDER", + "HiderInfo": "COMPLETE TASKS TO WIN", + "HiderInfoLong": "COMPLETE TASKS TO WIN", + "Seeker": "SEEKER", + "SeekerInfo": "KILL ALL HIDERS TO WIN", + "SeekerInfoLong": "KILL ALL HIDERS TO WIN", + "Fox": "FOX", + "FoxInfo": "SURVIVE UNTIL THE END TO WIN", + "FoxInfoLong": "SURVIVE UNTIL THE END TO WIN", + "FoxVision": "Fox Vision", + "FoxSpeed": "Fox Speed", + "Troll": "TROLL", + "TrollInfo": "GET KILLED TO WIN", + "TrollInfoLong": "GET KILLED TO WIN", + "TrollVision": "Troll Vision", + "TrollSpeed": "Troll Speed", "GNoCommandInfo": "This Command can only be used when in lobby or after you die.\\n\\ntype /gno X to play guess a number. X can be a number between 0 and 99 (both included). \\n\\nYou get maximum of 7 tries to guess the number.\\n\\n Example:- /gno 10", "GNoLost": "Oh, you were so close! Just one more guess, and you might have deciphered the Da Vinci code! By the way, the secret number was... {0}! But hey, you were only off by a few billion possibilities. Better luck next time, Sherlock! ", "GNoLow": "Oh, you're really nailing this! It's so low, I almost need a shovel to dig it up!\\nYou have {0} guesses left!", @@ -3772,6 +3796,5 @@ "RoleSelected": "The role of {0} in the next game will be{1}", "UpReplacedMessage": "/up was replaced by /setrole which allows you to set anyone's role for any game by typing '/setrole (ID) (ROLE)'. You can view ID's with /id.\nTo set your own role like with /up, you need to do '/setrole 0 (ROLE)'.", "PingText": "Ping", - "SettingsForRoleText": "Settings for", - "NotAssigned": " " + "SettingsForRoleText": "Settings for" } diff --git a/Roles/AddOns/Impostor/LastImpostor.cs b/Roles/AddOns/Impostor/LastImpostor.cs index bddd89909..1dd75bd74 100644 --- a/Roles/AddOns/Impostor/LastImpostor.cs +++ b/Roles/AddOns/Impostor/LastImpostor.cs @@ -32,9 +32,7 @@ public class LastImpostor : IAddon public static void SetSubRole() { if (currentId != byte.MaxValue || !AmongUsClient.Instance.AmHost) return; - if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato - || !CustomRoles.LastImpostor.IsEnable() || Main.AliveImpostorCount != 1) - return; + if (Options.CurrentGameMode != CustomGameMode.Standard || !CustomRoles.LastImpostor.IsEnable() || Main.AliveImpostorCount != 1) return; foreach (PlayerControl pc in Main.AllAlivePlayerControls) { if (CanBeLastImpostor(pc)) diff --git a/main.cs b/main.cs index 780deb7ec..2c4b5d584 100644 --- a/main.cs +++ b/main.cs @@ -96,6 +96,7 @@ public class Main : BasePlugin public static Dictionary> SetAddOns = []; public static Dictionary AlwaysSpawnTogetherCombos = []; public static Dictionary NeverSpawnTogetherCombos = []; + public static Dictionary LastAddOns = []; public static List AllRoleClasses; public static float RefixCooldownDelay; public static bool ProcessShapeshifts = true; @@ -909,6 +910,12 @@ public enum CustomRoles //HotPotato Potato, + //H&S + Hider, + Seeker, + Fox, + Troll, + //GM GM, @@ -994,6 +1001,11 @@ public enum CustomWinner None = -3, Error = -4, Neutrals = -5, + + // Hide And Seek + Hider = -6, + Seeker = -7, + Troll = -8, Impostor = CustomRoles.Impostor, Crewmate = CustomRoles.Crewmate, Jester = CustomRoles.Jester,