From bb7fb0ddea619bdc5ad054065ad911ca0866da80 Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Sun, 26 Jan 2025 12:50:45 +0100 Subject: [PATCH] custom languages support & fixes --- GameMode/MoveAndStop.cs | 6 +- Modules/GuessManager.cs | 118 +++++++++++++++++++++------------- Modules/OptionHolder.cs | 15 ++++- Modules/Translator.cs | 95 +++++++++++---------------- Patches/PlayerControlPatch.cs | 7 +- Resources/Lang/en_US.json | 4 ++ Roles/Crewmate/Spy.cs | 1 + Roles/Impostor/Swooper.cs | 13 ++-- 8 files changed, 139 insertions(+), 120 deletions(-) diff --git a/GameMode/MoveAndStop.cs b/GameMode/MoveAndStop.cs index cc6461959..55988faf7 100644 --- a/GameMode/MoveAndStop.cs +++ b/GameMode/MoveAndStop.cs @@ -170,7 +170,7 @@ internal static class MoveAndStop public static int RoundTime { get; set; } - private static bool HasJustStarted => GameTime.GetInt() - RoundTime < 20; + private static int TimeSinceStart => GameTime.GetInt() - RoundTime; private static int ExtraGreenTime => Main.CurrentMap switch { @@ -392,7 +392,7 @@ internal static class MoveAndStop var text = IsEventActive ? $"{string.Format(GetString("MoveAndStop_EventActive"), GetString($"MoveAndStop_Event_{Event.Type}"), Event.Duration + Event.StartTimeStamp - Utils.TimeStamp)}\n" : "\n"; text += IsEventActive && Event.Type == Events.FrozenTimers ? FixedUpdatePatch.LastSuffix[pc.PlayerId].Trim() : timers.ToString(); - if (HasJustStarted && EnableTutorial.GetBool() && !HasPlayed.Contains(pc.FriendCode) && Options.CurrentGameMode != CustomGameMode.AllInOne) + if (TimeSinceStart < 20 && EnableTutorial.GetBool() && !HasPlayed.Contains(pc.FriendCode) && Options.CurrentGameMode != CustomGameMode.AllInOne) text += $"\n\n{GetString("MoveAndStop_Tutorial")}"; return text; @@ -416,7 +416,7 @@ internal static class MoveAndStop PlayerControl pc = __instance; long now = Utils.TimeStamp; - if (!HasJustStarted && pc.IsLocalPlayer() && !IsEventActive && (now - Event.StartTimeStamp - Event.Duration) >= EventFrequency.GetInt()) + if (TimeSinceStart > 25 && !IsEventActive && (now - Event.StartTimeStamp - Event.Duration) >= EventFrequency.GetInt()) { var pool = EventChances.SelectMany(x => Enumerable.Repeat(x.Key, x.Value.GetInt() / 5)).ToList(); if (Event.Duration == 0) pool.RemoveAll(x => x == Events.VentAccess); diff --git a/Modules/GuessManager.cs b/Modules/GuessManager.cs index 714fd343f..93c04d129 100644 --- a/Modules/GuessManager.cs +++ b/Modules/GuessManager.cs @@ -21,8 +21,17 @@ namespace EHR; public static class GuessManager { + private const int MaxOneScreenRole = 40; private static readonly int Mask = Shader.PropertyToID("_Mask"); public static HashSet Guessers = []; + private static int Page; + private static GameObject guesserUI; + private static Dictionary> RoleButtons; + private static Dictionary RoleSelectButtons; + private static List PageButtons; + private static CustomRoleTypes currentTeamType; + + public static TextMeshPro textTemplate; public static string GetFormatString() => Main.AllAlivePlayerControls.Aggregate(GetString("PlayerIdList"), (current, pc) => current + $"\n{pc.PlayerId.ToString()} → {pc.GetRealName()}"); @@ -87,7 +96,8 @@ public static class GuessManager if (!AmongUsClient.Instance.AmHost) return false; if (!GameStates.IsMeeting || pc == null) return false; - if (pc.GetCustomRole() is not (CustomRoles.NiceGuesser or CustomRoles.EvilGuesser or CustomRoles.Doomsayer or CustomRoles.Judge or CustomRoles.NiceSwapper or CustomRoles.Councillor or CustomRoles.NecroGuesser) && !pc.Is(CustomRoles.Guesser) && !Options.GuesserMode.GetBool()) 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; int operate; // 1: ID, 2: Guess msg = msg.ToLower().TrimStart().TrimEnd(); @@ -114,15 +124,16 @@ public static class GuessManager if (pc.Is(CustomRoles.Lyncher) && Lyncher.GuessMode.GetValue() == 2) goto SkipCheck; - if ((!pc.Is(CustomRoles.NiceGuesser) && pc.IsCrewmate() && !Options.CrewmatesCanGuess.GetBool() && !pc.Is(CustomRoles.Judge) && !pc.Is(CustomRoles.NiceSwapper)) || - (!pc.Is(CustomRoles.EvilGuesser) && pc.IsImpostor() && !Options.ImpostorsCanGuess.GetBool() && !pc.Is(CustomRoles.Councillor)) || - (!pc.Is(CustomRoles.Augur) && pc.Is(Team.Coven) && !Options.CovenCanGuess.GetBool()) || + if ((pc.IsCrewmate() && !Options.CrewmatesCanGuess.GetBool()) || + (pc.IsImpostor() && !Options.ImpostorsCanGuess.GetBool()) || + (pc.Is(Team.Coven) && !Options.CovenCanGuess.GetBool()) || (pc.IsNeutralKiller() && !Options.NeutralKillersCanGuess.GetBool()) || - (pc.GetCustomRole().IsNonNK() && !Options.PassiveNeutralsCanGuess.GetBool() && pc.GetCustomRole() is not CustomRoles.Doomsayer and not CustomRoles.NecroGuesser) || + (pc.GetCustomRole().IsNonNK() && !Options.PassiveNeutralsCanGuess.GetBool()) || (pc.Is(CustomRoles.Lyncher) && Lyncher.GuessMode.GetValue() == 0) || (Options.GuesserNumRestrictions.GetBool() && !Guessers.Contains(pc.PlayerId))) { if (pc.Is(CustomRoles.Guesser)) goto SkipCheck; + if (hasGuessingRole) goto SkipCheck; if ((pc.Is(CustomRoles.Madmate) || pc.IsConverted()) && Options.BetrayalAddonsCanGuess.GetBool()) goto SkipCheck; ShowMessage("GuessNotAllowed"); @@ -426,14 +437,14 @@ public static class GuessManager if (DoubleShot.CheckGuess(pc, isUI)) return true; guesserSuicide = true; } - else if (pc.Is(CustomRoles.NiceGuesser) && target.IsCrewmate() && !Options.GGCanGuessCrew.GetBool() && !pc.Is(CustomRoles.Madmate)) + else if (pc.Is(CustomRoles.NiceGuesser) && role.IsCrewmate() && !Options.GGCanGuessCrew.GetBool() && !pc.Is(CustomRoles.Madmate)) { if (!isUI) Utils.SendMessage(GetString("GuessCrewRole"), pc.PlayerId, Utils.ColorString(Color.cyan, GetString("MessageFromGurge44"))); else pc.ShowPopUp($"{Utils.ColorString(Color.cyan, GetString("MessageFromGurge44"))}\n{GetString("GuessCrewRole")}"); return true; } - else if (pc.Is(CustomRoles.EvilGuesser) && target.IsImpostor() && !Options.EGCanGuessImp.GetBool()) + else if (pc.Is(CustomRoles.EvilGuesser) && role.IsImpostor() && !Options.EGCanGuessImp.GetBool()) { if (!isUI) Utils.SendMessage(GetString("GuessImpRole"), pc.PlayerId, Utils.ColorString(Color.cyan, GetString("MessageFromGurge44"))); else pc.ShowPopUp($"{Utils.ColorString(Color.cyan, GetString("MessageFromGurge44"))}\n{GetString("GuessImpRole")}"); @@ -721,29 +732,36 @@ public static class GuessManager } } - private const int MaxOneScreenRole = 40; - private static int Page; - private static GameObject guesserUI; - private static Dictionary> RoleButtons; - private static Dictionary RoleSelectButtons; - private static List PageButtons; - private static CustomRoleTypes currentTeamType; static void GuesserSelectRole(CustomRoleTypes role, bool setPage = true) { currentTeamType = role; if (setPage) Page = 1; + foreach (var RoleButton in RoleButtons) { int index = 0; + foreach (var RoleBtn in RoleButton.Value) { if (RoleBtn == null) continue; index++; - if (index <= (Page - 1) * 40) { RoleBtn.gameObject.SetActive(false); continue; } - if ((Page * 40) < index) { RoleBtn.gameObject.SetActive(false); continue; } + + if (index <= (Page - 1) * 40) + { + RoleBtn.gameObject.SetActive(false); + continue; + } + + if ((Page * 40) < index) + { + RoleBtn.gameObject.SetActive(false); + continue; + } + RoleBtn.gameObject.SetActive(RoleButton.Key == role); } } + foreach (var RoleButton in RoleSelectButtons) { if (RoleButton.Value == null) continue; @@ -751,7 +769,6 @@ public static class GuessManager } } - public static TextMeshPro textTemplate; static void GuesserOnClick(byte playerId, MeetingHud __instance) { var pc = Utils.GetPlayerById(playerId); @@ -788,17 +805,20 @@ public static class GuessManager exitButtonParent.transform.localScale = new Vector3(0.22f, 0.9f, 1f); exitButtonParent.transform.SetAsFirstSibling(); exitButton.GetComponent().OnClick.RemoveAllListeners(); + exitButton.GetComponent().OnClick.AddListener((Action)(() => { __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(true)); Object.Destroy(container.gameObject); })); + exitButton.GetComponent(); List buttons = []; Transform selectedButton = null; int tabCount = 0; + for (int index = 0; index < 5; index++) { switch (PlayerControl.LocalPlayer.GetCustomRole(), index) @@ -809,7 +829,7 @@ public static class GuessManager case (CustomRoles.NiceGuesser, 3) when !Options.GGCanGuessAdt.GetBool(): continue; } - + Transform TeambuttonParent = new GameObject().transform; TeambuttonParent.SetParent(container); Transform Teambutton = Object.Instantiate(buttonTemplate, TeambuttonParent); @@ -820,6 +840,7 @@ public static class GuessManager RoleSelectButtons.Add((CustomRoleTypes)index, Teambutton.GetComponent()); TeambuttonParent.localPosition = new(-2.75f + (tabCount++ * 1.73f), 2.225f, -200); TeambuttonParent.localScale = new(0.53f, 0.53f, 1f); + Teamlabel.color = (CustomRoleTypes)index switch { CustomRoleTypes.Coven => Team.Coven.GetColor(), @@ -829,6 +850,7 @@ public static class GuessManager CustomRoleTypes.Addon => new Color32(255, 154, 206, byte.MaxValue), _ => throw new ArgumentOutOfRangeException("The index is out of range, it's an invalid CustomRoleTypes (GuessManager.cs:GuesserOnClick method)", innerException: null) }; + Logger.Info(Teamlabel.color.ToString(), ((CustomRoleTypes)index).ToString()); Teamlabel.text = GetString("Type" + ((CustomRoleTypes)index)); Teamlabel.alignment = TextAlignmentOptions.Center; @@ -848,26 +870,28 @@ public static class GuessManager })); } } + static void ReloadPage() { PageButtons[0].color = new(1, 1, 1, 1f); PageButtons[1].color = new(1, 1, 1, 1f); + if ((RoleButtons[currentTeamType].Count / MaxOneScreenRole + (RoleButtons[currentTeamType].Count % MaxOneScreenRole != 0 ? 1 : 0)) < Page) { Page -= 1; PageButtons[1].color = new(1, 1, 1, 0.1f); } - else if ((RoleButtons[currentTeamType].Count / MaxOneScreenRole + (RoleButtons[currentTeamType].Count % MaxOneScreenRole != 0 ? 1 : 0)) < Page + 1) - { - PageButtons[1].color = new(1, 1, 1, 0.1f); - } + else if ((RoleButtons[currentTeamType].Count / MaxOneScreenRole + (RoleButtons[currentTeamType].Count % MaxOneScreenRole != 0 ? 1 : 0)) < Page + 1) { PageButtons[1].color = new(1, 1, 1, 0.1f); } + if (Page <= 1) { Page = 1; PageButtons[0].color = new(1, 1, 1, 0.1f); } + GuesserSelectRole(currentTeamType, false); } + static void CreatePage(bool isNext, MeetingHud __instance, Transform container) { var buttonTemplate = __instance.playerStates[0].transform.FindChild("votePlayerBase"); @@ -896,10 +920,12 @@ public static class GuessManager { if (isNext) Page += 1; else Page -= 1; + if (Page < 1) Page = 1; ReloadPage(); } } + if (PlayerControl.LocalPlayer.IsAlive()) { CreatePage(false, __instance, container); @@ -935,6 +961,7 @@ public static class GuessManager CreateRole(role); } + void CreateRole(CustomRoles role) { if (40 <= i[(int)role.GetCustomRoleTypes()]) i[(int)role.GetCustomRoleTypes()] = 0; @@ -946,10 +973,9 @@ public static class GuessManager TextMeshPro label = Object.Instantiate(textTemplate, button); button.GetComponent().sprite = CustomButton.Get("GuessPlate"); - if (!RoleButtons.ContainsKey(role.GetCustomRoleTypes())) - { - RoleButtons.Add(role.GetCustomRoleTypes(), []); - } + + if (!RoleButtons.ContainsKey(role.GetCustomRoleTypes())) { RoleButtons.Add(role.GetCustomRoleTypes(), []); } + RoleButtons[role.GetCustomRoleTypes()].Add(button); buttons.Add(button); int row = i[(int)role.GetCustomRoleTypes()] / 5; @@ -964,31 +990,34 @@ public static class GuessManager label.autoSizeTextContainer = true; button.GetComponent().OnClick.RemoveAllListeners(); - if (PlayerControl.LocalPlayer.IsAlive()) button.GetComponent().OnClick.AddListener((Action)(() => - { - if (selectedButton != button) + + if (PlayerControl.LocalPlayer.IsAlive()) + button.GetComponent().OnClick.AddListener((Action)(() => { - selectedButton = button; - buttons.ForEach(x => x.GetComponent().color = x == selectedButton ? Utils.GetRoleColor(PlayerControl.LocalPlayer.GetCustomRole()) : Color.white); - } - else - { - if (!(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted) || !PlayerControl.LocalPlayer.IsAlive()) return; + if (selectedButton != button) + { + selectedButton = button; + buttons.ForEach(x => x.GetComponent().color = x == selectedButton ? Utils.GetRoleColor(PlayerControl.LocalPlayer.GetCustomRole()) : Color.white); + } + else + { + if (!(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted) || !PlayerControl.LocalPlayer.IsAlive()) return; - Logger.Msg($"Click: {pc.GetNameWithRole()} => {role}", "Guesser UI"); + Logger.Msg($"Click: {pc.GetNameWithRole()} => {role}", "Guesser UI"); - if (AmongUsClient.Instance.AmHost) GuesserMsg(PlayerControl.LocalPlayer, $"/bt {playerId} {GetString(role.ToString())}", true); - else SendRPC(playerId, role); + if (AmongUsClient.Instance.AmHost) GuesserMsg(PlayerControl.LocalPlayer, $"/bt {playerId} {GetString(role.ToString())}", true); + else SendRPC(playerId, role); - // Reset the GUI - __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(true)); - Object.Destroy(container.gameObject); - textTemplate.enabled = false; + // Reset the GUI + __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(true)); + Object.Destroy(container.gameObject); + textTemplate.enabled = false; + } + })); - } - })); i[(int)role.GetCustomRoleTypes()]++; } + container.transform.localScale *= 0.75f; GuesserSelectRole(CustomRoleTypes.Neutral); ReloadPage(); @@ -1000,7 +1029,6 @@ public static class GuessManager } PlayerControl.LocalPlayer.RPCPlayCustomSound("Gunload"); - } // Modded non-host client guess role/add-on diff --git a/Modules/OptionHolder.cs b/Modules/OptionHolder.cs index 6571b59f3..714919a2e 100644 --- a/Modules/OptionHolder.cs +++ b/Modules/OptionHolder.cs @@ -48,6 +48,14 @@ public static class Options Tasks } + public enum ModLanguages + { + UseGameLanguage, + Hungarian, + Polish, + Indonesian + } + public static Dictionary GroupedOptions = []; public static Dictionary> GroupedAddons = []; @@ -171,7 +179,9 @@ public static class Options "pet_RANDOM_FOR_EVERYONE" ]; - public static float DefaultKillCooldown = Main.NormalOptions == null ? 25 : Main.NormalOptions.KillCooldown; + public static float DefaultKillCooldown = Main.NormalOptions == null ? 25f : Main.NormalOptions.KillCooldown; + + public static OptionItem ModLanguage; public static readonly Dictionary GameStateSettings = []; public static OptionItem MinPlayersForGameStateCommand; @@ -1295,6 +1305,9 @@ public static class Options MainLoadingText = "Building EHR settings"; + ModLanguage = new StringOptionItem(19308, "ModLanguage", Enum.GetNames(), 0, TabGroup.SystemSettings) + .SetHeader(true); + KickLowLevelPlayer = new IntegerOptionItem(19300, "KickLowLevelPlayer", new(0, 100, 1), 0, TabGroup.SystemSettings) .SetValueFormat(OptionFormat.Level) .SetHeader(true); diff --git a/Modules/Translator.cs b/Modules/Translator.cs index 238d1cee3..381a6fca7 100644 --- a/Modules/Translator.cs +++ b/Modules/Translator.cs @@ -14,8 +14,8 @@ namespace EHR; public static class Translator { - public const string LANGUAGE_FOLDER_NAME = "Language"; - public static Dictionary> translateMaps; + private const string LanguageFolderName = "Language"; + private static Dictionary> TranslateMaps; public static void Init() { @@ -34,7 +34,7 @@ public static class Translator var assembly = Assembly.GetExecutingAssembly(); string[] jsonFileNames = GetJsonFileNames(assembly, jsonDirectory); - translateMaps = []; + TranslateMaps = []; if (jsonFileNames.Length == 0) { @@ -61,7 +61,7 @@ public static class Translator jsonDictionary.Remove("LanguageID"); // Handle the rest of the data and merge it into the resulting translation map - MergeJsonIntoTranslationMap(translateMaps, languageId, jsonDictionary); + MergeJsonIntoTranslationMap(TranslateMaps, languageId, jsonDictionary); } else { @@ -72,25 +72,22 @@ public static class Translator } // Convert the resulting translation map to JSON - JsonSerializer.Serialize(translateMaps, new JsonSerializerOptions + JsonSerializer.Serialize(TranslateMaps, new JsonSerializerOptions { WriteIndented = true }); } - catch (Exception ex) - { - Logger.Error($"Error: {ex}", "Translator"); - } + catch (Exception ex) { Logger.Error($"Error: {ex}", "Translator"); } // Loading custom translation files - if (!Directory.Exists(LANGUAGE_FOLDER_NAME)) Directory.CreateDirectory(LANGUAGE_FOLDER_NAME); + if (!Directory.Exists(LanguageFolderName)) Directory.CreateDirectory(LanguageFolderName); // Creating a translation template CreateTemplateFile(); foreach (SupportedLangs lang in Enum.GetValues()) { - if (File.Exists(@$"./{LANGUAGE_FOLDER_NAME}/{lang}.dat")) + if (File.Exists($"./{LanguageFolderName}/{lang}.dat")) { UpdateCustomTranslation($"{lang}.dat" /*, lang*/); LoadCustomTranslation($"{lang}.dat", lang); @@ -104,7 +101,7 @@ public static class Translator { string textString = kvp.Key; - if (kvp.Value is string translation) + if (kvp.Value is { } translation) { // If the textString is not already in the translation map, add it if (!translationMaps.ContainsKey(textString)) translationMaps[textString] = []; @@ -129,6 +126,9 @@ public static class Translator if (Main.ForceOwnLanguage.Value) langId = GetUserTrueLang(); + int modLanguageId = Options.ModLanguage.GetValue(); + if (modLanguageId != 0) langId = (SupportedLangs)(modLanguageId + 100 - 1); + string str = GetString(s, langId); if (replacementDic != null) @@ -138,25 +138,25 @@ public static class Translator return str; } - public static string GetString(string str, SupportedLangs langId) + private static string GetString(string str, SupportedLangs langId) { var res = $""; try { - if (translateMaps.TryGetValue(str, out Dictionary dic) && (!dic.TryGetValue((int)langId, out res) || res == "" || (langId is not SupportedLangs.SChinese and not SupportedLangs.TChinese && Regex.IsMatch(res, @"[\u4e00-\u9fa5]") && res == GetString(str, SupportedLangs.SChinese)))) //strに該当する&無効なlangIdかresが空 + if (TranslateMaps.TryGetValue(str, out Dictionary dic) && (!dic.TryGetValue((int)langId, out res) || res == "" || (langId is not SupportedLangs.SChinese and not SupportedLangs.TChinese && Regex.IsMatch(res, @"[\u4e00-\u9fa5]") && res == GetString(str, SupportedLangs.SChinese)))) res = langId == SupportedLangs.English ? $"*{str}" : GetString(str, SupportedLangs.English); - if (!translateMaps.ContainsKey(str)) //translateMapsにない場合、StringNamesにあれば取得する + if (!TranslateMaps.ContainsKey(str)) { StringNames[] stringNames = Enum.GetValues().Where(x => x.ToString() == str).ToArray(); if (stringNames.Length > 0) res = GetString(stringNames.FirstOrDefault()); } } - catch (Exception Ex) + catch (Exception ex) { Logger.Fatal($"Error oucured at [{str}] in String.csv", "Translator"); - Logger.Error("Here was the error:\n" + Ex, "Translator"); + Logger.Error("Here was the error:\n" + ex, "Translator"); } return res; @@ -169,8 +169,8 @@ public static class Translator public static string GetRoleString(string str, bool forUser = true) { - SupportedLangs CurrentLanguage = TranslationController.Instance.currentLanguage.languageID; - SupportedLangs lang = forUser ? CurrentLanguage : SupportedLangs.English; + SupportedLangs currentLanguage = TranslationController.Instance.currentLanguage.languageID; + SupportedLangs lang = forUser ? currentLanguage : SupportedLangs.English; if (Main.ForceOwnLanguageRoleName.Value) lang = GetUserTrueLang(); return GetString(str, lang); @@ -182,24 +182,17 @@ public static class Translator { string name = CultureInfo.CurrentUICulture.Name; if (name.StartsWith("en")) return SupportedLangs.English; - if (name.StartsWith("zh_CHT")) return SupportedLangs.TChinese; - if (name.StartsWith("zh")) return SupportedLangs.SChinese; - if (name.StartsWith("ru")) return SupportedLangs.Russian; - return TranslationController.Instance.currentLanguage.languageID; } - catch - { - return SupportedLangs.English; - } + catch { return SupportedLangs.English; } } private static void UpdateCustomTranslation(string filename /*, SupportedLangs lang*/) { - var path = @$"./{LANGUAGE_FOLDER_NAME}/{filename}"; + var path = $"./{LanguageFolderName}/{filename}"; if (File.Exists(path)) { @@ -211,9 +204,7 @@ public static class Translator using (StreamReader reader = new(path, Encoding.GetEncoding("UTF-8"))) { - string line; - - while ((line = reader.ReadLine()) != null) + while (reader.ReadLine() is { } line) { // Split the line by ':' to get the first part string[] parts = line.Split(':'); @@ -230,7 +221,7 @@ public static class Translator var sb = new StringBuilder(); - foreach (string templateString in translateMaps.Keys) + foreach (string templateString in TranslateMaps.Keys) if (!textStrings.Contains(templateString)) sb.Append($"{templateString}:\n"); @@ -238,49 +229,35 @@ public static class Translator using StreamWriter writer = new(fileStream); writer.WriteLine(sb.ToString()); } - catch (Exception e) - { - Logger.Error("An error occurred: " + e.Message, "Translator"); - } + catch (Exception e) { Logger.Error("An error occurred: " + e.Message, "Translator"); } } } - public static void LoadCustomTranslation(string filename, SupportedLangs lang) + private static void LoadCustomTranslation(string filename, SupportedLangs lang) { - var path = @$"./{LANGUAGE_FOLDER_NAME}/{filename}"; + var path = $"./{LanguageFolderName}/{filename}"; if (File.Exists(path)) { - Logger.Info($"Loading Custom Translation File:{filename}", "LoadCustomTranslation"); + Logger.Info($"Loading Custom Translation File: {filename}", "LoadCustomTranslation"); try { using StreamReader sr = new(path, Encoding.GetEncoding("UTF-8")); - string text; - string[] tmp = []; - while ((text = sr.ReadLine()) != null) + while (sr.ReadLine() is { } text) { - tmp = text.Split(":"); + string[] tmp = text.Split(":"); if (tmp.Length > 1 && tmp[1] != "") { - try - { - translateMaps[tmp[0]][(int)lang] = tmp.Skip(1).Join(delimiter: ":").Replace("\\n", "\n").Replace("\\r", "\r"); - } - catch (KeyNotFoundException) - { - Logger.Warn($"Invalid Key:{tmp[0]}", "LoadCustomTranslation"); - } + try { TranslateMaps[tmp[0]][(int)lang] = tmp.Skip(1).Join(delimiter: ":").Replace("\\n", "\n").Replace("\\r", "\r"); } + catch (KeyNotFoundException) { Logger.Warn($"Invalid Key:{tmp[0]}", "LoadCustomTranslation"); } } } } catch (ObjectDisposedException) { } - catch (Exception e) - { - Logger.Error(e.ToString(), "Translator.LoadCustomTranslation"); - } + catch (Exception e) { Logger.Error(e.ToString(), "Translator.LoadCustomTranslation"); } } else Logger.Error($"Custom Translation File Not Found:{filename}", "LoadCustomTranslation"); @@ -289,9 +266,9 @@ public static class Translator private static void CreateTemplateFile() { var sb = new StringBuilder(); - foreach (KeyValuePair> title in translateMaps) sb.Append($"{title.Key}:\n"); + foreach (KeyValuePair> title in TranslateMaps) sb.Append($"{title.Key}:\n"); - File.WriteAllText(@$"./{LANGUAGE_FOLDER_NAME}/template.dat", sb.ToString()); + File.WriteAllText($"./{LanguageFolderName}/template.dat", sb.ToString()); } public static void ExportCustomTranslation() @@ -300,12 +277,12 @@ public static class Translator var sb = new StringBuilder(); SupportedLangs lang = TranslationController.Instance.currentLanguage.languageID; - foreach (KeyValuePair> title in translateMaps) + foreach (KeyValuePair> title in TranslateMaps) { string text = title.Value.GetValueOrDefault((int)lang, ""); sb.Append($"{title.Key}:{text.Replace("\n", "\\n").Replace("\r", "\\r")}\n"); } - File.WriteAllText(@$"./{LANGUAGE_FOLDER_NAME}/export_{lang}.dat", sb.ToString()); + File.WriteAllText($"./{LanguageFolderName}/export_{lang}.dat", sb.ToString()); } } \ No newline at end of file diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index de2f2c624..9d19fa1c5 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -1036,6 +1036,7 @@ internal static class ReportDeadBodyPatch } Options.UsedButtonCount++; + if (Math.Abs(Options.SyncedButtonCount.GetFloat() - Options.UsedButtonCount) < 0.5f) Logger.Info("This was the last allowed emergency meeting", "ReportDeadBody"); } @@ -1045,7 +1046,7 @@ internal static class ReportDeadBodyPatch catch (Exception e) { ThrowException(e); } return true; - + void Notify(string str) => __instance.Notify(ColorString(Color.yellow, GetString("CheckReportFail") + GetString(str)), 15f); } @@ -2222,13 +2223,13 @@ internal static class PlayerControlSetRolePatch if (roleType is RoleTypes.CrewmateGhost or RoleTypes.ImpostorGhost) { - bool targetIsKiller = __instance.Is(CustomRoleTypes.Impostor) || Main.ResetCamPlayerList.Contains(__instance.PlayerId); + bool targetIsKiller = __instance.Is(CustomRoleTypes.Impostor) || __instance.HasDesyncRole(); Dictionary ghostRoles = new(); foreach (PlayerControl seer in Main.AllPlayerControls) { bool self = seer.PlayerId == __instance.PlayerId; - bool seerIsKiller = seer.Is(CustomRoleTypes.Impostor) || Main.ResetCamPlayerList.Contains(seer.PlayerId); + bool seerIsKiller = seer.Is(CustomRoleTypes.Impostor) || seer.HasDesyncRole(); if (__instance.HasGhostRole()) ghostRoles[seer] = RoleTypes.GuardianAngel; diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index 4391221b5..639cc1979 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -5687,5 +5687,9 @@ "UpReplacedMessage": "/up was replaced by /setrole which allows you to set anyone's role for any game by typing '/setrole (ID) (ROLE)'. You can view ID's with /id.\nTo set your own role like with /up, you need to do '/setrole 0 (ROLE)'.", "PingText": "Ping", "SettingsForRoleText": "Settings for", + "UseGameLanguage": "Use Game Language", + "Hungarian": "Hungarian", + "Polish": "Polish", + "Indonesian": "Indonesian", "NotAssigned": "-" } diff --git a/Roles/Crewmate/Spy.cs b/Roles/Crewmate/Spy.cs index 9824398aa..a08361d77 100644 --- a/Roles/Crewmate/Spy.cs +++ b/Roles/Crewmate/Spy.cs @@ -110,6 +110,7 @@ public class Spy : RoleBase SpyRedNameList.TryAdd(killer.PlayerId, TimeStamp); SendRPC(1, killer.PlayerId); NotifyRoles(SpecifySeer: target, SpecifyTarget: killer); + killer.SetKillCooldown(); return false; } diff --git a/Roles/Impostor/Swooper.cs b/Roles/Impostor/Swooper.cs index ae25d17e4..149cb2c80 100644 --- a/Roles/Impostor/Swooper.cs +++ b/Roles/Impostor/Swooper.cs @@ -20,8 +20,8 @@ public class Swooper : RoleBase private static OptionItem SwooperVentNormallyOnCooldown; private static OptionItem SwooperLimitOpt; public static OptionItem SwooperAbilityUseGainWithEachKill; - private int CD; + private int CD; private float Cooldown; private int Count; @@ -193,13 +193,11 @@ public class Swooper : RoleBase { case < 0: lastTime = now; - Vector2 pos = player.Pos(); - player.MyPhysics?.RpcBootFromVent(ventedId == -10 ? Main.LastEnteredVent[player.PlayerId].Id : ventedId); + Main.AllPlayerControls.Without(player).Do(x => player.MyPhysics.RpcExitVentDesync(ventedId == -10 ? Main.LastEnteredVent[player.PlayerId].Id : ventedId, x)); player.Notify(GetString("SwooperInvisStateOut")); InvisTime = -10; SendRPC(); refresh = true; - LateTask.New(() => player.TP(pos), 0.5f, log: false); break; case <= 10 when !player.IsModClient(): player.Notify(string.Format(GetString("SwooperInvisStateCountdown"), remainTime + 1), overrideAll: true); @@ -223,12 +221,9 @@ public class Swooper : RoleBase if (CanGoInvis && (wraith || limit >= 1)) { + __instance.RpcExitVentDesync(ventId, pc); + ventedId = ventId; - - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(__instance.NetId, 34, SendOption.Reliable, pc.GetClientId()); - writer.WritePacked(ventId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - InvisTime = Utils.TimeStamp; if (!wraith) pc.RpcRemoveAbilityUse();