From 38ac451a70949406c84722785595bb40d92e7258 Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Mon, 18 May 2026 13:14:55 +0200 Subject: [PATCH] a few fixes --- Gamemodes/BedWars.cs | 75 +++++++++++-------- Gamemodes/CaptureTheFlag.cs | 4 +- Gamemodes/Deathrace.cs | 2 +- Gamemodes/FreeForAll.cs | 2 +- Gamemodes/Mingle.cs | 2 +- Gamemodes/SoloPVP.cs | 2 +- Modules/CustomRoleSelector.cs | 4 +- Modules/CustomRpcSender.cs | 46 +++++++++--- Modules/CustomSounds.cs | 2 +- Modules/CustomTeamManager.cs | 15 ++-- Modules/ExtendedPlayerControl.cs | 8 +- .../GameOptionsSender/GameOptionsSender.cs | 5 +- Modules/Utils.cs | 2 +- Patches/ChatCommandPatch.cs | 2 +- Patches/CheckGameEndPatch.cs | 24 +++++- Patches/ExceptionSwallowers.cs | 19 +++-- Patches/HudPatch.cs | 12 ++- Patches/IntroPatch.cs | 4 +- Patches/MeetingHudPatch.cs | 3 + Patches/PlayerJoinAndLeftPatch.cs | 6 +- Roles/Standard/Impostor/Vanilla/PhantomEHR.cs | 6 +- Roles/Standard/Neutral/Pariah/Magistrate.cs | 23 +++++- 22 files changed, 179 insertions(+), 89 deletions(-) diff --git a/Gamemodes/BedWars.cs b/Gamemodes/BedWars.cs index 941d95b90..e28a47fac 100644 --- a/Gamemodes/BedWars.cs +++ b/Gamemodes/BedWars.cs @@ -443,7 +443,7 @@ public static class BedWars // Assign players to teams List players = Main.EnumerateAlivePlayerControls().Shuffle(); - if (Main.GM.Value) players.RemoveAll(x => x.IsHost()); + if (Main.GM.Value) players.RemoveAll(x => x.AmOwner); if (ChatCommands.Spectators.Count > 0) players.RemoveAll(x => ChatCommands.Spectators.Contains(x.PlayerId)); Dictionary playerTeams = players @@ -488,25 +488,28 @@ public static class BedWars if (!pc.AmOwner) { - sender.StartMessage(pc.OwnerId); - - sender.StartRpc(pc.NetId, RpcCalls.ProtectPlayer) - .WriteNetObject(pc) - .Write(0) - .EndRpc(); - - foreach ((byte otherId, BedWarsTeam otherTeam) in playerTeams) + if (pc.OwnerId >= 0) { - PlayerControl target = otherId.GetPlayer(); - if (!target || target.PlayerId == pc.PlayerId || otherTeam != team) continue; + sender.StartMessage(pc.OwnerId); - sender.StartRpc(target.NetId, RpcCalls.SetRole) - .Write((ushort)RoleTypes.Impostor) - .Write(true) + sender.StartRpc(pc.NetId, RpcCalls.ProtectPlayer) + .WriteNetObject(pc) + .Write(0) .EndRpc(); - } - sender.EndMessage(); + foreach ((byte otherId, BedWarsTeam otherTeam) in playerTeams) + { + PlayerControl target = otherId.GetPlayer(); + if (!target || target.PlayerId == pc.PlayerId || otherTeam != team) continue; + + sender.StartRpc(target.NetId, RpcCalls.SetRole) + .Write((ushort)RoleTypes.Impostor) + .Write(true) + .EndRpc(); + } + + sender.EndMessage(); + } } else { @@ -1676,9 +1679,11 @@ public static class BedWars public override string ToString() { + bool vanillaServer = GameStates.CurrentServerType == GameStates.ServerType.Vanilla; + var i = 0; List itemsDisplays = []; - string bottomText = Utils.EmptyMessage; + string bottomText = string.Empty; foreach ((Item item, int count) in Items) { @@ -1689,9 +1694,9 @@ public static class BedWars if (count > 1) { - sb.Append(""); + sb.Append(vanillaServer ? "X" : ""); sb.Append(count); - sb.Append(""); + if (!vanillaServer) sb.Append(""); } itemsDisplays.Add(sb.ToString()); @@ -1700,22 +1705,23 @@ public static class BedWars } while (itemsDisplays.Count < InventorySlots) - itemsDisplays.Add(Utils.ColorString(Color.clear, "---")); + itemsDisplays.Add(Utils.ColorString(Color.clear, vanillaServer ? string.Empty : "---")); const string baseColor = "<#000000>"; var finalSb = new StringBuilder(); finalSb.Append(baseColor); - finalSb.AppendLine("▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁"); - finalSb.Append(""); + if (!vanillaServer) finalSb.AppendLine("▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁"); i = 0; foreach (string itemsDisplay in itemsDisplays) { - bool selected = i == SelectedSlot || i - 1 == SelectedSlot; - if (!selected) finalSb.Append(baseColor); + bool currentSelected = i == SelectedSlot; + bool previousSelected = i - 1 == SelectedSlot; + bool selected = currentSelected || previousSelected; + if (currentSelected) finalSb.Append(""); finalSb.Append(selected ? '┃' : '│'); - if (!selected) finalSb.Append(""); + if (previousSelected) finalSb.Append(baseColor); finalSb.Append(' '); finalSb.Append(itemsDisplay); finalSb.Append(' '); @@ -1723,15 +1729,20 @@ public static class BedWars } bool lastSelected = i - 1 == SelectedSlot; - if (!lastSelected) finalSb.Append(baseColor); finalSb.Append(lastSelected ? '┃' : '│'); - if (!lastSelected) finalSb.Append(""); - finalSb.AppendLine(baseColor); - finalSb.Append("▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔"); - finalSb.AppendLine(""); - finalSb.AppendLine(); - finalSb.Append(Utils.ColorString(Color.white, bottomText)); + if (!vanillaServer) + { + if (lastSelected) finalSb.Append(baseColor); + finalSb.Append("▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔"); + finalSb.AppendLine(); + finalSb.Append(Utils.ColorString(Color.white, bottomText)); + finalSb.AppendLine(""); + } + else if (!lastSelected) + { + finalSb.AppendLine(""); + } return finalSb.ToString(); } diff --git a/Gamemodes/CaptureTheFlag.cs b/Gamemodes/CaptureTheFlag.cs index 6a0b4ebf1..78f4a40e3 100644 --- a/Gamemodes/CaptureTheFlag.cs +++ b/Gamemodes/CaptureTheFlag.cs @@ -355,7 +355,7 @@ public static class CaptureTheFlag // Assign players to teams List players = Main.EnumerateAlivePlayerControls().Shuffle(); - if (Main.GM.Value) players.RemoveAll(x => x.IsHost()); + if (Main.GM.Value) players.RemoveAll(x => x.AmOwner); if (ChatCommands.Spectators.Count > 0) players.RemoveAll(x => ChatCommands.Spectators.Contains(x.PlayerId)); int blueCount = players.Count / 2; @@ -425,7 +425,7 @@ public static class CaptureTheFlag try { var pc1 = id1.GetPlayer(); - if (!pc1 || pc1.AmOwner) continue; + if (!pc1 || pc1.AmOwner || pc1.OwnerId < 0) continue; sender.StartMessage(pc1.OwnerId); diff --git a/Gamemodes/Deathrace.cs b/Gamemodes/Deathrace.cs index 4e68c42c1..9d2cf096a 100644 --- a/Gamemodes/Deathrace.cs +++ b/Gamemodes/Deathrace.cs @@ -224,7 +224,7 @@ public static class Deathrace Logger.Info($"Track: {string.Join(" » ", Track)}", "Deathrace"); List players = Main.EnumerateAlivePlayerControls().ToList(); - if (Main.GM.Value) players.RemoveAll(x => x.IsHost()); + if (Main.GM.Value) players.RemoveAll(x => x.AmOwner); if (ChatCommands.Spectators.Count > 0) players.RemoveAll(x => ChatCommands.Spectators.Contains(x.PlayerId)); Data = players.ToDictionary(x => x.PlayerId, x => new PlayerData diff --git a/Gamemodes/FreeForAll.cs b/Gamemodes/FreeForAll.cs index dd4a6c246..7da54d313 100644 --- a/Gamemodes/FreeForAll.cs +++ b/Gamemodes/FreeForAll.cs @@ -327,7 +327,7 @@ internal static class FreeForAll break; } - if (killer.IsHost()) Main.AllPlayerKillCooldown[killer.PlayerId] += Utils.CalculatePingDelay(); + if (killer.AmOwner) Main.AllPlayerKillCooldown[killer.PlayerId] += Utils.CalculatePingDelay(); if (sync || Math.Abs(nowKCD - Main.AllPlayerKillCooldown[killer.PlayerId]) > 0.1f) { diff --git a/Gamemodes/Mingle.cs b/Gamemodes/Mingle.cs index 1493c0c4b..cbc5904b0 100644 --- a/Gamemodes/Mingle.cs +++ b/Gamemodes/Mingle.cs @@ -248,7 +248,7 @@ public static class Mingle yield return new WaitForSecondsRealtime(Main.CurrentMap == MapNames.Airship ? 8f : 3f); List players = Main.EnumerateAlivePlayerControls().ToList(); - if (Main.GM.Value) players.RemoveAll(x => x.IsHost()); + if (Main.GM.Value) players.RemoveAll(x => x.AmOwner); if (ChatCommands.Spectators.Count > 0) players.RemoveAll(x => ChatCommands.Spectators.Contains(x.PlayerId)); bool showTutorial = players.ExceptBy(HasPlayedFCs, x => x.FriendCode).Count() > players.Count / 2; diff --git a/Gamemodes/SoloPVP.cs b/Gamemodes/SoloPVP.cs index 7d30e3c50..b7b9bbdab 100644 --- a/Gamemodes/SoloPVP.cs +++ b/Gamemodes/SoloPVP.cs @@ -299,7 +299,7 @@ internal static class SoloPVP float addRate = IRandom.Instance.Next(3, 5 + GetRankFromScore(killer.PlayerId)) / 100f; addRate *= SoloPVP_KillBonusMultiplier.GetFloat(); - if (killer.IsHost()) addRate /= 2f; + if (killer.AmOwner) addRate /= 2f; var text = string.Empty; float addin; diff --git a/Modules/CustomRoleSelector.cs b/Modules/CustomRoleSelector.cs index d5fa1170f..f9dee9c9f 100644 --- a/Modules/CustomRoleSelector.cs +++ b/Modules/CustomRoleSelector.cs @@ -302,7 +302,7 @@ internal static class CustomRoleSelector if (Main.GM.Value) { Logger.Warn("Host: GM", "CustomRoleSelector"); - allPlayers.RemoveAll(x => x.IsHost()); + allPlayers.RemoveAll(x => x.AmOwner); RoleResult[PlayerControl.LocalPlayer.PlayerId] = CustomRoles.GM; } @@ -398,7 +398,7 @@ internal static class CustomRoleSelector { foreach (PlayerControl pc in Main.CachedAllPlayerControls()) { - if ((Main.GM.Value && pc.IsHost()) || ChatCommands.Spectators.Contains(pc.PlayerId)) + if ((Main.GM.Value && pc.AmOwner) || ChatCommands.Spectators.Contains(pc.PlayerId)) { RoleResult[pc.PlayerId] = CustomRoles.GM; continue; diff --git a/Modules/CustomRpcSender.cs b/Modules/CustomRpcSender.cs index 92ab63a98..1230069d3 100644 --- a/Modules/CustomRpcSender.cs +++ b/Modules/CustomRpcSender.cs @@ -156,18 +156,42 @@ public class CustomRpcSender public void SendMessage(bool dispose = false) { - if (currentState == State.InRootMessage) EndMessage(); - - if (currentState == State.InRootPackedMessage) EndMessage(); - - if (currentState != State.Ready && !dispose) + if (!dispose) { - var errorMsg = $"Tried to send RPC but State is not Ready (in: \"{name}\", state: {currentState})"; + if (currentState == State.InRootMessage) EndMessage(); + + if (currentState == State.InRootPackedMessage) + { + static int GetPackedIntSize(int value) + { + uint v = (uint)value; + int count = 0; - if (isUnsafe) - Logger.Warn(errorMsg, "CustomRpcSender.Warn"); - else - throw new InvalidOperationException(errorMsg); + do + { + v >>= 7; + count++; + } + while (v != 0); + + return count; + } + + if (1 + GetPackedIntSize(AmongUsClient.Instance.GameId) >= stream.Length) + dispose = true; + else + EndMessage(); + } + + if (currentState != State.Ready) + { + var errorMsg = $"Tried to send RPC but State is not Ready (in: \"{name}\", state: {currentState})"; + + if (isUnsafe) + Logger.Warn(errorMsg, "CustomRpcSender.Warn"); + else + throw new InvalidOperationException(errorMsg); + } } if (stream.Length > 1200 && !dispose) Logger.Msg($"Large packet \"{name}\" is sending ({stream.Length} bytes)", "CustomRpcSender"); @@ -239,7 +263,7 @@ public class CustomRpcSender if (currentState == State.InRootPackedMessage && targetClientId < 0) { - var errorMsg = $"Tried to start RPC automatically, but State is InRootPackedMessage and the requested targetClientId is negative. Only GameDataTo messages can be started in this state. (in: \"{name}\")"; + var errorMsg = $"Tried to start RPC, but State is InRootPackedMessage and the requested targetClientId is negative. Only GameDataTo messages can be started in this state. (in: \"{name}\")"; if (isUnsafe) Logger.Warn(errorMsg, "CustomRpcSender.Warn"); diff --git a/Modules/CustomSounds.cs b/Modules/CustomSounds.cs index f2ffc2008..397eeb2c6 100644 --- a/Modules/CustomSounds.cs +++ b/Modules/CustomSounds.cs @@ -107,7 +107,7 @@ public static class CustomSoundsManager var fileData = Il2CppSystem.IO.File.ReadAllBytes(path); WAV wav = new(fileData); - Logger.Info($"[WAV: LeftChannel={wav.LeftChannel}, RightChannel={wav.RightChannel}, ChannelCount={wav.ChannelCount}, SampleCount={wav.SampleCount}, Frequency={wav.Frequency}]", "CustomSounds"); + Logger.Info($"[WAV: ChannelCount={wav.ChannelCount}, SampleCount={wav.SampleCount}, Frequency={wav.Frequency}]", "CustomSounds"); AudioClip clip = AudioClip.Create(Path.GetFileNameWithoutExtension(path), wav.SampleCount, 1, wav.Frequency, false, false); clip.SetData(wav.LeftChannel, 0); diff --git a/Modules/CustomTeamManager.cs b/Modules/CustomTeamManager.cs index 3380e1471..4cdf9a8ad 100644 --- a/Modules/CustomTeamManager.cs +++ b/Modules/CustomTeamManager.cs @@ -77,7 +77,10 @@ internal static class CustomTeamManager public static void InitializeCustomTeamPlayers() { + WinnerTeam = null; + CustomTeamPlayerIds.Clear(); UpdateEnabledTeams(); + if (EnabledCustomTeams.Count == 0) return; var aapc = Main.CachedAlivePlayerControls(); @@ -162,7 +165,7 @@ internal static class CustomTeamManager public static string GetSuffix(PlayerControl seer) { - if (seer == null || EnabledCustomTeams.Count == 0 || Main.HasJustStarted || !IsSettingEnabledForPlayerTeam(seer.PlayerId, CTAOption.Arrows)) return string.Empty; + if (EnabledCustomTeams.Count == 0 || Main.HasJustStarted || !IsSettingEnabledForPlayerTeam(seer.PlayerId, CTAOption.Arrows)) return string.Empty; return CustomTeamPlayerIds[GetCustomTeam(seer.PlayerId)].Aggregate(string.Empty, (s, id) => s + Utils.ColorString(Main.PlayerColors.GetValueOrDefault(id, Color.white), TargetArrow.GetArrows(seer, id))); } @@ -205,11 +208,8 @@ internal static class CustomTeamManager } AliveTeamPlayers.Clear(); - foreach (var kvp in CustomTeamPlayerIds) + foreach ((CustomTeam teamKey, HashSet originalSet) in CustomTeamPlayerIds) { - CustomTeam teamKey = kvp.Key; - var originalSet = kvp.Value; - HashSet aliveSet = null; foreach (var id in originalSet) { @@ -237,7 +237,7 @@ internal static class CustomTeamManager PlayerControl player = aapc[i]; CustomTeam playerTeam = GetCustomTeam(player.PlayerId); - if (playerTeam == null || playerTeam != onlyTeam) + if (playerTeam == null || !Equals(playerTeam, onlyTeam)) return false; } @@ -311,9 +311,10 @@ internal static class CustomTeamManager RoleRevealScreenBackgroundColor = parts[3]; TeamMembers = parts[4].Split(',').Select(x => Enum.Parse(x, true)).ToList(); + + CustomTeams.Add(this); } catch (Exception e) { Utils.ThrowException(e); } - finally { CustomTeams.Add(this); } } public List TeamMembers { get; } = []; diff --git a/Modules/ExtendedPlayerControl.cs b/Modules/ExtendedPlayerControl.cs index e1d88a614..0970b42ad 100644 --- a/Modules/ExtendedPlayerControl.cs +++ b/Modules/ExtendedPlayerControl.cs @@ -184,7 +184,7 @@ internal static class ExtendedPlayerControl foreach (PlayerControl pc in Main.CachedAlivePlayerControls()) { - if (pc == player || pc.AmOwner) continue; + if (pc == player || pc.AmOwner || pc.OwnerId < 0) continue; sender.StartMessage(pc.OwnerId); sender.StartRpc(player.NetTransform.NetId, (byte)RpcCalls.SnapTo) .WriteVector2(player.transform.position) @@ -1531,7 +1531,7 @@ internal static class ExtendedPlayerControl foreach (PlayerControl pc in PlayerControl.AllPlayerControls) { - if (pc.AmOwner || pc == player || (!phantom && pc.IsModdedClient()) || (phantom && pc.IsImpostor())) continue; + if (pc.AmOwner || pc.OwnerId < 0 || pc == player || (!phantom && pc.IsModdedClient()) || (phantom && pc.IsImpostor())) continue; sender.StartMessage(pc.OwnerId); sender.StartRpc(player.NetTransform.NetId, RpcCalls.SnapTo) @@ -1584,7 +1584,7 @@ internal static class ExtendedPlayerControl foreach (PlayerControl pc in PlayerControl.AllPlayerControls) { - if (pc.AmOwner || pc == player || (!phantom && pc.IsModdedClient()) || (phantom && pc.IsImpostor())) continue; + if (pc.AmOwner || pc.OwnerId < 0 || pc == player || (!phantom && pc.IsModdedClient()) || (phantom && pc.IsImpostor())) continue; sender.StartMessage(pc.OwnerId); sender.StartRpc(player.NetTransform.NetId, RpcCalls.SnapTo) @@ -1621,7 +1621,7 @@ internal static class ExtendedPlayerControl foreach (PlayerControl pc in PlayerControl.AllPlayerControls) { - if (pc.AmOwner || pc == player || (!phantom && pc.IsModdedClient()) || (phantom && pc.IsImpostor())) continue; + if (pc.AmOwner || pc.OwnerId < 0 || pc == player || (!phantom && pc.IsModdedClient()) || (phantom && pc.IsImpostor())) continue; sender.StartMessage(pc.OwnerId); sender.RpcExiled(player, autoStartRpc: false, exileForHost: false); diff --git a/Modules/GameOptionsSender/GameOptionsSender.cs b/Modules/GameOptionsSender/GameOptionsSender.cs index 4e916ed4f..d3d4ea45a 100644 --- a/Modules/GameOptionsSender/GameOptionsSender.cs +++ b/Modules/GameOptionsSender/GameOptionsSender.cs @@ -87,6 +87,9 @@ public abstract class GameOptionsSender protected static MessageWriter PackedWriter; protected static int PackedWriterMessages; + + // Currently, a LogicOptions serialize is 155-156 bytes. 11 bytes are needed for the packet headers. + // Safe to pack until the length is over 1000, as it's impossible to exceed 1200 with 156 bytes per message. public static IEnumerator SendDirtyGameOptionsContinuously() { @@ -106,7 +109,7 @@ public abstract class GameOptionsSender { yield return WaitFrameIfNecessary(); - if (PackedWriter != null && (PackedWriter.Length > 500 || PackedWriterMessages >= AmongUsClient.Instance.GetMaxMessagePackingLimit())) + if (PackedWriter != null && (PackedWriter.Length > 1000 || PackedWriterMessages >= AmongUsClient.Instance.GetMaxMessagePackingLimit())) { PackedWriter.EndMessage(); var qa = DataFlagRateLimiter.Enqueue(() => AmongUsClient.Instance.SendOrDisconnect(PackedWriter)); diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 00bc79e5e..3f25bc287 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -2860,7 +2860,7 @@ public static class Utils var fontSize = Options.LargerRoleTextSize.GetBool() ? "2" : "1.7"; - if (forMeeting && (seer.GetClient().PlatformData.Platform == Platforms.Playstation || seer.GetClient().PlatformData.Platform == Platforms.Switch)) + if (forMeeting && (seer.GetClient().PlatformData.Platform is Platforms.Playstation or Platforms.Switch)) fontSize = "70%"; // Text containing progress, such as tasks diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index 706915659..1f3aca281 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -2170,7 +2170,7 @@ internal static class ChatCommands { string kickedPlayerName = kickedPlayer.GetRealName(); var textToSend = $"{kickedPlayerName} {GetString("KickCommandKicked")}"; - if (GameStates.IsInGame) textToSend += string.Format(GetString("KickCommandKickedRole"), kickedPlayer.GetCustomRole().ToColoredString()); + if (GameStates.IsInGame) textToSend += $"\n{string.Format(GetString("KickCommandKickedRole"), kickedPlayer.GetCustomRole().ToColoredString())}"; if (args.Length >= 3) textToSend += $"\n{GetString("KickCommandKickedReason")} {string.Join(' ', args[2..])}"; Utils.SendMessage(textToSend, importance: GameStates.IsInGame ? MessageImportance.Medium : MessageImportance.Low); diff --git a/Patches/CheckGameEndPatch.cs b/Patches/CheckGameEndPatch.cs index 4f5f5cefe..4562be778 100644 --- a/Patches/CheckGameEndPatch.cs +++ b/Patches/CheckGameEndPatch.cs @@ -349,6 +349,8 @@ internal static class GameEndChecker WinnerIds.UnionWith(Main.EnumeratePlayerControls().Where(x => x.GetCustomRole().IsNeutral()).Select(x => x.PlayerId)); else if (Options.NeutralRoleWinTogether.GetBool()) { + List toAdd = null; + foreach (byte id in WinnerIds) { PlayerControl pc = GetPlayerById(id); @@ -357,9 +359,14 @@ internal static class GameEndChecker foreach (PlayerControl tar in Main.CachedAllPlayerControls()) { if (!WinnerIds.Contains(tar.PlayerId) && tar.GetCustomRole() == pc.GetCustomRole()) - WinnerIds.Add(tar.PlayerId); + { + toAdd ??= []; + toAdd.Add(tar.PlayerId); + } } } + + toAdd.ForEach(x => WinnerIds.Add(x)); foreach (CustomRoles role in WinnerRoles) WinnerIds.UnionWith(Main.EnumeratePlayerControls().Where(x => x.GetCustomRole() == role).Select(x => x.PlayerId)); } @@ -637,9 +644,15 @@ internal static class GameEndChecker var role = pc.GetCustomRole(); var countType = pc.GetCountTypes(); - if (role == CustomRoles.Sunnyboy) hasSunnyboy = true; - if (role == CustomRoles.Pawn) hasPawn = true; - if (countType == CountTypes.CustomTeam) hasCustomTeamCount = true; + switch (role) + { + case CustomRoles.Sunnyboy: + hasSunnyboy = true; + break; + case CustomRoles.Pawn: + hasPawn = true; + break; + } switch (countType) { @@ -652,6 +665,9 @@ internal static class GameEndChecker case CountTypes.Coven: coven++; break; + case CountTypes.CustomTeam: + hasCustomTeamCount = true; + break; } if (!hasKillerNonCrew && pc.CanUseKillButton() && !pc.IsCrewmate()) diff --git a/Patches/ExceptionSwallowers.cs b/Patches/ExceptionSwallowers.cs index 36e963643..66fc6406f 100644 --- a/Patches/ExceptionSwallowers.cs +++ b/Patches/ExceptionSwallowers.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Reflection; using HarmonyLib; using InnerNet; @@ -7,14 +9,19 @@ namespace EHR.Patches; // These methods sometimes throw random exceptions in the base game code and stop the code after them from executing // Simply swallow the exception and continue as if nothing happened -[HarmonyPatch(typeof(AbilityButton), nameof(AbilityButton.SetFromSettings))] -[HarmonyPatch(typeof(ActionButton), nameof(ActionButton.SetEnabled))] -[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RawSetName))] -[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetName))] -[HarmonyPatch(typeof(CosmeticsLayer), nameof(CosmeticsLayer.UpdateBodyMaterial))] -[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.SendOrDisconnect))] +[HarmonyPatch] static class ExceptionSwallowers { + public static IEnumerable TargetMethods() + { + yield return AccessTools.Method(typeof(AbilityButton), nameof(AbilityButton.SetFromSettings)); + yield return AccessTools.Method(typeof(ActionButton), nameof(ActionButton.SetEnabled)); + yield return AccessTools.Method(typeof(PlayerControl), nameof(PlayerControl.RawSetName)); + yield return AccessTools.Method(typeof(PlayerControl), nameof(PlayerControl.SetName)); + yield return AccessTools.Method(typeof(CosmeticsLayer), nameof(CosmeticsLayer.UpdateBodyMaterial)); + yield return AccessTools.Method(typeof(InnerNetClient), nameof(InnerNetClient.SendOrDisconnect)); + } + public static Exception Finalizer() { return null; diff --git a/Patches/HudPatch.cs b/Patches/HudPatch.cs index 0ce5e1ca3..f754f04da 100644 --- a/Patches/HudPatch.cs +++ b/Patches/HudPatch.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; +using System.Reflection; using TMPro; using UnityEngine; using static EHR.Translator; @@ -1027,11 +1028,16 @@ internal static class MapRoomDoorsUpdatePatch } } -[HarmonyPatch(typeof(CrewmateGhostRole), nameof(CrewmateGhostRole.SpawnTaskHeader))] -[HarmonyPatch(typeof(ImpostorGhostRole), nameof(ImpostorGhostRole.SpawnTaskHeader))] -[HarmonyPatch(typeof(ImpostorRole), nameof(ImpostorRole.SpawnTaskHeader))] +[HarmonyPatch] internal static class SpawnTaskHeaderPatch { + public static IEnumerable TargetMethods() + { + yield return AccessTools.Method(typeof(CrewmateGhostRole), nameof(CrewmateGhostRole.SpawnTaskHeader)); + yield return AccessTools.Method(typeof(ImpostorGhostRole), nameof(ImpostorGhostRole.SpawnTaskHeader)); + yield return AccessTools.Method(typeof(ImpostorRole), nameof(ImpostorRole.SpawnTaskHeader)); + } + public static bool Prefix() { return !GameStates.InGame; diff --git a/Patches/IntroPatch.cs b/Patches/IntroPatch.cs index fe35a8bc8..9ea86284e 100644 --- a/Patches/IntroPatch.cs +++ b/Patches/IntroPatch.cs @@ -1129,7 +1129,7 @@ internal static class IntroCutsceneDestroyPatch Main.IntroDestroyed = true; PreventKill = true; - LateTask.New(() => PreventKill = false, 10f, "PreventKillReset"); + LateTask.New(() => PreventKill = false, Options.StartingKillCooldown?.GetFloat() ?? 10f, "PreventKillReset"); var apc = Main.AllPlayerControlsToList; @@ -1164,7 +1164,7 @@ internal static class IntroCutsceneDestroyPatch } else { - int kcd = Options.StartingKillCooldown.GetInt(); + int kcd = Options.StartingKillCooldown?.GetInt() ?? 10; LateTask.New(() => aapc.Do(x => x.SetKillCooldown(kcd)), 2f, "FixKillCooldownTask"); } } diff --git a/Patches/MeetingHudPatch.cs b/Patches/MeetingHudPatch.cs index 100e3c46e..c07f759cf 100644 --- a/Patches/MeetingHudPatch.cs +++ b/Patches/MeetingHudPatch.cs @@ -1028,6 +1028,9 @@ internal static class MeetingHudStartPatch { string name = pc.GetRealName(true); + if (Magistrate.CallCourtNextMeeting) + name = seer.Is(CustomRoles.Magistrate) ? GetString("Magistrate.CourtName") : GetString("Magistrate.JuryName"); + foreach (PlayerControl seerPc in Main.EnumeratePlayerControls()) { try { Main.LastNotifyNames[(pc.PlayerId, seerPc.PlayerId)] = name; } diff --git a/Patches/PlayerJoinAndLeftPatch.cs b/Patches/PlayerJoinAndLeftPatch.cs index 77efd0d6a..78545fbb3 100644 --- a/Patches/PlayerJoinAndLeftPatch.cs +++ b/Patches/PlayerJoinAndLeftPatch.cs @@ -89,7 +89,7 @@ internal static class OnGameJoinedPatch try { - ClientData client = PlayerControl.LocalPlayer?.GetClient(); + ClientData client = PlayerControl.LocalPlayer.GetClient(); if (BanManager.CheckEACList(PlayerControl.LocalPlayer.FriendCode, client.GetHashedPuid()) && GameStates.IsOnlineGame) { @@ -606,11 +606,13 @@ internal static class OnPlayerLeftPatch PlayerState state = Main.PlayerStates[id]; if (state.deathReason == PlayerState.DeathReason.etc) state.deathReason = PlayerState.DeathReason.Disconnected; - if (!state.IsDead) state.SetDead(); Utils.AfterPlayerDeathTasks(data.Character, GameStates.IsMeeting, true); + try { state.Role.Remove(id); } + catch (Exception e) { Utils.ThrowException(e); } + NameNotifyManager.Notifies.Remove(id); data.Character.RpcSetName(data.Character.GetRealName(true)); PlayerGameOptionsSender.RemoveSender(data.Character); diff --git a/Roles/Standard/Impostor/Vanilla/PhantomEHR.cs b/Roles/Standard/Impostor/Vanilla/PhantomEHR.cs index 44125b1af..0a7dc607b 100644 --- a/Roles/Standard/Impostor/Vanilla/PhantomEHR.cs +++ b/Roles/Standard/Impostor/Vanilla/PhantomEHR.cs @@ -1,6 +1,4 @@ -using AmongUs.GameOptions; - -namespace EHR.Roles; +namespace EHR.Roles; public class PhantomEHR : RoleBase { @@ -28,7 +26,7 @@ public class PhantomEHR : RoleBase if (ReportDeadBodyPatch.MeetingStarted || GameStates.IsMeeting) return; pc.RpcMakeVisible(phantom: true); pc.RpcResetAbilityCooldown(); - }, Main.RealOptionsData.GetFloat(FloatOptionNames.PhantomDuration), "PhantomEHR Appear"); + }, ImpostorVanillaRoles.PhantomDuration.GetFloat(), "PhantomEHR Appear"); return false; } diff --git a/Roles/Standard/Neutral/Pariah/Magistrate.cs b/Roles/Standard/Neutral/Pariah/Magistrate.cs index c725251aa..7e97f7766 100644 --- a/Roles/Standard/Neutral/Pariah/Magistrate.cs +++ b/Roles/Standard/Neutral/Pariah/Magistrate.cs @@ -1,5 +1,6 @@ using AmongUs.GameOptions; using EHR.Modules; +using UnityEngine; namespace EHR.Roles; @@ -36,10 +37,28 @@ public class Magistrate : RoleBase AbilityTrigger = Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool() ? AbilityTriggers.Vanish : Options.UsePets.GetBool() ? AbilityTriggers.Pet : AbilityTriggers.Vent; } + public override void Remove(byte playerId) + { + Main.Instance.StartCoroutine(Coroutine()); + return; + + System.Collections.IEnumerator Coroutine() + { + while (GameStates.IsMeeting || ExileController.Instance || AntiBlackout.SkipTasks) yield return new WaitForSeconds(5f); + yield return new WaitForSeconds(1f); + while (GameStates.IsMeeting || ExileController.Instance || AntiBlackout.SkipTasks) yield return new WaitForSeconds(2f); + if (GameStates.IsEnded || !GameStates.InGame) yield break; + AfterMeetingTasks(); + } + } + public override void AfterMeetingTasks() { - CallCourtNextMeeting = false; - Main.EnumeratePlayerControls().Do(x => Camouflage.RpcSetSkin(x, notCommsOrCamo: true)); + if (CallCourtNextMeeting) + { + CallCourtNextMeeting = false; + Main.EnumeratePlayerControls().Do(x => Camouflage.RpcSetSkin(x, notCommsOrCamo: true)); + } } public override void ApplyGameOptions(IGameOptions opt, byte playerId)