diff --git a/Modules/AntiBlackout.cs b/Modules/AntiBlackout.cs index 9996919f9..aaae3a0c6 100644 --- a/Modules/AntiBlackout.cs +++ b/Modules/AntiBlackout.cs @@ -113,7 +113,10 @@ public static class AntiBlackout pc.RpcResetAbilityCooldown(); if (Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out float kcd)) - pc.SetKillCooldown(kcd - elapsedSeconds); + { + float time = kcd - elapsedSeconds; + if (time > 0) pc.SetKillCooldown(time); + } else pc.SetKillCooldown(); } diff --git a/Modules/FixedUpdateCaller.cs b/Modules/FixedUpdateCaller.cs index 5104b439c..35e5f1d9c 100644 --- a/Modules/FixedUpdateCaller.cs +++ b/Modules/FixedUpdateCaller.cs @@ -57,6 +57,13 @@ public static class FixedUpdateCaller } } +#if ANDROID + GameStartManager gameStartManager = GameStartManager.Instance; + + if (gameStartManager) + GameStartManagerPatch.GameStartManagerUpdatePatch.Postfix_ManualCall(gameStartManager); +#endif + HudManager hudManager = FastDestroyableSingleton.Instance; if (hudManager) diff --git a/Modules/GuessManager.cs b/Modules/GuessManager.cs index ab4d3cf5b..1876bd1c7 100644 --- a/Modules/GuessManager.cs +++ b/Modules/GuessManager.cs @@ -66,7 +66,7 @@ public static class GuessManager string originMsg = msg; if (!AmongUsClient.Instance.AmHost) return false; - if (!GameStates.IsMeeting || pc == null) return false; + if (!GameStates.IsMeeting || MeetingHud.Instance.state is MeetingHud.VoteStates.Results or MeetingHud.VoteStates.Proceeding || pc == null) return false; bool hasGuessingRole = pc.GetCustomRole() is CustomRoles.NiceGuesser or CustomRoles.EvilGuesser or CustomRoles.Doomsayer or CustomRoles.Judge or CustomRoles.NiceSwapper or CustomRoles.Councillor or CustomRoles.NecroGuesser or CustomRoles.Augur; if (!hasGuessingRole && !pc.Is(CustomRoles.Guesser) && !Options.GuesserMode.GetBool()) return false; diff --git a/Modules/LateTask.cs b/Modules/LateTask.cs index c256e68f9..7ba6c61e3 100644 --- a/Modules/LateTask.cs +++ b/Modules/LateTask.cs @@ -21,7 +21,7 @@ internal class LateTask LOG = log; CallerData = callerData; Tasks.Add(this); - if (log && name is not "" and not "No Name Task") Logger.Info("\"" + name + "\" is created", "LateTask"); + if (log && name is not "" and not "No Name Task") Logger.Info($"\"{name}\" is created (completes in {time:N2})", "LateTask"); } private bool Run(float deltaTime) diff --git a/Modules/RPC.cs b/Modules/RPC.cs index 4fc9dfd5d..844c7212f 100644 --- a/Modules/RPC.cs +++ b/Modules/RPC.cs @@ -455,34 +455,22 @@ internal static class RPCHandlerPatch { if (AmongUsClient.Instance.AmHost) break; - List listOptions = []; - int startAmount = reader.ReadInt32(); - int lastAmount = reader.ReadInt32(); + int startIndex = reader.ReadPackedInt32(); - int countAllOptions = OptionItem.AllOptions.Count; - - // Add Options - for (int option = startAmount; option < countAllOptions && option <= lastAmount; option++) - listOptions.Add(OptionItem.AllOptions[option]); - - int countOptions = listOptions.Count; - Logger.Msg($"StartAmount: {startAmount} - LastAmount: {lastAmount} ({startAmount}/{lastAmount}) :--: ListOptionsCount: {countOptions} - AllOptions: {countAllOptions} ({countOptions}/{countAllOptions})", "SyncCustomSettings"); - - // Sync Settings - foreach (OptionItem option in listOptions) + for (int i = startIndex; i < OptionItem.AllOptions.Count; ++i) { - try { option.SetValue(reader.ReadPackedInt32()); } - catch { } - - try + if (reader.BytesRemaining == 0) break; + var option = OptionItem.AllOptions[i]; + + if (option.Id == 0) { - if (startAmount == 0 && option.Name == "Preset" && option.CurrentValue != 9) - option.SetValue(9); + option.SetValue(9); + continue; } - catch (Exception e) { Utils.ThrowException(e); } + + option.SetValue(reader.ReadPackedInt32()); } - Main.Instance.StartCoroutine(OptionShower.GetText()); break; } case CustomRPC.SetDeathReason: @@ -1360,7 +1348,6 @@ internal static class RPCHandlerPatch internal static class RPC { - // Credit: https://github.com/music-discussion/TownOfHost-TheOtherRoles/blob/main/Modules/RPC.cs public static void SyncCustomSettingsRPC(int targetId = -1) { if (targetId != -1) @@ -1369,41 +1356,29 @@ internal static class RPC if (client == null || client.Character == null || !Main.PlayerVersion.ContainsKey(client.Character.PlayerId)) return; } - if (!AmongUsClient.Instance.AmHost || PlayerControl.AllPlayerControls.Count <= 1 || (!AmongUsClient.Instance.AmHost && PlayerControl.LocalPlayer == null)) return; + if (!AmongUsClient.Instance.AmHost || PlayerControl.AllPlayerControls.Count <= 1) return; - int amount = OptionItem.AllOptions.Count; - int divideBy = amount / 10; - for (var i = 0; i <= 10; i++) SyncOptionsBetween(i * divideBy, (i + 1) * divideBy, targetId); - } - - private static void SyncOptionsBetween(int startAmount, int lastAmount, int targetId = -1) - { - if (targetId != -1) + Logger.Msg(" Starting from 0", "SyncCustomSettings"); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncCustomSettings, SendOption.Reliable, targetId); + writer.WritePacked(0); + + for (int i = 0; i < OptionItem.AllOptions.Count; ++i) { - ClientData client = Utils.GetClientById(targetId); - if (client == null || client.Character == null || !Main.PlayerVersion.ContainsKey(client.Character.PlayerId)) return; + var option = OptionItem.AllOptions[i]; + + if (writer.Length > 500) + { + Logger.Msg($" Starting from {i}", "SyncCustomSettings"); + AmongUsClient.Instance.FinishRpcImmediately(writer); + writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncCustomSettings, SendOption.Reliable, targetId); + writer.WritePacked(i); + } + + writer.WritePacked(option.GetValue()); } - if (!AmongUsClient.Instance.AmHost || PlayerControl.AllPlayerControls.Count <= 1 || (!AmongUsClient.Instance.AmHost && PlayerControl.LocalPlayer == null)) return; - - int amountAllOptions = OptionItem.AllOptions.Count; - - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncCustomSettings, SendOption.Reliable, targetId); - writer.Write(startAmount); - writer.Write(lastAmount); - - List listOptions = []; - - // Add Options - for (int option = startAmount; option < amountAllOptions && option <= lastAmount; option++) listOptions.Add(OptionItem.AllOptions[option]); - - int countListOptions = listOptions.Count; - Logger.Msg($"StartAmount: {startAmount} - LastAmount: {lastAmount} ({startAmount}/{lastAmount}) :--: ListOptionsCount: {countListOptions} - AllOptions: {amountAllOptions} ({countListOptions}/{amountAllOptions})", "SyncCustomSettings"); - - // Sync Settings - foreach (OptionItem option in listOptions) writer.WritePacked(option.GetValue()); - AmongUsClient.Instance.FinishRpcImmediately(writer); + Logger.Msg(" Finished", "SyncCustomSettings"); } public static void PlaySoundRPC(byte playerID, Sounds sound) diff --git a/Patches/GameStartManagerPatch.cs b/Patches/GameStartManagerPatch.cs index 0789fc163..74ff43f2e 100644 --- a/Patches/GameStartManagerPatch.cs +++ b/Patches/GameStartManagerPatch.cs @@ -17,16 +17,6 @@ using static EHR.Translator; namespace EHR; -[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Update))] -public static class GameStartManagerUpdatePatch -{ - public static void Prefix(GameStartManager __instance) - { - try { __instance.MinPlayers = 1; } - catch (Exception ex) { Logger.Error(ex.ToString(), "Surely this can't be causing an issue, right?"); } - } -} - [HarmonyPatch] public static class GameStartManagerPatch { @@ -140,22 +130,20 @@ public static class GameStartManagerPatch private static SpriteRenderer LobbyTimerBg; public static bool Warned; +#if !ANDROID public static bool Prefix(GameStartManager __instance) { try { + try { __instance.MinPlayers = 1; } + catch (Exception ex) { Logger.Error(ex.ToString(), "Surely this can't be causing an issue, right?"); } + if (AmongUsClient.Instance == null) return false; if (AmongUsClient.Instance.AmHost) VanillaUpdate(__instance); if (AmongUsClient.Instance.IsGameStarted || GameStates.IsInGame || __instance == null || __instance.startState == GameStartManager.StartingStates.Starting) return false; - MinWait = Options.MinWaitAutoStart.GetFloat(); - MaxWait = Options.MaxWaitAutoStart.GetFloat(); - MinPlayer = Options.PlayerAutoStart.GetInt(); - MinWait = 600f - (MinWait * 60f); - MaxWait *= 60f; - // Lobby code if (DataManager.Settings != null && DataManager.Settings.Gameplay != null) { @@ -173,72 +161,84 @@ public static class GameStartManagerPatch if (AmongUsClient.Instance == null || GameData.Instance == null || !AmongUsClient.Instance.AmHost || !GameData.Instance) return true; - bool votedToStart = (int)Math.Round(ChatCommands.VotedToStart.Count / (float)PlayerControl.AllPlayerControls.Count * 100f) > 50; - - if ((Main.AutoStart != null && Main.AutoStart.Value) || votedToStart) - { - Main.UpdateTime++; - - if (Main.UpdateTime >= 50) - { - Main.UpdateTime = 0; - - float timer = Timer; - - if (((GameData.Instance?.PlayerCount >= MinPlayer && timer <= MinWait) || timer <= MaxWait || votedToStart) && !GameStates.IsCountDown) - { - PlayerControl[] invalidColor = Main.AllPlayerControls.Where(p => p.Data.DefaultOutfit.ColorId < 0 || Palette.PlayerColors.Length <= p.Data.DefaultOutfit.ColorId).ToArray(); - - if (invalidColor.Length > 0) - { - Main.AllPlayerControls - .Where(p => p.Data.DefaultOutfit.ColorId < 0 || Palette.PlayerColors.Length <= p.Data.DefaultOutfit.ColorId) - .Do(p => AmongUsClient.Instance.KickPlayer(p.OwnerId, false)); - - Logger.SendInGame(GetString("Error.InvalidColorPreventStart"), Color.yellow); - string msg = GetString("Error.InvalidColor"); - msg += "\n" + string.Join(",", invalidColor.Select(p => $"{p.GetRealName()}")); - Utils.SendMessage(msg, sendOption: SendOption.None); - } - - if (Options.RandomMapsMode.GetBool()) - { - Main.NormalOptions.MapId = GameStartRandomMap.SelectRandomMap(); - CreateOptionsPickerPatch.SetDleks = Main.CurrentMap == MapNames.Dleks; - } - else if (CreateOptionsPickerPatch.SetDleks) Main.NormalOptions.MapId = 3; - else if (CreateOptionsPickerPatch.SetSubmerged) Main.NormalOptions.MapId = 6; - - if (Main.CurrentMap == MapNames.Dleks || Main.NormalOptions.MapId == 6) - { - var opt = Main.NormalOptions.CastFast(); - - Options.DefaultKillCooldown = Main.NormalOptions.KillCooldown; - Main.LastKillCooldown.Value = Main.NormalOptions.KillCooldown; - Main.NormalOptions.KillCooldown = 0f; - AURoleOptions.SetOpt(opt); - Main.LastShapeshifterCooldown.Value = AURoleOptions.ShapeshifterCooldown; - AURoleOptions.ShapeshifterCooldown = 0f; - AURoleOptions.ImpostorsCanSeeProtect = false; - - GameManager.Instance.LogicOptions.SetDirty(); - OptionItem.SyncAllOptions(); - } - - RPC.RpcVersionCheck(); - - GameStartManager.Instance.startState = GameStartManager.StartingStates.Countdown; - GameStartManager.Instance.countDownTimer = Options.AutoStartTimer.GetInt(); - __instance?.StartButton.gameObject.SetActive(false); - } - } - } + CheckAutoStart(__instance); } catch (NullReferenceException) { } catch (Exception ex) { Logger.Error(ex.ToString(), "GameStartManagerUpdatePatch.Prefix (2)"); } return false; } +#endif + + private static void CheckAutoStart(GameStartManager __instance) + { + MinWait = Options.MinWaitAutoStart.GetFloat(); + MaxWait = Options.MaxWaitAutoStart.GetFloat(); + MinPlayer = Options.PlayerAutoStart.GetInt(); + MinWait = 600f - (MinWait * 60f); + MaxWait *= 60f; + + bool votedToStart = (int)Math.Round(ChatCommands.VotedToStart.Count / (float)PlayerControl.AllPlayerControls.Count * 100f) > 50; + + if ((Main.AutoStart != null && Main.AutoStart.Value) || votedToStart) + { + Main.UpdateTime++; + + if (Main.UpdateTime >= 50) + { + Main.UpdateTime = 0; + + float timer = Timer; + + if (((GameData.Instance?.PlayerCount >= MinPlayer && timer <= MinWait) || timer <= MaxWait || votedToStart) && !GameStates.IsCountDown) + { + PlayerControl[] invalidColor = Main.AllPlayerControls.Where(p => p.Data.DefaultOutfit.ColorId < 0 || Palette.PlayerColors.Length <= p.Data.DefaultOutfit.ColorId).ToArray(); + + if (invalidColor.Length > 0) + { + Main.AllPlayerControls + .Where(p => p.Data.DefaultOutfit.ColorId < 0 || Palette.PlayerColors.Length <= p.Data.DefaultOutfit.ColorId) + .Do(p => AmongUsClient.Instance.KickPlayer(p.OwnerId, false)); + + Logger.SendInGame(GetString("Error.InvalidColorPreventStart"), Color.yellow); + string msg = GetString("Error.InvalidColor"); + msg += "\n" + string.Join(",", invalidColor.Select(p => $"{p.GetRealName()}")); + Utils.SendMessage(msg, sendOption: SendOption.None); + } + + if (Options.RandomMapsMode.GetBool()) + { + Main.NormalOptions.MapId = GameStartRandomMap.SelectRandomMap(); + CreateOptionsPickerPatch.SetDleks = Main.CurrentMap == MapNames.Dleks; + } + else if (CreateOptionsPickerPatch.SetDleks) Main.NormalOptions.MapId = 3; + else if (CreateOptionsPickerPatch.SetSubmerged) Main.NormalOptions.MapId = 6; + + if (Main.CurrentMap == MapNames.Dleks || Main.NormalOptions.MapId == 6) + { + var opt = Main.NormalOptions.CastFast(); + + Options.DefaultKillCooldown = Main.NormalOptions.KillCooldown; + Main.LastKillCooldown.Value = Main.NormalOptions.KillCooldown; + Main.NormalOptions.KillCooldown = 0f; + AURoleOptions.SetOpt(opt); + Main.LastShapeshifterCooldown.Value = AURoleOptions.ShapeshifterCooldown; + AURoleOptions.ShapeshifterCooldown = 0f; + AURoleOptions.ImpostorsCanSeeProtect = false; + + GameManager.Instance.LogicOptions.SetDirty(); + OptionItem.SyncAllOptions(); + } + + RPC.RpcVersionCheck(); + + GameStartManager.Instance.startState = GameStartManager.StartingStates.Countdown; + GameStartManager.Instance.countDownTimer = Options.AutoStartTimer.GetInt(); + __instance?.StartButton.gameObject.SetActive(false); + } + } + } + } private static void VanillaUpdate(GameStartManager instance) { @@ -329,7 +329,14 @@ public static class GameStartManagerPatch instance.LobbyInfoPane.gameObject.SetActive(!FastDestroyableSingleton.Instance.Chat.IsOpenOrOpening); } +#if !ANDROID public static void Postfix(GameStartManager __instance) + { + Postfix_ManualCall(__instance); + } +#endif + + public static void Postfix_ManualCall(GameStartManager __instance) { try { @@ -385,6 +392,14 @@ public static class GameStartManagerPatch } } +#if ANDROID + try + { + if (canStartGame) CheckAutoStart(__instance); + } + catch (Exception e) { Utils.ThrowException(e); } +#endif + if (warningMessage == "") WarningText.gameObject.SetActive(false); else diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index 5a2d94f03..744fddfef 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -1603,6 +1603,10 @@ internal static class FixedUpdatePatch player.Notify(GetString("PlagueBearerToPestilence")); player.RpcGuardAndKill(player); + var state = Main.PlayerStates[player.PlayerId]; + state.RemoveSubRole(CustomRoles.Fragile); + state.RemoveSubRole(CustomRoles.Unbound); + if (!PlagueBearer.PestilenceList.Contains(playerId)) PlagueBearer.PestilenceList.Add(playerId); diff --git a/Roles/Crewmate/Medic.cs b/Roles/Crewmate/Medic.cs index 1c73314d5..eb8036948 100644 --- a/Roles/Crewmate/Medic.cs +++ b/Roles/Crewmate/Medic.cs @@ -221,15 +221,19 @@ public class Medic : RoleBase killer.SetKillCooldown(ResetCooldown.GetFloat()); Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer); + var medics = Main.AllPlayerControls.Where(x => PlayerIdList.Contains(x.PlayerId) && x.IsAlive()).ToArray(); + switch (KnowShieldBroken.GetInt()) { case 0: target.RpcGuardAndKill(); - Main.AllPlayerControls.Where(x => PlayerIdList.Contains(x.PlayerId) && x.IsAlive()).NotifyPlayers(Translator.GetString("MedicKillerTryBrokenShieldTargetForMedic")); + medics.Do(x => x.KillFlash()); + medics.NotifyPlayers(Translator.GetString("MedicKillerTryBrokenShieldTargetForMedic")); Main.AllPlayerControls.Where(x => ProtectList.Contains(x.PlayerId)).NotifyPlayers(Translator.GetString("MedicKillerTryBrokenShieldTargetForTarget")); break; case 1: - Main.AllPlayerControls.Where(x => PlayerIdList.Contains(x.PlayerId) && x.IsAlive()).NotifyPlayers(Translator.GetString("MedicKillerTryBrokenShieldTargetForMedic")); + medics.Do(x => x.KillFlash()); + medics.NotifyPlayers(Translator.GetString("MedicKillerTryBrokenShieldTargetForMedic")); break; case 2: target.RpcGuardAndKill(); diff --git a/Roles/Crewmate/Retributionist.cs b/Roles/Crewmate/Retributionist.cs index 9430bfc95..abeede16c 100644 --- a/Roles/Crewmate/Retributionist.cs +++ b/Roles/Crewmate/Retributionist.cs @@ -49,7 +49,7 @@ public class Retributionist : RoleBase public override void SetKillCooldown(byte id) { - Main.AllPlayerKillCooldown[id] = 5f; + Main.AllPlayerKillCooldown[id] = 1f; } public override void AfterMeetingTasks()