diff --git a/GameMode/Quiz.cs b/GameMode/Quiz.cs index 39f8acd2b..e392d71c4 100644 --- a/GameMode/Quiz.cs +++ b/GameMode/Quiz.cs @@ -192,6 +192,9 @@ public static class Quiz string correctRoom = GetString(UsedRooms[Main.CurrentMap][correctAnswerLetter].ToString()); string color = wasWrong ? "#FF0000" : "#00FF00"; string str = string.Format(GetString("Quiz.Notify.CorrectAnswer"), color, correctAnswerLetter, correctAnswer, correctRoom); + + int numPlayers = Main.AllAlivePlayerControls.Length; + if (DyingPlayers.Count == numPlayers) str += "\n" + GetString("Quiz.Notify.AllWrong"); if (CurrentDifficulty > Difficulty.Test && Settings[CurrentDifficulty].QuestionsAsked.GetInt() <= QuestionsAsked) { @@ -204,7 +207,7 @@ public static class Quiz str += "\n" + NumCorrectAnswers.Count(x => x.Value[CurrentDifficulty][Round] < requiredCorrect) switch { 0 => GetString("Quiz.Notify.AllCorrect"), - var x when x == Main.AllAlivePlayerControls.Length => GetString("Quiz.Notify.AllDie"), + var x when x == numPlayers => GetString("Quiz.Notify.AllDie"), 1 => failed ? GetString("Quiz.Notify.OnlyYouWrong") : GetString("Quiz.Notify.OneWrong"), _ => failed ? GetString("Quiz.Notify.IncorrectFFA") : GetString("Quiz.Notify.CorrectFFA") }; @@ -233,8 +236,16 @@ public static class Quiz AllowKills = false; NoSuffix = true; - Dictionary sample = Enum.GetValues()[1..].ToDictionary(x => x, x => Enumerable.Repeat(0, Settings[x].Rounds.GetInt()).ToArray()); - NumCorrectAnswers = Main.PlayerStates.Keys.ToDictionary(x => x, _ => sample); + foreach (PlayerControl pc in Main.AllPlayerControls) + { + NumCorrectAnswers[pc.PlayerId] = new Dictionary + { + [Difficulty.Test] = new int[1], + [Difficulty.Easy] = new int[Settings[Difficulty.Easy].Rounds.GetInt()], + [Difficulty.Medium] = new int[Settings[Difficulty.Medium].Rounds.GetInt()], + [Difficulty.Hard] = new int[100] // Surely there won't be more than 100 hard rounds, right? + }; + } } public static IEnumerator OnGameStart() @@ -300,8 +311,6 @@ public static class Quiz if (newRound) { - if (CurrentDifficulty == Difficulty.Hard) NumCorrectAnswers.Values.Do(x => x[Difficulty.Hard][Round + 1] = 0); - NoSuffix = true; Main.AllAlivePlayerControls.NotifyPlayers(string.Format(GetString("Quiz.Notify.NextRound"), Round + 1)); yield return new WaitForSeconds(3f); @@ -361,17 +370,13 @@ public static class Quiz PlayerControl[] aapc = Main.AllAlivePlayerControls; SystemTypes correctRoom = UsedRooms[Main.CurrentMap][(char)('A' + CurrentQuestion.CorrectAnswerIndex)]; DyingPlayers = aapc.Select(x => (ID: x.PlayerId, Room: x.GetPlainShipRoom())).Where(x => correctRoom == SystemTypes.Outside ? x.Room != null : x.Room == null || x.Room.RoomId != correctRoom).Select(x => x.ID).ToList(); - NumCorrectAnswers.ExceptBy(DyingPlayers, x => x.Key).Do(x => x.Value[CurrentDifficulty][Round]++); bool everyoneWasWrong = DyingPlayers.Count == aapc.Length; - Logger.Info($"Players who got the question wrong: {string.Join(", ", DyingPlayers.Select(x => Main.AllPlayerNames[x]))}", "Quiz"); + if (!everyoneWasWrong) NumCorrectAnswers.DoIf(x => !DyingPlayers.Contains(x.Key), x => x.Value[CurrentDifficulty][Round]++); + Logger.Info($"{(everyoneWasWrong ? "Everyone" : "Players who")} got the question wrong: {string.Join(", ", DyingPlayers.Select(x => Main.AllPlayerNames.GetValueOrDefault(x, $"Someone (ID {x})")))}", "Quiz"); + Logger.Info($"Number of correct answers for everyone currently: {string.Join(", ", NumCorrectAnswers.Select(x => $"{Main.AllPlayerNames.GetValueOrDefault(x.Key, string.Empty)}: {x.Value[CurrentDifficulty][Round]}"))}", "Quiz"); - if (everyoneWasWrong) - { - aapc.NotifyPlayers(GetString("Quiz.Notify.AllWrong")); - QuestionsAsked--; - } - else - Utils.NotifyRoles(); + if (everyoneWasWrong) QuestionsAsked--; + else Utils.NotifyRoles(); yield return new WaitForSeconds(everyoneWasWrong ? 11f : 7f); if (GameStates.IsMeeting || ExileController.Instance || !GameStates.InGame || GameStates.IsLobby) yield break; diff --git a/Modules/EAC.cs b/Modules/EAC.cs index 328431097..0dfc56259 100644 --- a/Modules/EAC.cs +++ b/Modules/EAC.cs @@ -502,16 +502,13 @@ internal static class EAC Utils.SendMessage(string.Format(GetString("Message.NoticeByEAC"), pc?.Data?.PlayerName, text), PlayerControl.LocalPlayer.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("MessageFromEAC"))); break; case 3: - foreach (PlayerControl player in Main.AllPlayerControls) - { - if (player.PlayerId != pc?.Data?.PlayerId) - { - string message = string.Format(GetString("Message.NoticeByEAC"), pc?.Data?.PlayerName, text); - string title = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("MessageFromEAC")); - Utils.SendMessage(message, player.PlayerId, title); - } - } - + ( + from player in Main.AllPlayerControls + where player.PlayerId != pc?.Data?.PlayerId + let message = string.Format(GetString("Message.NoticeByEAC"), pc?.Data?.PlayerName, text) + let title = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("MessageFromEAC")) + select new Message(message, player.PlayerId, title) + ).SendMultipleMessages(SendOption.None); break; case 4: string hashedPuid = pc.GetClient().GetHashedPuid(); diff --git a/Modules/SpamManager.cs b/Modules/SpamManager.cs index 3fef0aee6..3a981bbc7 100644 --- a/Modules/SpamManager.cs +++ b/Modules/SpamManager.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text; +using Hazel; using static EHR.Translator; namespace EHR; @@ -103,7 +104,7 @@ public static class SpamManager kick = true; } - if (msg != string.Empty && msg != "") Utils.SendMessage(msg); + if (msg != string.Empty && msg != "") Utils.SendMessage(msg, sendOption: SendOption.None); if (kick) AmongUsClient.Instance.KickPlayer(player.GetClientId(), Options.AutoKickStartAsBan.GetBool()); @@ -134,11 +135,11 @@ public static class SpamManager if (msg != string.Empty && msg != "") { if (kick || !GameStates.IsInGame) - Utils.SendMessage(msg); + Utils.SendMessage(msg, sendOption: SendOption.None); else { foreach (PlayerControl pc in Main.AllPlayerControls.Where(x => x.IsAlive() == player.IsAlive()).ToArray()) - Utils.SendMessage(msg, pc.PlayerId); + Utils.SendMessage(msg, pc.PlayerId, sendOption: SendOption.None); } } diff --git a/Modules/TemplateManager.cs b/Modules/TemplateManager.cs index eb9c40f4b..5958de8da 100644 --- a/Modules/TemplateManager.cs +++ b/Modules/TemplateManager.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.RegularExpressions; using AmongUs.Data; using HarmonyLib; +using Hazel; using InnerNet; using UnityEngine; using static EHR.Translator; @@ -120,12 +121,16 @@ public static class TemplateManager if (playerId == 0xff) HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, string.Format(GetString("Message.TemplateNotFoundHost"), str, tags.Join(delimiter: ", "))); else - Utils.SendMessage(string.Format(GetString("Message.TemplateNotFoundClient"), str), playerId); + Utils.SendMessage(string.Format(GetString("Message.TemplateNotFoundClient"), str), playerId, sendOption: SendOption.None); } else { + List messages = []; + foreach (string x in sendList) - Utils.SendMessage(ApplyReplaceDictionary(x), playerId); + messages.Add(new Message(ApplyReplaceDictionary(x), playerId)); + + messages.SendMultipleMessages(); } } diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 40b175fca..8517441ef 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -1133,26 +1133,36 @@ public static class Utils public static void ShowActiveSettingsHelp(byte PlayerId = byte.MaxValue) { - var sender = CustomRpcSender.Create("ShowActiveSettingsHelp", SendOption.Reliable); + // var sender = CustomRpcSender.Create("ShowActiveSettingsHelp", SendOption.Reliable); + // + // SendMessage(GetString("CurrentActiveSettingsHelp") + ":", PlayerId, writer: sender, multiple: true); + // + // if (Options.DisableDevices.GetBool()) SendMessage(GetString("DisableDevicesInfo"), PlayerId, writer: sender, multiple: true); + // if (Options.SyncButtonMode.GetBool()) SendMessage(GetString("SyncButtonModeInfo"), PlayerId, writer: sender, multiple: true); + // if (Options.SabotageTimeControl.GetBool()) SendMessage(GetString("SabotageTimeControlInfo"), PlayerId, writer: sender, multiple: true); + // if (Options.RandomMapsMode.GetBool()) SendMessage(GetString("RandomMapsModeInfo"), PlayerId, writer: sender, multiple: true); + // + // if (Main.GM.Value) SendMessage(GetRoleName(CustomRoles.GM) + GetString("GMInfoLong"), PlayerId, writer: sender, multiple: true); + // + // foreach (CustomRoles role in Enum.GetValues()) + // { + // if (role.IsEnable() && !role.IsVanilla()) + // SendMessage(GetRoleName(role) + GetRoleMode(role) + GetString($"{role}InfoLong"), PlayerId, writer: sender, multiple: true); + // } + // + // if (Options.NoGameEnd.GetBool()) SendMessage(GetString("NoGameEndInfo"), PlayerId, writer: sender, multiple: true); + // + // sender.SendMessage(dispose: sender.stream.Length <= 3); - SendMessage(GetString("CurrentActiveSettingsHelp") + ":", PlayerId, writer: sender, multiple: true); - - if (Options.DisableDevices.GetBool()) SendMessage(GetString("DisableDevicesInfo"), PlayerId, writer: sender, multiple: true); - if (Options.SyncButtonMode.GetBool()) SendMessage(GetString("SyncButtonModeInfo"), PlayerId, writer: sender, multiple: true); - if (Options.SabotageTimeControl.GetBool()) SendMessage(GetString("SabotageTimeControlInfo"), PlayerId, writer: sender, multiple: true); - if (Options.RandomMapsMode.GetBool()) SendMessage(GetString("RandomMapsModeInfo"), PlayerId, writer: sender, multiple: true); - - if (Main.GM.Value) SendMessage(GetRoleName(CustomRoles.GM) + GetString("GMInfoLong"), PlayerId, writer: sender, multiple: true); - - foreach (CustomRoles role in Enum.GetValues()) - { - if (role.IsEnable() && !role.IsVanilla()) - SendMessage(GetRoleName(role) + GetRoleMode(role) + GetString($"{role}InfoLong"), PlayerId, writer: sender, multiple: true); - } - - if (Options.NoGameEnd.GetBool()) SendMessage(GetString("NoGameEndInfo"), PlayerId, writer: sender, multiple: true); - - sender.SendMessage(dispose: sender.stream.Length <= 3); + List messages = [new(GetString("CurrentActiveSettingsHelp") + ":", PlayerId)]; + if (Options.DisableDevices.GetBool()) messages.Add(new(GetString("DisableDevicesInfo"), PlayerId)); + if (Options.SyncButtonMode.GetBool()) messages.Add(new(GetString("SyncButtonModeInfo"), PlayerId)); + if (Options.SabotageTimeControl.GetBool()) messages.Add(new(GetString("SabotageTimeControlInfo"), PlayerId)); + if (Options.RandomMapsMode.GetBool()) messages.Add(new(GetString("RandomMapsModeInfo"), PlayerId)); + if (Main.GM.Value) messages.Add(new(GetRoleName(CustomRoles.GM) + GetString("GMInfoLong"), PlayerId)); + messages.AddRange(from role in Enum.GetValues() where role.IsEnable() && !role.IsVanilla() select new Message(GetRoleName(role) + GetRoleMode(role) + GetString($"{role}InfoLong"), PlayerId)); + if (Options.NoGameEnd.GetBool()) messages.Add(new(GetString("NoGameEndInfo"), PlayerId)); + messages.SendMultipleMessages(); } /// @@ -1170,13 +1180,13 @@ public static class Utils { if (Options.HideGameSettings.GetBool() && PlayerId != byte.MaxValue) { - SendMessage(GetString("Message.HideGameSettings"), PlayerId); + SendMessage(GetString("Message.HideGameSettings"), PlayerId, sendOption: SendOption.None); return; } if (Options.DIYGameSettings.GetBool()) { - SendMessage(GetString("Message.NowOverrideText"), PlayerId); + SendMessage(GetString("Message.NowOverrideText"), PlayerId, sendOption: SendOption.None); return; } @@ -1200,13 +1210,13 @@ public static class Utils { if (Options.HideGameSettings.GetBool() && PlayerId != byte.MaxValue) { - SendMessage(GetString("Message.HideGameSettings"), PlayerId); + SendMessage(GetString("Message.HideGameSettings"), PlayerId, sendOption: SendOption.None); return; } if (Options.DIYGameSettings.GetBool()) { - SendMessage(GetString("Message.NowOverrideText"), PlayerId); + SendMessage(GetString("Message.NowOverrideText"), PlayerId, sendOption: SendOption.None); return; } @@ -1302,7 +1312,7 @@ public static class Utils { if (Options.HideGameSettings.GetBool() && PlayerId != byte.MaxValue) { - SendMessage(GetString("Message.HideGameSettings"), PlayerId); + SendMessage(GetString("Message.HideGameSettings"), PlayerId, sendOption: SendOption.None); return; } @@ -1343,15 +1353,15 @@ public static class Utils } } - var sender = CustomRpcSender.Create("ShowActiveRoles", SendOption.Reliable); - SendMessage($"{sb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("GMRoles"), writer: sender, multiple: true); - SendMessage($"{impsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, ColorString(GetRoleColor(CustomRoles.Impostor), GetString("ImpostorRoles")), writer: sender, multiple: true); - SendMessage($"{crewsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, ColorString(GetRoleColor(CustomRoles.Crewmate), GetString("CrewmateRoles")), writer: sender, multiple: true); - SendMessage($"{neutralsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("NeutralRoles"), writer: sender, multiple: true); - SendMessage($"{covensb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("CovenRoles"), writer: sender, multiple: true); - SendMessage($"{ghostsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("GhostRoles"), writer: sender, multiple: true); - SendMessage($"{addonsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("AddonRoles"), writer: sender, multiple: true); - sender.SendMessage(dispose: sender.stream.Length <= 3); + new List { + new($"{sb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("GMRoles")), + new($"{impsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, ColorString(GetRoleColor(CustomRoles.Impostor), GetString("ImpostorRoles"))), + new($"{crewsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, ColorString(GetRoleColor(CustomRoles.Crewmate), GetString("CrewmateRoles"))), + new($"{neutralsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("NeutralRoles")), + new($"{covensb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("CovenRoles")), + new($"{ghostsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("GhostRoles")), + new($"{addonsb.Append("\n.").ToString().RemoveHtmlTags()}", PlayerId, GetString("AddonRoles")) + }.SendMultipleMessages(); } public static void ShowChildrenSettings(OptionItem option, ref StringBuilder sb, int deep = 0, bool f1 = false, bool disableColor = true) @@ -1387,7 +1397,7 @@ public static class Utils { if (AmongUsClient.Instance.IsGameStarted) { - SendMessage(GetString("CantUse.lastroles"), playerId); + SendMessage(GetString("CantUse.lastroles"), playerId, sendOption: SendOption.None); return; } @@ -1494,7 +1504,7 @@ public static class Utils { if (GameStates.IsInGame) { - SendMessage(GetString("CantUse.killlog"), playerId); + SendMessage(GetString("CantUse.killlog"), playerId, sendOption: SendOption.None); return; } @@ -1505,7 +1515,7 @@ public static class Utils { if (GameStates.IsInGame) { - SendMessage(GetString("CantUse.lastresult"), playerId); + SendMessage(GetString("CantUse.lastresult"), playerId, sendOption: SendOption.None); return; } @@ -1519,12 +1529,7 @@ public static class Utils public static void ShowLastAddOns(byte playerId = byte.MaxValue) { - if (GameStates.IsInGame) - { - SendMessage(GetString("CantUse.lastresult"), playerId); - return; - } - + if (GameStates.IsInGame) return; if (!CustomGameMode.Standard.IsActiveOrIntegrated()) return; string result = Main.LastAddOns.Values.Join(delimiter: "\n"); @@ -1705,7 +1710,14 @@ public static class Utils catch (Exception e) { ThrowException(e); } } - public static void SendMessage(string text, byte sendTo = byte.MaxValue, string title = "", bool noSplit = false, CustomRpcSender writer = null, bool final = false, bool multiple = false) + public static void SendMultipleMessages(this IEnumerable messages, SendOption sendOption = SendOption.Reliable) + { + var sender = CustomRpcSender.Create("Utils.SendMultipleMessages", sendOption); + messages.Do(x => SendMessage(x.Text, x.SendTo, x.Title, writer: sender, multiple: true, sendOption: sendOption)); + sender.SendMessage(dispose: sender.stream.Length <= 3); + } + + public static void SendMessage(string text, byte sendTo = byte.MaxValue, string title = "", bool noSplit = false, CustomRpcSender writer = null, bool final = false, bool multiple = false, SendOption sendOption = SendOption.Reliable) { PlayerControl receiver = GetPlayerById(sendTo, false); if (sendTo != byte.MaxValue && receiver == null) return; @@ -1753,7 +1765,7 @@ public static class Utils if (sendTo != byte.MaxValue) { - writer ??= CustomRpcSender.Create("Utils.SendMessage", SendOption.Reliable); + writer ??= CustomRpcSender.Create("Utils.SendMessage", sendOption); if (writer.CurrentState == CustomRpcSender.State.Ready) writer.StartMessage(receiver.GetClientId()); if (!noSplit) @@ -1781,9 +1793,9 @@ public static class Utils } if (shortenedText.Length >= sizeLimit) - shortenedText.Chunk(sizeLimit).Do(x => SendMessage(new(x), sendTo, title, true, writer)); + shortenedText.Chunk(sizeLimit).Do(x => SendMessage(new(x), sendTo, title, true, writer, sendOption: sendOption)); else - SendMessage(shortenedText, sendTo, title, true, writer); + SendMessage(shortenedText, sendTo, title, true, writer, sendOption: sendOption); string sentText = shortenedText; shortenedText = line + "\n"; @@ -1795,7 +1807,7 @@ public static class Utils } } - if (shortenedText.Length > 0) SendMessage(shortenedText, sendTo, title, true, writer, true); + if (shortenedText.Length > 0) SendMessage(shortenedText, sendTo, title, true, writer, true, sendOption: sendOption); else if (writer != null && sendTo != byte.MaxValue && writer.CurrentState == CustomRpcSender.State.InRootMessage) { writer.StartRpc(sender.NetId, (byte)RpcCalls.SetName) @@ -1853,7 +1865,7 @@ public static class Utils if (writer.stream.Length > 800) { writer.SendMessage(); - writer = CustomRpcSender.Create("Utils.SendMessage", SendOption.Reliable); + writer = CustomRpcSender.Create("Utils.SendMessage", sendOption); writer.StartMessage(receiver.GetClientId()); } } @@ -3058,14 +3070,11 @@ public static class Utils case CustomRoles.CyberStar when !disconnect: if (onMeeting) { - foreach (PlayerControl pc in Main.AllPlayerControls) - { - if ((!Options.ImpKnowCyberStarDead.GetBool() && pc.GetCustomRole().IsImpostor()) - || (!Options.NeutralKnowCyberStarDead.GetBool() && pc.GetCustomRole().IsNeutral())) - continue; - - SendMessage(string.Format(GetString("CyberStarDead"), target.GetRealName()), pc.PlayerId, ColorString(GetRoleColor(CustomRoles.CyberStar), GetString("CyberStarNewsTitle"))); - } + ( + from pc in Main.AllPlayerControls + where (Options.ImpKnowCyberStarDead.GetBool() || !pc.GetCustomRole().IsImpostor()) && (Options.NeutralKnowCyberStarDead.GetBool() || !pc.GetCustomRole().IsNeutral()) + select new Message(string.Format(GetString("CyberStarDead"), target.GetRealName()), pc.PlayerId, ColorString(GetRoleColor(CustomRoles.CyberStar), GetString("CyberStarNewsTitle"))) + ).SendMultipleMessages(); } else { @@ -3657,4 +3666,11 @@ public static class Utils float minTime = Mathf.Max(0.02f, AmongUsClient.Instance.Ping / divice * 6f); return minTime; } +} + +public class Message(string text, byte sendTo = byte.MaxValue, string title = "") +{ + public string Text { get; } = text; + public byte SendTo { get; } = sendTo; + public string Title { get; } = title; } \ No newline at end of file diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index 32d006aa2..c26dee19b 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -425,7 +425,7 @@ internal static class ChatCommands { if (Options.Disable8ballCommand.GetBool()) { - Utils.SendMessage("\n", player.PlayerId, GetString("EightBallDisabled")); + Utils.SendMessage("\n", player.PlayerId, GetString("EightBallDisabled"), sendOption: SendOption.None); return; } @@ -484,7 +484,7 @@ internal static class ChatCommands string message = string.Join(' ', args[1..]); if (amJailor) Utils.SendMessage(message, jailor.JailorTarget, title); - else Jailor.PlayerIdList.ForEach(x => Utils.SendMessage(message, x, title)); + else Jailor.PlayerIdList.ForEach(x => Utils.SendMessage(message, x, title, sendOption: SendOption.None)); } private static void RoleListCommand(PlayerControl player, string text, string[] args) @@ -608,7 +608,7 @@ internal static class ChatCommands if (Options.DisableSpectateCommand.GetBool()) { - Utils.SendMessage("\n", player.PlayerId, GetString("SpectateDisabled")); + Utils.SendMessage("\n", player.PlayerId, GetString("SpectateDisabled"), sendOption: SendOption.None); return; } @@ -640,13 +640,13 @@ internal static class ChatCommands if (Options.DisableWhisperCommand.GetBool()) { - Utils.SendMessage("\n", player.PlayerId, GetString("WhisperDisabled")); + Utils.SendMessage("\n", player.PlayerId, GetString("WhisperDisabled"), sendOption: SendOption.None); return; } if (Magistrate.CallCourtNextMeeting) { - Utils.SendMessage("\n", player.PlayerId, GetString("NoWhisperDuringCourt")); + Utils.SendMessage("\n", player.PlayerId, GetString("NoWhisperDuringCourt"), sendOption: SendOption.None); return; } @@ -679,7 +679,7 @@ internal static class ChatCommands if (!NoteKiller.CanGuess) { - Utils.SendMessage(GetString("DeathNoteCommand.CanNotGuess"), player.PlayerId); + Utils.SendMessage(GetString("DeathNoteCommand.CanNotGuess"), player.PlayerId, sendOption: SendOption.None); return; } @@ -713,7 +713,7 @@ internal static class ChatCommands SoundManager.Instance.PlaySound(pc.KillSfx, false, 0.8f); string coloredName = deadPlayer.ColoredPlayerName(); - Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("DeathNoteCommand.Success"), coloredName)); + Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("DeathNoteCommand.Success"), coloredName), sendOption: SendOption.None); Utils.SendMessage(string.Format(GetString("DeathNoteCommand.SuccessForOthers"), coloredName)); NoteKiller.Kills++; @@ -845,12 +845,16 @@ internal static class ChatCommands { for (var index = 0; index < 3; index++) { + List messages = []; + foreach ((byte id, List roles) in DraftRoles) { IEnumerable roleList = roles.Select((x, i) => $"{i + 1}. {x.ToColoredString()}"); string msg = string.Format(GetString(index == 0 ? "DraftStart" : "DraftResend"), string.Join('\n', roleList)); - Utils.SendMessage(msg, id, GetString("DraftTitle")); + messages.Add(new Message(msg, id, GetString("DraftTitle"))); } + + messages.SendMultipleMessages(index == 0 ? SendOption.Reliable : SendOption.None); yield return new WaitForSeconds(20f); if (DraftResult.Count >= DraftRoles.Count || GameStates.InGame) yield break; @@ -911,11 +915,13 @@ internal static class ChatCommands int duration = args.Length < 3 || !int.TryParse(args[2], out int dur) ? 60 : dur; MutedPlayers[id] = (Utils.TimeStamp, duration); - var sender = CustomRpcSender.Create("MuteCommand", SendOption.Reliable); - Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("PlayerMuted"), id.ColoredPlayerName(), duration), writer: sender, multiple: true); - Utils.SendMessage("\n", id, string.Format(GetString("YouMuted"), player.PlayerId.ColoredPlayerName(), duration), writer: sender, multiple: true); - if (!host) Utils.SendMessage("\n", 0, string.Format(GetString("ModeratorMuted"), player.PlayerId.ColoredPlayerName(), id.ColoredPlayerName(), duration), writer: sender, multiple: true); - sender.SendMessage(dispose: sender.stream.Length <= 3); + List messages = + [ + new("\n", player.PlayerId, string.Format(GetString("PlayerMuted"), id.ColoredPlayerName(), duration)), + new("\n", id, string.Format(GetString("YouMuted"), player.PlayerId.ColoredPlayerName(), duration)) + ]; + if (!host) messages.Add(new Message("\n", 0, string.Format(GetString("ModeratorMuted"), player.PlayerId.ColoredPlayerName(), id.ColoredPlayerName(), duration))); + messages.SendMultipleMessages(); } private static void UnmuteCommand(PlayerControl player, string text, string[] args) @@ -1067,7 +1073,8 @@ internal static class ChatCommands IEnumerator SendOnMeeting() { bool meeting = GameStates.IsMeeting; - while (!GameStates.IsMeeting) yield return null; + while (!GameStates.IsMeeting && GameStates.InGame) yield return null; + if (!GameStates.InGame) yield break; if (!meeting) yield return new WaitForSeconds(7f); @@ -1149,7 +1156,7 @@ internal static class ChatCommands if (resendTimer >= 15f) { resendTimer = 0f; - Utils.SendMessage(msg + $"{string.Format(GetString("Poll.TimeInfo"), (int)Math.Round(PollTimer))}", title: title); + Utils.SendMessage(msg + $"{string.Format(GetString("Poll.TimeInfo"), (int)Math.Round(PollTimer))}", title: title, sendOption: SendOption.None); } yield return null; @@ -1201,13 +1208,13 @@ internal static class ChatCommands if (PollVotes.Count == 0) { - Utils.SendMessage(GetString("Poll.Inactive"), player.PlayerId); + Utils.SendMessage(GetString("Poll.Inactive"), player.PlayerId, sendOption: SendOption.None); return; } if (PollVoted.Contains(player.PlayerId)) { - Utils.SendMessage(GetString("Poll.AlreadyVoted"), player.PlayerId); + Utils.SendMessage(GetString("Poll.AlreadyVoted"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1256,7 +1263,7 @@ internal static class ChatCommands if (!GameStates.IsLobby && player.IsAlive()) { - Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId); + Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1264,13 +1271,13 @@ internal static class ChatCommands if (subArgs == "" || !int.TryParse(subArgs, out int guessedNo)) { - Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId); + Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId, sendOption: SendOption.None); return; } if (guessedNo is < 0 or > 99) { - Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId); + Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1436,13 +1443,13 @@ internal static class ChatCommands if (GameStates.IsInGame) { - Utils.SendMessage(GetString("Message.OnlyCanUseInLobby"), player.PlayerId); + Utils.SendMessage(GetString("Message.OnlyCanUseInLobby"), player.PlayerId, sendOption: SendOption.None); return; } if (!player.IsHost() && !Options.PlayerCanSetColor.GetBool() && !IsPlayerVIP(player.FriendCode) && !player.FriendCode.GetDevUser().up) { - Utils.SendMessage(GetString("DisableUseCommand"), player.PlayerId); + Utils.SendMessage(GetString("DisableUseCommand"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1451,12 +1458,12 @@ internal static class ChatCommands if (color == byte.MaxValue) { - Utils.SendMessage(GetString("IllegalColor"), player.PlayerId); + Utils.SendMessage(GetString("IllegalColor"), player.PlayerId, sendOption: SendOption.None); return; } player.RpcSetColor(color); - Utils.SendMessage(string.Format(GetString("Message.SetColor"), subArgs), player.PlayerId); + Utils.SendMessage(string.Format(GetString("Message.SetColor"), subArgs), player.PlayerId, sendOption: SendOption.None); } private static void KillCommand(PlayerControl player, string text, string[] args) @@ -1469,7 +1476,7 @@ internal static class ChatCommands if (GameStates.IsLobby) { - Utils.SendMessage(GetString("Message.CanNotUseInLobby"), player.PlayerId); + Utils.SendMessage(GetString("Message.CanNotUseInLobby"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1498,7 +1505,7 @@ internal static class ChatCommands if (GameStates.IsLobby) { - Utils.SendMessage(GetString("Message.CanNotUseInLobby"), player.PlayerId); + Utils.SendMessage(GetString("Message.CanNotUseInLobby"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1532,14 +1539,14 @@ internal static class ChatCommands // Check if the Kick command is enabled in the settings if (!Options.ApplyModeratorList.GetBool() && !player.IsHost()) { - Utils.SendMessage(GetString("KickCommandDisabled"), player.PlayerId); + Utils.SendMessage(GetString("KickCommandDisabled"), player.PlayerId, sendOption: SendOption.None); return; } // Check if the Player has the necessary privileges to use the command if (!IsPlayerModerator(player.FriendCode) && !player.IsHost()) { - Utils.SendMessage(GetString("KickCommandNoAccess"), player.PlayerId); + Utils.SendMessage(GetString("KickCommandNoAccess"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1547,13 +1554,13 @@ internal static class ChatCommands if (string.IsNullOrEmpty(subArgs) || !byte.TryParse(subArgs, out byte kickPlayerId)) { - Utils.SendMessage(GetString("KickCommandInvalidID"), player.PlayerId); + Utils.SendMessage(GetString("KickCommandInvalidID"), player.PlayerId, sendOption: SendOption.None); return; } if (kickPlayerId.IsHost()) { - Utils.SendMessage(GetString("KickCommandKickHost"), player.PlayerId); + Utils.SendMessage(GetString("KickCommandKickHost"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1561,14 +1568,14 @@ internal static class ChatCommands if (kickedPlayer == null) { - Utils.SendMessage(GetString("KickCommandInvalidID"), player.PlayerId); + Utils.SendMessage(GetString("KickCommandInvalidID"), player.PlayerId, sendOption: SendOption.None); return; } // Prevent Moderators from kicking other Moderators if (IsPlayerModerator(kickedPlayer.FriendCode)) { - Utils.SendMessage(GetString("KickCommandKickMod"), player.PlayerId); + Utils.SendMessage(GetString("KickCommandKickMod"), player.PlayerId, sendOption: SendOption.None); return; } @@ -1578,7 +1585,7 @@ internal static class ChatCommands var textToSend = $"{kickedPlayerName} {GetString("KickCommandKicked")}"; if (GameStates.IsInGame) textToSend += $"{GetString("KickCommandKickedRole")} {kickedPlayer.GetCustomRole().ToColoredString()}"; - Utils.SendMessage(textToSend); + Utils.SendMessage(textToSend, sendOption: GameStates.IsInGame ? SendOption.Reliable : SendOption.None); } private static void CheckCommand(PlayerControl player, string text, string[] args) @@ -1764,7 +1771,7 @@ internal static class ChatCommands if (killer == null) { - Utils.SendMessage("\n", player.PlayerId, GetString("DeathCommandFail")); + Utils.SendMessage("\n", player.PlayerId, GetString("DeathCommandFail"), sendOption: SendOption.None); return; } @@ -1802,7 +1809,7 @@ internal static class ChatCommands if (args.Length > 1) TemplateManager.SendTemplate(args[1], player.PlayerId); else - Utils.SendMessage($"{GetString("ForExample")}:\n{args[0]} test", player.PlayerId); + Utils.SendMessage($"{GetString("ForExample")}:\n{args[0]} test", player.PlayerId, sendOption: SendOption.None); } } @@ -2300,7 +2307,7 @@ internal static class ChatCommands if (GameStates.IsInGame) { - Utils.SendMessage(GetString("Message.OnlyCanUseInLobby"), player.PlayerId); + Utils.SendMessage(GetString("Message.OnlyCanUseInLobby"), player.PlayerId, sendOption: SendOption.None); return; } @@ -2308,7 +2315,7 @@ internal static class ChatCommands if (name.Length is > 50 or < 1) { - Utils.SendMessage(GetString("Message.AllowNameLength"), player.PlayerId); + Utils.SendMessage(GetString("Message.AllowNameLength"), player.PlayerId, sendOption: SendOption.None); return; } @@ -2341,7 +2348,7 @@ internal static class ChatCommands } if (Main.WinnerNameList.Count == 0) - Utils.SendMessage(GetString("NoInfoExists")); + Utils.SendMessage(GetString("NoInfoExists"), sendOption: SendOption.None); else Utils.SendMessage("Winners:\n" + string.Join(", ", Main.WinnerNameList)); } @@ -2918,7 +2925,7 @@ internal static class ChatCommands { string text = GetString($"ModeDescribe.{Options.CurrentGameMode}"); bool allInOne = Options.CurrentGameMode == CustomGameMode.AllInOne; - Utils.SendMessage(allInOne ? "\n" : text, playerId, allInOne ? text : ""); + Utils.SendMessage(allInOne ? "\n" : text, playerId, allInOne ? text : "", sendOption: SendOption.None); if (!CustomGameMode.HideAndSeek.IsActiveOrIntegrated()) return; } @@ -2951,7 +2958,7 @@ internal static class ChatCommands if (rl.GetCount() < 1 || rl.GetMode() == 0) devMark = string.Empty; - if (isUp) Utils.SendMessage(devMark == "▲" ? string.Format(GetString("Message.YTPlanSelected"), roleName) : string.Format(GetString("Message.YTPlanSelectFailed"), roleName), playerId); + if (isUp) Utils.SendMessage(devMark == "▲" ? string.Format(GetString("Message.YTPlanSelected"), roleName) : string.Format(GetString("Message.YTPlanSelectFailed"), roleName), playerId, sendOption: SendOption.None); if (isUp) return; } @@ -2992,12 +2999,12 @@ internal static class ChatCommands { string text = GetString($"ModeDescribe.{gameMode}"); bool allInOne = gameMode == CustomGameMode.AllInOne; - Utils.SendMessage(allInOne ? "\n" : text, playerId, allInOne ? text : gmString); + Utils.SendMessage(allInOne ? "\n" : text, playerId, allInOne ? text : gmString, sendOption: SendOption.None); return; } } - Utils.SendMessage(isUp ? GetString("Message.YTPlanCanNotFindRoleThePlayerEnter") : GetString("Message.CanNotFindRoleThePlayerEnter"), playerId); + Utils.SendMessage(isUp ? GetString("Message.YTPlanCanNotFindRoleThePlayerEnter") : GetString("Message.CanNotFindRoleThePlayerEnter"), playerId, sendOption: SendOption.None); } // ------------------------------------------------------------------------------------------------------------------------- diff --git a/Patches/GameStartManagerPatch.cs b/Patches/GameStartManagerPatch.cs index 1e6c89689..72258cc10 100644 --- a/Patches/GameStartManagerPatch.cs +++ b/Patches/GameStartManagerPatch.cs @@ -7,6 +7,7 @@ using EHR.Modules; using EHR.Neutral; using EHR.Patches; using HarmonyLib; +using Hazel; using InnerNet; using TMPro; using UnityEngine; @@ -174,7 +175,7 @@ public static class GameStartManagerPatch Logger.SendInGame(GetString("Error.InvalidColorPreventStart")); string msg = GetString("Error.InvalidColor"); msg += "\n" + string.Join(",", invalidColor.Select(p => $"{p.GetRealName()}")); - Utils.SendMessage(msg); + Utils.SendMessage(msg, sendOption: SendOption.None); } if (Options.RandomMapsMode.GetBool()) @@ -430,7 +431,7 @@ public static class GameStartRandomMap Logger.SendInGame(GetString("Error.InvalidColorPreventStart")); string msg = GetString("Error.InvalidColor"); msg += "\n" + string.Join(",", invalidColor.Select(p => $"{p.GetRealName()}")); - Utils.SendMessage(msg); + Utils.SendMessage(msg, sendOption: SendOption.None); return false; } diff --git a/Patches/MeetingHudPatch.cs b/Patches/MeetingHudPatch.cs index d7cc314ab..c80dfc768 100644 --- a/Patches/MeetingHudPatch.cs +++ b/Patches/MeetingHudPatch.cs @@ -665,10 +665,12 @@ internal static class MeetingHudStartPatch CheckForEndVotingPatch.RunRoleCode = true; - List<(string Message, byte TargetID, string Title)> msgToSend = []; + List msgToSend = []; if (Options.SendRoleDescriptionFirstMeeting.GetBool() && MeetingStates.FirstMeeting && Options.CurrentGameMode == CustomGameMode.Standard) { + List roleDescMsgs = []; + foreach (PlayerControl pc in Main.AllAlivePlayerControls) { if (pc.IsModdedClient()) continue; @@ -699,15 +701,19 @@ internal static class MeetingHudStartPatch sb.Replace(searchSubStr.ToLower(), subRole.ToColoredString()); } - if (settings.Length > 0) AddMsg("\n", pc.PlayerId, settings.ToString()); + if (settings.Length > 0) roleDescMsgs.Add(new("\n", pc.PlayerId, settings.ToString())); - AddMsg(sb.Append("").ToString(), pc.PlayerId, titleSb.ToString()); + roleDescMsgs.Add(new(sb.Append("").ToString(), pc.PlayerId, titleSb.ToString())); } + + LateTask.New(() => roleDescMsgs.SendMultipleMessages(SendOption.None), 6f, "Send Role Descriptions Round 1"); } - if (Options.MadmateSpawnMode.GetInt() == 2 && CustomRoles.Madmate.IsEnable() && MeetingStates.FirstMeeting) AddMsg(string.Format(GetString("Message.MadmateSelfVoteModeNotify"), GetString("MadmateSpawnMode.SelfVote"))); + if (Options.MadmateSpawnMode.GetInt() == 2 && CustomRoles.Madmate.IsEnable() && MeetingStates.FirstMeeting) + AddMsg(string.Format(GetString("Message.MadmateSelfVoteModeNotify"), GetString("MadmateSpawnMode.SelfVote"))); - if (CustomRoles.God.RoleExist() && God.NotifyGodAlive.GetBool()) AddMsg(GetString("GodNoticeAlive"), 255, Utils.ColorString(Utils.GetRoleColor(CustomRoles.God), GetString("GodAliveTitle"))); + if (CustomRoles.God.RoleExist() && God.NotifyGodAlive.GetBool()) + AddMsg(GetString("GodNoticeAlive"), 255, Utils.ColorString(Utils.GetRoleColor(CustomRoles.God), GetString("GodAliveTitle"))); if (MeetingStates.FirstMeeting && CustomRoles.Workaholic.RoleExist() && Workaholic.WorkaholicGiveAdviceAlive.GetBool() && !Workaholic.WorkaholicCannotWinAtDeath.GetBool() /* && !Options.GhostIgnoreTasks.GetBool()*/) { @@ -789,7 +795,7 @@ internal static class MeetingHudStartPatch } } - if (msgToSend.Count > 0) LateTask.New(() => msgToSend.Do(x => Utils.SendMessage(x.Message, x.TargetID, x.Title)), 6f, "Meeting Start Notify"); + if (msgToSend.Count > 0) LateTask.New(() => msgToSend.Do(x => Utils.SendMessage(x.Text, x.SendTo, x.Title)), 6f, "Meeting Start Notify"); Main.CyberStarDead.Clear(); Express.SpeedNormal.Clear(); @@ -801,7 +807,7 @@ internal static class MeetingHudStartPatch Enigma.MsgToSend.Clear(); return; - void AddMsg(string text, byte sendTo = 255, string title = "") => msgToSend.Add((text, sendTo, title)); + void AddMsg(string text, byte sendTo = 255, string title = "") => msgToSend.Add(new(text, sendTo, title)); } public static void Prefix( /*MeetingHud __instance*/) diff --git a/Patches/OnGameStartedPatch.cs b/Patches/OnGameStartedPatch.cs index ec9abceba..068e515bc 100644 --- a/Patches/OnGameStartedPatch.cs +++ b/Patches/OnGameStartedPatch.cs @@ -301,7 +301,7 @@ internal static class ChangeRoleSettings string msg = GetString("Error.InvalidColor"); Logger.SendInGame(msg); msg += "\n" + string.Join(",", invalidColor); - Utils.SendMessage(msg); + Utils.SendMessage(msg, sendOption: SendOption.None); Logger.Error(msg, "CoStartGame"); } } diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index 34c1cc7b3..3f7e74040 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -1079,7 +1079,7 @@ internal static class ReportDeadBodyPatch PlayerControl killer = receiver.GetRealKiller(); if (killer == null) continue; - SendMessage("\n", receiver.PlayerId, string.Format(GetString("DeathCommand"), killer.PlayerId.ColoredPlayerName(), (killer.Is(CustomRoles.Bloodlust) ? $"{CustomRoles.Bloodlust.ToColoredString()} " : string.Empty) + killer.GetCustomRole().ToColoredString())); + SendMessage("\n", receiver.PlayerId, string.Format(GetString("DeathCommand"), killer.PlayerId.ColoredPlayerName(), (killer.Is(CustomRoles.Bloodlust) ? $"{CustomRoles.Bloodlust.ToColoredString()} " : string.Empty) + killer.GetCustomRole().ToColoredString()), sendOption: SendOption.None); } } diff --git a/Patches/PlayerJoinAndLeftPatch.cs b/Patches/PlayerJoinAndLeftPatch.cs index 6ecdad2b0..3b0a9bfc0 100644 --- a/Patches/PlayerJoinAndLeftPatch.cs +++ b/Patches/PlayerJoinAndLeftPatch.cs @@ -320,7 +320,7 @@ internal static class InnerNetClientSpawnPatch LateTask.New(() => { if (Main.OverrideWelcomeMsg != "") - Utils.SendMessage(Main.OverrideWelcomeMsg, client.Character.PlayerId); + Utils.SendMessage(Main.OverrideWelcomeMsg, client.Character.PlayerId, sendOption: SendOption.None); else TemplateManager.SendTemplate("welcome", client.Character.PlayerId, true); }, GameStates.CurrentServerType == GameStates.ServerType.Niko ? 7f : 3f, "Welcome Message"); diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index 0d18d69d4..83f46b076 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -702,7 +702,7 @@ "WitchInfoLong": "(Impostors):\\nThe Witch can kill players directly or cast spells by tapping the kill button once or twice, respectively. Spelled players will have a 「†」 mark next to their name in the next meeting. If the Witch survives until the meeting's end, all spelled players die.", "MafiaInfoLong": "(Impostors):\\nNemesis can't kill while there are other Impostors alive in the game, but can use /rv [player id] after death to kill the specified player.", "GodfatherInfoLong": "(Impostors):\\nAs a Godfather, you vote for someone to make them your target. In the next round if someone kills the target, the killer will turn into a refugee", - "PuppeteerInfoLong": "(Impostors):\\nPuppeteers control a player that can kill the next non-impostor who gets too close. If the non-impostor dies on contact, the Puppeteer also dies. Lazy Guy is useless.", + "PuppeteerInfoLong": "(Impostors):\\nAs the Puppeteer, use your kill button to manipulate someone. After a certain time, they will kill the next player that approaches them.\\n\\nThere are a lot of settings for this role, which further varies its mechanics:\\n- You may be able to kill normally using double click.\\n- The manipulation may end after a certain time, even if the manipulated player didn't kill anyone.\\n- Lazy Guy and/or Lazy players may not be able to get manipulated.\\n- The manipulated player may even kill other impostors or the Puppeteer itself.\\n- The maximum times you can manipulate someone may be limited.\\n- You may die after using up all your puppets.\\n- Manipulated players may die along with their victim.", "TimeThiefInfoLong": "(Impostors):\\nEvery time the Time Thief kills a player, the meeting time will be reduced by a certain amount of time. If the Time Thief dies, the meeting time will return to normal.", "SniperInfoLong": "(Impostors):\\nIf you want to shoot players from a distance, you'll need to follow these steps. First, you must shapeshift or pet twice to make a successful snipe. Once you've done that, imagine an arrow pointing from your first shapeshift or petting location to your unshift or second petting location. That arrow will show you the direction in which the snipe will be made. Remember that the snipe only kills the first person in its path. Also, you won't be able to kill anyone normally until you use up all of your ammo.", "EvilTrackerInfoLong": "(Impostors):\\nThe Evil Tracker can track and shapeshift to switch the tracking target but will unshift immediately after. The arrow below their name indicates the target's direction. They receive a kill flash when their teammate kills.", @@ -8469,7 +8469,7 @@ "GNoWon": "Oh, how did you ever figure that out? It's almost like you're a mind reader! Congratulations, you're a genius! You found the secret number with {0} guesses left!", "Bandit": "Bandit", "BanditInfo": "Rob Add-ons", - "BanditInfoLong": "(Neutral):\\nAs the Bandit, use your kill button to steal a player's Addon. Depending on the settings, you may instantly steal the addon or after the meeting starts. After the max number of steals are reached you will be able to kill normally. Additionaly, if there are no stealable addons present on the target, you will the target.\\n\\nKill everyone to win.\\n\\nNote: Cleansed and Last Impostor can not be stolen.", + "BanditInfoLong": "(Neutral):\\nAs the Bandit, single click with your kill button to steal an add-on from your target (if they have any that can be stolen), double click to kill them normally.\\n\\nKill everyone to win!\\nNotes:\\n- If you run out of ability uses, the kill button kills at all times.\\n- Add-ons may be stolen when a meeting gets called instead of immediately.", "BanditStealMode.OnMeeting": "On Meeting", "BanditStealMode.Instantly": "Instantly", "BanditMaxSteals": "Maximum Steals", diff --git a/Roles/Crewmate/Catcher.cs b/Roles/Crewmate/Catcher.cs index d440f964c..ec4211d8d 100644 --- a/Roles/Crewmate/Catcher.cs +++ b/Roles/Crewmate/Catcher.cs @@ -158,7 +158,7 @@ public class Catcher : RoleBase Utils.SendMessage("\n", CatcherId, Translator.GetString("Catcher.CaughtRoles") + roles); } else - Utils.SendMessage("\n", CatcherId, Translator.GetString("Catcher.NotEnoughCaughtRoles")); + Utils.SendMessage("\n", CatcherId, Translator.GetString("Catcher.NotEnoughCaughtRoles"), sendOption: SendOption.None); CaughtRoles = []; }, 10f, "Send Catcher Caught Roles"); diff --git a/Roles/Crewmate/Cleanser.cs b/Roles/Crewmate/Cleanser.cs index 0991ca63c..5c1a0a824 100644 --- a/Roles/Crewmate/Cleanser.cs +++ b/Roles/Crewmate/Cleanser.cs @@ -98,7 +98,7 @@ public class Cleanser : RoleBase if (target.PlayerId == voter.PlayerId) { - Utils.SendMessage(GetString("CleanserRemoveSelf"), voter.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle"))); + Utils.SendMessage(GetString("CleanserRemoveSelf"), voter.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle")), sendOption: SendOption.None); return false; } @@ -108,7 +108,7 @@ public class Cleanser : RoleBase CleanserTarget = target.PlayerId; Logger.Info($"{voter.GetNameWithRole().RemoveHtmlTags()} cleansed {target.GetNameWithRole().RemoveHtmlTags()}", "Cleansed"); CleansedPlayers.Add(target.PlayerId); - Utils.SendMessage(string.Format(GetString("CleanserRemovedRole"), target.GetRealName()), voter.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle"))); + Utils.SendMessage(string.Format(GetString("CleanserRemovedRole"), target.GetRealName()), voter.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle")), sendOption: SendOption.None); SendRPC(voter.PlayerId); Main.DontCancelVoteList.Add(voter.PlayerId); diff --git a/Roles/Crewmate/Divinator.cs b/Roles/Crewmate/Divinator.cs index 5b399e9d9..44adf7faf 100644 --- a/Roles/Crewmate/Divinator.cs +++ b/Roles/Crewmate/Divinator.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using EHR.Modules; +using Hazel; using static EHR.Options; using static EHR.Translator; @@ -115,7 +116,7 @@ public class Divinator : RoleBase if (player.PlayerId == target.PlayerId) { - Utils.SendMessage(GetString("DivinatorCheckSelfMsg") + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), player.GetAbilityUseLimit()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle"))); + Utils.SendMessage(GetString("DivinatorCheckSelfMsg") + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), player.GetAbilityUseLimit()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")), sendOption: SendOption.None); return false; } @@ -129,7 +130,7 @@ public class Divinator : RoleBase msg = string.Format(GetString("DivinatorCheckResult"), target.GetRealName(), roles); } - Utils.SendMessage(GetString("DivinatorCheck") + "\n" + msg + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), player.GetAbilityUseLimit()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle"))); + Utils.SendMessage(GetString("DivinatorCheck") + "\n" + msg + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), player.GetAbilityUseLimit()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")), sendOption: SendOption.None); Main.DontCancelVoteList.Add(player.PlayerId); return true; diff --git a/Roles/Crewmate/Judge.cs b/Roles/Crewmate/Judge.cs index bd8610efe..87a781bf1 100644 --- a/Roles/Crewmate/Judge.cs +++ b/Roles/Crewmate/Judge.cs @@ -104,7 +104,7 @@ public class Judge : RoleBase if (!pc.IsAlive()) { - Utils.SendMessage(GetString("JudgeDead"), pc.PlayerId); + Utils.SendMessage(GetString("JudgeDead"), pc.PlayerId, sendOption: SendOption.None); return true; } @@ -121,7 +121,7 @@ public class Judge : RoleBase if (!MsgToPlayerAndRole(msg, out byte targetId, out string error)) { - Utils.SendMessage(error, pc.PlayerId); + Utils.SendMessage(error, pc.PlayerId, sendOption: SendOption.None); return true; } @@ -165,7 +165,7 @@ public class Judge : RoleBase if (pc.PlayerId == target.PlayerId) { if (!isUI) - Utils.SendMessage(GetString("LaughToWhoTrialSelf"), pc.PlayerId, Utils.ColorString(Color.cyan, GetString("MessageFromKPD"))); + Utils.SendMessage(GetString("LaughToWhoTrialSelf"), pc.PlayerId, Utils.ColorString(Color.cyan, GetString("MessageFromKPD")), sendOption: SendOption.None); else pc.ShowPopUp(Utils.ColorString(Color.cyan, GetString("MessageFromKPD")) + "\n" + GetString("LaughToWhoTrialSelf")); diff --git a/Roles/Crewmate/NiceEraser.cs b/Roles/Crewmate/NiceEraser.cs index 98ea4dd37..b12ddd19c 100644 --- a/Roles/Crewmate/NiceEraser.cs +++ b/Roles/Crewmate/NiceEraser.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Hazel; using static EHR.Translator; namespace EHR.Crewmate; @@ -58,7 +59,7 @@ internal class NiceEraser : RoleBase if (target.PlayerId == player.PlayerId) { - Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle"))); + Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle")), sendOption: SendOption.None); return false; } diff --git a/Roles/Crewmate/NiceSwapper.cs b/Roles/Crewmate/NiceSwapper.cs index 57729860d..1e5cb5465 100644 --- a/Roles/Crewmate/NiceSwapper.cs +++ b/Roles/Crewmate/NiceSwapper.cs @@ -89,8 +89,7 @@ public class NiceSwapper : RoleBase { if (!pc.IsAlive()) { - if (!isUI) Utils.SendMessage(GetString("SwapDead"), pc.PlayerId); - + if (!isUI) Utils.SendMessage(GetString("SwapDead"), pc.PlayerId, sendOption: SendOption.None); pc.ShowPopUp(GetString("SwapDead")); return true; } diff --git a/Roles/Crewmate/Oracle.cs b/Roles/Crewmate/Oracle.cs index d9e766d69..b78f86409 100644 --- a/Roles/Crewmate/Oracle.cs +++ b/Roles/Crewmate/Oracle.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Hazel; using static EHR.Options; using static EHR.Translator; @@ -81,7 +82,7 @@ public class Oracle : RoleBase if (player.PlayerId == target.PlayerId) { - Utils.SendMessage(GetString("OracleCheckSelfMsg") + "\n\n" + string.Format(GetString("OracleCheckLimit"), player.GetAbilityUseLimit()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle"))); + Utils.SendMessage(GetString("OracleCheckSelfMsg") + "\n\n" + string.Format(GetString("OracleCheckLimit"), player.GetAbilityUseLimit()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle")), sendOption: SendOption.None); return false; } diff --git a/Roles/Crewmate/ParityCop.cs b/Roles/Crewmate/ParityCop.cs index 292149d32..a0c4765c9 100644 --- a/Roles/Crewmate/ParityCop.cs +++ b/Roles/Crewmate/ParityCop.cs @@ -4,6 +4,7 @@ using System.Linq; using EHR.Modules; using EHR.Neutral; using HarmonyLib; +using Hazel; using UnityEngine; using static EHR.Options; using static EHR.Translator; @@ -131,7 +132,7 @@ public class ParityCop : RoleBase if (!pc.IsAlive()) { - Utils.SendMessage(GetString("ParityCopDead"), pc.PlayerId); + Utils.SendMessage(GetString("ParityCopDead"), pc.PlayerId, sendOption: SendOption.None); return true; } diff --git a/Roles/Impostor/Councillor.cs b/Roles/Impostor/Councillor.cs index 5345d0089..346c9e4d9 100644 --- a/Roles/Impostor/Councillor.cs +++ b/Roles/Impostor/Councillor.cs @@ -113,7 +113,7 @@ public class Councillor : RoleBase if (!pc.IsAlive()) { - Utils.SendMessage(GetString("CouncillorDead"), pc.PlayerId); + Utils.SendMessage(GetString("CouncillorDead"), pc.PlayerId, sendOption: SendOption.None); return true; } diff --git a/Roles/Impostor/Eraser.cs b/Roles/Impostor/Eraser.cs index 7d489c171..bddb7ba66 100644 --- a/Roles/Impostor/Eraser.cs +++ b/Roles/Impostor/Eraser.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Hazel; using static EHR.Translator; namespace EHR.Impostor; @@ -110,7 +111,7 @@ internal class Eraser : RoleBase if (target.PlayerId == player.PlayerId) { - Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle"))); + Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle")), sendOption: SendOption.None); return false; } diff --git a/Roles/Impostor/Mafia.cs b/Roles/Impostor/Mafia.cs index c76abe6c0..890c154cc 100644 --- a/Roles/Impostor/Mafia.cs +++ b/Roles/Impostor/Mafia.cs @@ -74,7 +74,7 @@ internal class Mafia : RoleBase if (MafiaCanKillNum.GetInt() < 1) { if (!isUI) - Utils.SendMessage(GetString("MafiaKillDisable"), pc.PlayerId); + Utils.SendMessage(GetString("MafiaKillDisable"), pc.PlayerId, sendOption: SendOption.None); else pc.ShowPopUp(GetString("MafiaKillDisable")); @@ -83,7 +83,7 @@ internal class Mafia : RoleBase if (!pc.Data.IsDead) { - Utils.SendMessage(GetString("MafiaAliveKill"), pc.PlayerId); + Utils.SendMessage(GetString("MafiaAliveKill"), pc.PlayerId, sendOption: SendOption.None); return true; } @@ -119,7 +119,7 @@ internal class Mafia : RoleBase catch { if (!isUI) - Utils.SendMessage(GetString("MafiaKillDead"), pc.PlayerId); + Utils.SendMessage(GetString("MafiaKillDead"), pc.PlayerId, sendOption: SendOption.None); else pc.ShowPopUp(GetString("MafiaKillDead")); @@ -129,7 +129,7 @@ internal class Mafia : RoleBase if (target == null || target.Data.IsDead) { if (!isUI) - Utils.SendMessage(GetString("MafiaKillDead"), pc.PlayerId); + Utils.SendMessage(GetString("MafiaKillDead"), pc.PlayerId, sendOption: SendOption.None); else pc.ShowPopUp(GetString("MafiaKillDead")); @@ -146,7 +146,7 @@ internal class Mafia : RoleBase return true; } - Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} 复仇了 {target.GetNameWithRole().RemoveHtmlTags()}", "Mafia"); + Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} revenged {target.GetNameWithRole().RemoveHtmlTags()}", "Mafia"); string Name = target.GetRealName();