diff --git a/AmongUsRevamped.cs b/AmongUsRevamped.cs index 32c0555..4b74c1e 100644 --- a/AmongUsRevamped.cs +++ b/AmongUsRevamped.cs @@ -35,6 +35,7 @@ public partial class Main : BasePlugin public static ConfigEntry DarkTheme { get; private set; } public static ConfigEntry LobbyMusic { get; private set; } public static ConfigEntry DisableInfoWhenDead { get; private set; } + public static ConfigEntry DisableCommandHelper { get; private set; } public static NormalGameOptionsV10 NormalOptions => GameOptionsManager.Instance != null ? GameOptionsManager.Instance.currentNormalGameOptions : null; public static HideNSeekGameOptionsV10 HideNSeekOptions => GameOptionsManager.Instance != null ? GameOptionsManager.Instance.currentHideNSeekGameOptions : null; @@ -42,7 +43,7 @@ public partial class Main : BasePlugin public static bool HasArgumentException; public static string CredentialsText; - public const string ModVersion = "v1.7.4"; + public const string ModVersion = "v1.7.5"; public static float GameTimer; @@ -90,8 +91,10 @@ public partial class Main : BasePlugin DarkTheme = Config.Bind("Client Options", "Dark Theme", false); LobbyMusic = Config.Bind("Client Options", "Lobby Music", false); DisableInfoWhenDead = Config.Bind("Client Options", "Disable Task/Kill View", false); + DisableCommandHelper = Config.Bind("Client Options", "Disable Command Helper", false); Translator.Init(); + Translator.Reload(); BanManager.Init(); Harmony.PatchAll(); diff --git a/Modules/BanManager.cs b/Modules/BanManager.cs index 8a1da27..5da5d39 100644 --- a/Modules/BanManager.cs +++ b/Modules/BanManager.cs @@ -23,9 +23,9 @@ public static class BanManager private static readonly string DenyNameListPath = $"{DataPath}/AUR-DATA/Deniednames.txt"; private static string BanListPath = $"{DataPath}/AUR-DATA/Banlist.txt"; private static string BanWordPath = $"{DataPath}/AUR-DATA/Deniedwords.txt"; - private static string VipListPath = $"{DataPath}/AUR-DATA/VIP.txt"; - private static string ModeratorListPath = $"{DataPath}/AUR-DATA/Moderator.txt"; - private static string AdminListPath = $"{DataPath}/AUR-DATA/Admin.txt"; + public static string VipListPath = $"{DataPath}/AUR-DATA/VIP.txt"; + public static string ModeratorListPath = $"{DataPath}/AUR-DATA/Moderator.txt"; + public static string AdminListPath = $"{DataPath}/AUR-DATA/Admin.txt"; private static string TemplatePath = $"{DataPath}/AUR-DATA/Templates.txt"; public static Dictionary Templates = new(); public static List TempBanWhiteList = []; @@ -233,4 +233,19 @@ public static class BanManager Logger.Exception(ex, "BanManager"); } } + + public static string CheckTemplate(string text) + { + Dictionary variables = new() + { + { "ModVersion", Main.ModVersion } + }; + + foreach (var kvp in variables) + { + text = text.Replace($"{{{kvp.Key}}}", kvp.Value); + } + + return text; + } } diff --git a/Modules/CommandHelper.cs b/Modules/CommandHelper.cs new file mode 100644 index 0000000..c2f71fd --- /dev/null +++ b/Modules/CommandHelper.cs @@ -0,0 +1,156 @@ +using InnerNet; +using System; +using System.IO; +using UnityEngine; +using UnityEngine.UI; +using TMPro; + +namespace AmongUsRevamped; + +[HarmonyPatch(typeof(TextBoxTMP), nameof(TextBoxTMP.SetText))] +internal static class CommandHelper +{ + private static TextMeshPro HelperText; + + public class Cmd + { + public string[] Name; + public string Prompt; + public string Description; + public bool HasVariable; + } + + static readonly List Commands = new() + { + new Cmd { Name = new[] { "/help" }, Prompt = "/help", Description = Translator.Get("helpDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/sns" }, Prompt = "/sns", Description = Translator.Get("snsDesc"), HasVariable = false }, + new Cmd { Name = new[] { "/shiftandseek" }, Prompt = "/shiftandseek", Description = Translator.Get("snsDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/0kc" }, Prompt = "/0kc", Description = Translator.Get("0kcDesc"), HasVariable = false }, + new Cmd { Name = new[] { "/0killcooldown" }, Prompt = "/0killcooldown", Description = Translator.Get("0kcDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/sr" }, Prompt = "/sr", Description = Translator.Get("SrDesc"), HasVariable = false }, + new Cmd { Name = new[] { "/speedrun" }, Prompt = "/speedrun", Description = Translator.Get("SrDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/eg" }, Prompt = "/eg", Description = Translator.Get("egDesc"), HasVariable = false }, + new Cmd { Name = new[] { "/endgame" }, Prompt = "/endgame", Description = Translator.Get("egDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/em" }, Prompt = "/em", Description = Translator.Get("emDesc"), HasVariable = false }, + new Cmd { Name = new[] { "/endmeeting" }, Prompt = "/endmeeting", Description = Translator.Get("emDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/aur" }, Prompt = "/aur", Description = Translator.Get("aurDesc"), HasVariable = false }, + new Cmd { Name = new[] { "/socials" }, Prompt = "/socials", Description = Translator.Get("aurDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/s" }, Prompt = "/s", Description = Translator.Get("sDesc"), HasVariable = false }, + new Cmd { Name = new[] { "/start" }, Prompt = "/start", Description = Translator.Get("sDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/r" }, Prompt = "/r {role}", Description = Translator.Get("rDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/roles" }, Prompt = "/roles", Description = Translator.Get("rolesDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/kick" }, Prompt = "/kick {name}", Description = Translator.Get("kickDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/ckick" }, Prompt = "/ckick {color}", Description = Translator.Get("ckickDesc"), HasVariable = true }, + + new Cmd { Name = new[] { "/ban" }, Prompt = "/ban {name}", Description = Translator.Get("banDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/cban" }, Prompt = "/cban {color}", Description = Translator.Get("cbanDesc"), HasVariable = true }, + + new Cmd { Name = new[] { "/dump" }, Prompt = "/dump", Description = Translator.Get("dumpDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/col" }, Prompt = "/col {color}", Description = Translator.Get("colDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/color" }, Prompt = "/color {color}", Description = Translator.Get("colDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/colour" }, Prompt = "/colour {color}", Description = Translator.Get("colDesc"), HasVariable = true }, + + new Cmd { Name = new[] { "/reload" }, Prompt = "/reload", Description = Translator.Get("reloadDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/vip" }, Prompt = "/vip {name}", Description = Translator.Get("vipDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/moderator" }, Prompt = "/moderator {name}", Description = Translator.Get("moderatorDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/admin" }, Prompt = "/admin {name}", Description = Translator.Get("adminDesc"), HasVariable = true }, + + new Cmd { Name = new[] { "/removevip" }, Prompt = "/removevip {name}", Description = Translator.Get("cremoveVipDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/removemoderator" }, Prompt = "/removemoderator {name}", Description = Translator.Get("removeModeratorDesc"), HasVariable = true }, + new Cmd { Name = new[] { "/removeadmin" }, Prompt = "/removeadmin {name}", Description = Translator.Get("removeAdminDesc"), HasVariable = true }, + + new Cmd { Name = new[] { "/lastgame" }, Prompt = "/lastgame", Description = Translator.Get("lastgameDesc"), HasVariable = false }, + + new Cmd { Name = new[] { "/t" }, Prompt = "/t {template}", Description = Translator.Get("templateDesc"), HasVariable = true } + }; + + [HarmonyPostfix] + public static void Postfix(TextBoxTMP __instance) + { + if (!HudManager.InstanceExists || HudManager.Instance.Chat == null || HudManager.Instance.Chat.freeChatField == null || __instance != HudManager.Instance.Chat.freeChatField.textArea) return; + + if (Main.DisableCommandHelper.Value) + { + HelperText.enabled = false; + return; + } + + if (!HelperText) + { + HelperText = Object.Instantiate(__instance.outputText, __instance.outputText.transform.parent); + HelperText.name = "HelperText"; + HelperText.color = new Color(0.7f, 0.7f, 0.7f, 0.7f); + HelperText.transform.localPosition = __instance.outputText.transform.localPosition; + HelperText.enabled = false; + } + + string t = __instance.text; + + if (string.IsNullOrEmpty(t) || !t.StartsWith("/")) + { + HelperText.enabled = false; + return; + } + + string textCmd = t.Split(' ')[0]; + + Cmd u = null; + Cmd v = null; + + foreach (var cmd in Commands) + { + foreach (var a in cmd.Name) + { + string aliasCmd = a; + + if (aliasCmd.Equals(textCmd)) + { + v = cmd; + u = cmd; + break; + } + + if (aliasCmd.StartsWith(textCmd)) + { + u ??= cmd; + } + } + + if (v != null) break; + } + + if (v != null && !v.HasVariable && t.Length > textCmd.Length) + { + HelperText.enabled = false; + return; + } + + __instance.outputText.enabled = true; + + if (v != null && textCmd.Equals(v.Name[0])) + { + HelperText.text = $"\n\n{v.Description}"; + } + else if (u != null) + { + HelperText.text = u.Prompt; + } + else + { + HelperText.enabled = false; + return; + } + HelperText.enabled = true; + } +} \ No newline at end of file diff --git a/Modules/CustomOptionsHolder.cs b/Modules/CustomOptionsHolder.cs index 0824343..a6a84e6 100644 --- a/Modules/CustomOptionsHolder.cs +++ b/Modules/CustomOptionsHolder.cs @@ -58,7 +58,7 @@ namespace AmongUsRevamped public static readonly string[] crewmateAbilities = { - "Mayor", "Workhorse", "Jester", "Speedrunner", "None" + "Mayor", "Workhorse", "Jester", "Tasker", "None" }; public static readonly string[] impostorAbilities = { @@ -89,6 +89,8 @@ namespace AmongUsRevamped public static OptionItem AutoStartTimer; public static OptionItem WaitAutoStart; public static OptionItem PlayerAutoStart; + public static OptionItem EnableJoinMessages; + public static OptionItem MessagePerPlayerNum; public static OptionItem TabGroupMisc; @@ -259,11 +261,6 @@ namespace AmongUsRevamped public static OptionItem DisableSubmitScan; public static OptionItem DisableUploadData; - // Gamemode -/* - public static OptionItem TabGroupStandard; - public static OptionItem ChatBeforeFirstMeeting; -*/ public static OptionItem TabGroupHNS; public static OptionItem NumSeekers; @@ -383,6 +380,9 @@ namespace AmongUsRevamped WaitAutoStart = IntegerOptionItem.Create(64421, Translator.Get("waitAutoStart"), new(10, 600, 10), 300, TabGroup.SystemSettings, false) .SetValueFormat(OptionFormat.Seconds); PlayerAutoStart = IntegerOptionItem.Create(64422, Translator.Get("playerAutoStart"), new(1, 15, 1), 1, TabGroup.SystemSettings, false); + EnableJoinMessages = BooleanOptionItem.Create(64423, Translator.Get("enableJoinMessages"), true, TabGroup.SystemSettings, false); + MessagePerPlayerNum = IntegerOptionItem.Create(64424, Translator.Get("messagePerPlayerNum"), new(1, 15, 1), 5, TabGroup.SystemSettings, false) + .SetParent(EnableJoinMessages); TabGroupMisc = TextOptionItem.Create(60379, Translator.Get("tabGroupMisc"), TabGroup.SystemSettings) .SetColor(Color.green); diff --git a/Modules/CustomRoleManagement.cs b/Modules/CustomRoleManagement.cs index 6e1337b..918a09b 100644 --- a/Modules/CustomRoleManagement.cs +++ b/Modules/CustomRoleManagement.cs @@ -104,31 +104,31 @@ public static class AbilityManagement public static string RoleList() { - var firstLines = new List(); + if (!AmongUsClient.Instance.AmHost) return ""; - if (Options.CrewmateAbility.GetValue() != 4) firstLines.Add($"Crewmate: {Options.CrewmateAbility.GetString()}"); - if (Options.ScientistAbility.GetValue() != 4) firstLines.Add($"Scientist: {Options.ScientistAbility.GetString()}"); - if (Options.EngineerAbility.GetValue() != 4) firstLines.Add($"Engineer: {Options.EngineerAbility.GetString()}"); - if (Options.NoisemakerAbility.GetValue() != 4) firstLines.Add($"Noisemaker: {Options.NoisemakerAbility.GetString()}"); - if (Options.TrackerAbility.GetValue() != 4) firstLines.Add($"Tracker: {Options.TrackerAbility.GetString()}"); + var lines = new List(); - var secondLines = new List(); + if (Options.CrewmateAbility.GetValue() != 4) lines.Add($"Crewmate: {Options.CrewmateAbility.GetString()}"); + if (Options.ScientistAbility.GetValue() != 4) lines.Add($"Scientist: {Options.ScientistAbility.GetString()}"); + if (Options.EngineerAbility.GetValue() != 4) lines.Add($"Engineer: {Options.EngineerAbility.GetString()}"); + if (Options.NoisemakerAbility.GetValue() != 4) lines.Add($"Noisemaker: {Options.NoisemakerAbility.GetString()}"); + if (Options.TrackerAbility.GetValue() != 4) lines.Add($"Tracker: {Options.TrackerAbility.GetString()}"); + if (Options.DetectiveAbility.GetValue() != 4) lines.Add($"Detective: {Options.DetectiveAbility.GetString()}"); - if (Options.DetectiveAbility.GetValue() != 4) secondLines.Add($"Detective: {Options.DetectiveAbility.GetString()}"); - if (Options.ImpostorAbility.GetValue() != 3) secondLines.Add($"Impostor: {Options.ImpostorAbility.GetString()}"); - if (Options.ShapeshifterAbility.GetValue() != 3) secondLines.Add($"Shapeshifter: {Options.ShapeshifterAbility.GetString()}"); - if (Options.PhantomAbility.GetValue() != 3) secondLines.Add($"Phantom: {Options.PhantomAbility.GetString()}"); - if (Options.ViperAbility.GetValue() != 3) secondLines.Add($"Viper: {Options.ViperAbility.GetString()}"); + if (Options.ImpostorAbility.GetValue() != 3) lines.Add($"Impostor: {Options.ImpostorAbility.GetString()}"); + if (Options.ShapeshifterAbility.GetValue() != 3) lines.Add($"Shapeshifter: {Options.ShapeshifterAbility.GetString()}"); + if (Options.PhantomAbility.GetValue() != 3) lines.Add($"Phantom: {Options.PhantomAbility.GetString()}"); + if (Options.ViperAbility.GetValue() != 3) lines.Add($"Viper: {Options.ViperAbility.GetString()}"); - string firstText = firstLines.Count > 0 ? "ABILITIES:\n\n" + string.Join("\n", firstLines) : ""; - string secondText = secondLines.Count > 0 ? "\n" + string.Join("\n", secondLines) : ""; + if (lines.Count == 0) return ""; - return firstText + secondText; + return "ABILITIES:\n\n" + string.Join("\n", lines); } public static void SendRoleList(ChatController c, string text, bool moderator) { - if (string.IsNullOrEmpty(AbilityManagement.RoleList())) return; + if (!AmongUsClient.Instance.AmHost) return; + if (string.IsNullOrEmpty(RoleList()) || Utils.isHideNSeek) return; if (text.Length <= 120) { @@ -147,6 +147,75 @@ public static class AbilityManagement if (moderator) Utils.ModeratorChatCommand(first, second, true); else Utils.ChatCommand(c, first, second, true); } + + public static string RoleInfoString(PlayerControl player) + { + if (!AmongUsClient.Instance.AmHost) return ""; + if (IsMayor(player)) return Translator.Get("youAreMayor", Options.ExtraVotesCrewmate.GetInt()); + if (IsWorkhorse(player)) return Translator.Get("youAreWorkhorse", Options.ExtraVotesPerTask.GetFloat()); + if (IsJester(player)) return Translator.Get("youAreJester"); + if (IsSpeedrunner(player)) return Translator.Get("youAreSpeedrunner"); + if (IsTyrant(player)) return Translator.Get("youAreTyrant", Options.ExtraVotesImpostor.GetInt()); + if (IsStealer(player)) return Translator.Get("youAreStealer", Options.ExtraVotesPerKill.GetFloat()); + if (IsJuggernaut(player)) return Translator.Get("youAreJuggernaut", Options.KillsNeededForJuggernaut.GetInt()); + else return ""; + } + + public static bool HandlingRoleMessages = false; + private static int PendingRoleMessages = 0; + public static void SendRoleMessages() + { + if (!AmongUsClient.Instance.AmHost) return; + + if (string.IsNullOrEmpty(RoleList()) || PlayerControl.LocalPlayer.Data.IsDead) + { + HandlingRoleMessages = false; + PendingRoleMessages = 0; + return; + } + + var players = PlayerControl.AllPlayerControls.ToArray().ToList(); + float delay = 4.4f; + + PendingRoleMessages = 0; + HandlingRoleMessages = true; + + SendRoleList(DestroyableSingleton.Instance.Chat, AbilityManagement.RoleList(), false); + + foreach (var player in players) + { + if (string.IsNullOrEmpty(RoleInfoString(player))) continue; + + PendingRoleMessages++; + + new LateTask(() => + { + if (Utils.InGame) + { + Utils.SendPrivateMessage(player, RoleInfoString(player)); + } + else + { + Logger.Info("Role sending was forcefully canceled. This should not happen.", "SendRoleMessages"); + } + + PendingRoleMessages--; + + if (PendingRoleMessages <= 0) + { + PendingRoleMessages = 0; + HandlingRoleMessages = false; + } + }, delay, "SendRoleMessage"); + + delay += 2.2f; + } + + if (PendingRoleMessages == 0) + { + HandlingRoleMessages = false; + } + } } /* public static class CustomRoleManagement diff --git a/Modules/FixedUpdate.cs b/Modules/FixedUpdate.cs index 46dad28..b4d67b1 100644 --- a/Modules/FixedUpdate.cs +++ b/Modules/FixedUpdate.cs @@ -92,8 +92,6 @@ class FixedUpdateInGamePatch break; case 3: // Speedrun - if (settingsLabel == null) - Main.NormalOptions.TaskBarMode = 0; break; case 0: // Reset diff --git a/Modules/Utils.cs b/Modules/Utils.cs index a0aef15..b2c2f8e 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -216,7 +216,7 @@ public static class Utils NormalGameEndChecker.ImpCheckComplete = false; CreateOptionsPickerPatch.SetDleks2 = false; CanCallMeetings = true; - //CustomRoleManagement.HandlingRoleMessages = false; + AbilityManagement.HandlingRoleMessages = false; PlayerControlSetRolePatch.FirstAssign = true; PlayerControlSetRolePatch.Jesters.Clear(); @@ -226,6 +226,8 @@ public static class Utils PlayerControlCompleteTaskPatch.ignoredCompletedTasks = 0; PlayerControlCompleteTaskPatch.ignoredTasks = 0; + OnPlayerJoinedPatch.JoinNum = 0; + } public static PlayerControl[] AllAlivePlayerControls @@ -376,6 +378,8 @@ public static class Utils public static void ChatCommand(ChatController __instance, string msg, string msg2, bool multi) { + if (OnGameJoinedPatch.WaitingForChat) return; + OnGameJoinedPatch.WaitingForChat = true; __instance.freeChatField.textArea.Clear(); @@ -406,6 +410,8 @@ public static class Utils public static void ModeratorChatCommand(string msg, string msg2, bool multi) { + if (OnGameJoinedPatch.WaitingForChat) return; + OnGameJoinedPatch.WaitingForChat = true; new LateTask(() => @@ -574,7 +580,7 @@ public static class Utils { if (p == null) return ""; - if (p.Data.RoleType == RoleTypes.Impostor || p.Data.RoleType == RoleTypes.Shapeshifter || p.Data.RoleType == RoleTypes.Phantom || p.Data.RoleType == RoleTypes.Viper) + if (p.Data.RoleType == RoleTypes.Impostor || p.Data.RoleType == RoleTypes.Shapeshifter || p.Data.RoleType == RoleTypes.Phantom || p.Data.RoleType == RoleTypes.Viper || p.Data.RoleType == RoleTypes.ImpostorGhost) { return $"{p.Data.RoleType}"; } diff --git a/Patches/ChatPatches.cs b/Patches/ChatPatches.cs index 5bcaab0..8c73b9d 100644 --- a/Patches/ChatPatches.cs +++ b/Patches/ChatPatches.cs @@ -1,6 +1,7 @@ ๏ปฟusing Hazel; using InnerNet; using System; +using System.IO; using UnityEngine; using UnityEngine.UI; using TMPro; @@ -107,7 +108,7 @@ internal static class SendChatPatch __instance.freeChatField.textArea.SetText(string.Empty); return false; } - if (text == "/h" || text == "/help") + if (text == "/help") { HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, $"{Translator.Get("allCommandsFull")}"); __instance.freeChatField.textArea.Clear(); @@ -118,6 +119,8 @@ internal static class SendChatPatch if (text == "/s" || text == "/start") { GameStartManager.Instance.BeginGame(); + __instance.freeChatField.textArea.Clear(); + __instance.freeChatField.textArea.SetText(string.Empty); return false; } @@ -143,9 +146,186 @@ internal static class SendChatPatch return false; } - if (__instance.timeSinceLastMessage < 3f || OnGameJoinedPatch.WaitingForChat /*|| CustomRoleManagement.HandlingRoleMessages*/) return false; + if (text.StartsWith("/vip ")) + { + PlayerControl target = null; + string arg = text.Substring(5).Trim(); - if (text == "/l" || text == "/lastgame" || text == "/win" || text == "/winner") + foreach (PlayerControl p in PlayerControl.AllPlayerControls) + { + if (p.Data == null || p == PlayerControl.LocalPlayer) continue; + + if (p.Data.PlayerName.Equals(arg, StringComparison.OrdinalIgnoreCase)) + { + target = p; + break; + } + } + if (target == null) + { + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("permFail", arg)); + } + else + { + File.AppendAllText(BanManager.VipListPath, "\n" + target.Data.FriendCode); + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("vipAdd", target.Data.PlayerName)); + } + + __instance.freeChatField.textArea.Clear(); + __instance.freeChatField.textArea.SetText(string.Empty); + return false; + } + + if (text.StartsWith("/moderator ")) + { + PlayerControl target = null; + string arg = text.Substring(11).Trim(); + + foreach (PlayerControl p in PlayerControl.AllPlayerControls) + { + if (p.Data == null || p == PlayerControl.LocalPlayer) continue; + + if (p.Data.PlayerName.Equals(arg, StringComparison.OrdinalIgnoreCase)) + { + target = p; + break; + } + } + if (target == null) + { + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("permFail", arg)); + } + else + { + File.AppendAllText(BanManager.ModeratorListPath, "\n" + target.Data.FriendCode); + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("moderatorAdd", target.Data.PlayerName)); + } + + __instance.freeChatField.textArea.Clear(); + __instance.freeChatField.textArea.SetText(string.Empty); + return false; + } + + if (text.StartsWith("/admin ")) + { + PlayerControl target = null; + string arg = text.Substring(7).Trim(); + + foreach (PlayerControl p in PlayerControl.AllPlayerControls) + { + if (p.Data == null || p == PlayerControl.LocalPlayer) continue; + + if (p.Data.PlayerName.Equals(arg, StringComparison.OrdinalIgnoreCase)) + { + target = p; + break; + } + } + if (target == null) + { + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("permFail", arg)); + } + else + { + File.AppendAllText(BanManager.AdminListPath, "\n" + target.Data.FriendCode); + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("adminAdd", target.Data.PlayerName)); + } + + __instance.freeChatField.textArea.Clear(); + __instance.freeChatField.textArea.SetText(string.Empty); + return false; + } + + if (text.StartsWith("/removevip ")) + { + PlayerControl target = null; + string arg = text.Substring(11).Trim(); + + foreach (PlayerControl p in PlayerControl.AllPlayerControls) + { + if (p.Data == null || p == PlayerControl.LocalPlayer) continue; + + if (p.Data.PlayerName.Equals(arg, StringComparison.OrdinalIgnoreCase)) + { + target = p; + break; + } + } + if (target == null) + { + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("permFail", arg)); + } + else + { + File.WriteAllLines(BanManager.VipListPath, File.ReadAllLines(BanManager.VipListPath).Where(x => x.Trim() != target.Data.FriendCode)); + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("vipRemove", target.Data.PlayerName)); + } + __instance.freeChatField.textArea.Clear(); + __instance.freeChatField.textArea.SetText(string.Empty); + return false; + } + + if (text.StartsWith("/removemoderator ")) + { + PlayerControl target = null; + string arg = text.Substring(17).Trim(); + + foreach (PlayerControl p in PlayerControl.AllPlayerControls) + { + if (p.Data == null || p == PlayerControl.LocalPlayer) continue; + + if (p.Data.PlayerName.Equals(arg, StringComparison.OrdinalIgnoreCase)) + { + target = p; + break; + } + } + if (target == null) + { + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("permFail", arg)); + } + else + { + File.WriteAllLines(BanManager.ModeratorListPath, File.ReadAllLines(BanManager.ModeratorListPath).Where(x => x.Trim() != target.Data.FriendCode)); + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("moderatorRemove", target.Data.PlayerName)); + } + __instance.freeChatField.textArea.Clear(); + __instance.freeChatField.textArea.SetText(string.Empty); + return false; + } + + if (text.StartsWith("/removeadmin ")) + { + PlayerControl target = null; + string arg = text.Substring(13).Trim(); + + foreach (PlayerControl p in PlayerControl.AllPlayerControls) + { + if (p.Data == null || p == PlayerControl.LocalPlayer) continue; + + if (p.Data.PlayerName.Equals(arg, StringComparison.OrdinalIgnoreCase)) + { + target = p; + break; + } + } + if (target == null) + { + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("permFail", arg)); + } + else + { + File.WriteAllLines(BanManager.AdminListPath, File.ReadAllLines(BanManager.AdminListPath).Where(x => x.Trim() != target.Data.FriendCode)); + HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("adminRemove", target.Data.PlayerName)); + } + __instance.freeChatField.textArea.Clear(); + __instance.freeChatField.textArea.SetText(string.Empty); + return false; + } + + if (__instance.timeSinceLastMessage < 3f || OnGameJoinedPatch.WaitingForChat || AbilityManagement.HandlingRoleMessages) return false; + + if (text == "/l" || text == "/lastgame") { if (string.IsNullOrEmpty(NormalGameEndChecker.LastWinReason) || Utils.InGame) return false; Utils.ChatCommand(__instance, $"{NormalGameEndChecker.LastWinReason}", "", false); @@ -175,11 +355,11 @@ internal static class SendChatPatch Utils.ChatCommand(__instance, Translator.Get("juggernautPublic", Options.KillsNeededForJuggernaut.GetInt()), "", false); return false;} - if (text == "/r speedrunner"){ + if (text == "/r tasker"){ Utils.ChatCommand(__instance, Translator.Get("speedrunnerPublic"), "", false); return false;} - if (text == "/aur" || text == "/amongusrevamped" || text == "/socials") + if (text == "/aur" || text == "/socials") { Utils.ChatCommand(__instance, Translator.Get("socialsAll"), "", false); return false; @@ -197,13 +377,13 @@ internal static class SendChatPatch return false; } - if (text == "/sp" || text == "/sr" || text == "/speedrun") + if (text == "/sr" || text == "/speedrun") { Utils.ChatCommand(__instance, Translator.Get("speedrunMode", Options.GameAutoEndsAfter.GetInt()), "", false); return false; } - if (text == "/r" || text == "/roles" || text == "/gamemode" || text == "/gm") + if (text == "/r" || text == "/roles") { switch (Options.Gamemode.GetValue()) { @@ -238,7 +418,7 @@ internal static class SendChatPatch { if (templateMessage.Length < 121) { - Utils.ChatCommand(__instance, templateMessage, "", false); + Utils.ChatCommand(__instance, BanManager.CheckTemplate(templateMessage), "", false); } else { @@ -255,7 +435,7 @@ internal static class SendChatPatch return false; } - bool col1 = text.StartsWith("/col ") || text.StartsWith("/cor "); + bool col1 = text.StartsWith("/col "); bool col2 = text.StartsWith("/color "); bool col3 = text.StartsWith("/colour "); @@ -380,7 +560,7 @@ public static class RPCHandlerPatch BanManager.IsWordBanned(__instance, text); - bool col1 = text.StartsWith("/col ") || text.StartsWith("/cor "); + bool col1 = text.StartsWith("/col "); bool col2 = text.StartsWith("/color "); bool col3 = text.StartsWith("/colour "); @@ -444,28 +624,7 @@ public static class RPCHandlerPatch } } - if (/*CustomRoleManagement.HandlingRoleMessages || */OnGameJoinedPatch.WaitingForChat || GameStartManagerUpdatePatch.CountingDown) return; - - if (text == "/h" || text == "/help") - { - if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashHelpAndAurCmd.GetValue()) return; - OnGameJoinedPatch.WaitingForChat = true; - - new LateTask(() => - { - Utils.SendPrivateMessage(__instance, Translator.Get("allCommandsOne")); - }, 2.2f, "MHP1"); - - new LateTask(() => - { - Utils.SendPrivateMessage(__instance, Translator.Get("allCommandsTwo")); - }, 4.4f, "MHP2"); - - new LateTask(() => - { - OnGameJoinedPatch.WaitingForChat = false; - }, 6.6f, "MHP3"); - } + if (AbilityManagement.HandlingRoleMessages || OnGameJoinedPatch.WaitingForChat || GameStartManagerUpdatePatch.CountingDown) return; if (text == "/eg" || text == "/endgame") { @@ -490,7 +649,7 @@ public static class RPCHandlerPatch GameStartManager.Instance.BeginGame(); } - if (text == "/l" || text == "/lastgame" || text == "/win" || text == "/winner") + if (text == "/l" || text == "/lastgame") { if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashLastGameCmd.GetValue()) return; if (string.IsNullOrEmpty(NormalGameEndChecker.LastWinReason) || Utils.InGame) return; @@ -508,13 +667,13 @@ public static class RPCHandlerPatch Utils.ModeratorChatCommand(Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true); } - if (text == "/sp" || text == "/sr" || text == "/speedrun") + if (text == "/sr" || text == "/speedrun") { if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashRolesAndGamemodeCmd.GetValue()) return; Utils.ModeratorChatCommand(Translator.Get("speedrunMode", Options.GameAutoEndsAfter.GetInt()), "", false); } - if (text == "/r" || text == "/roles" || text == "/gamemode" || text == "/gm") + if (text == "/r" || text == "/roles") { if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashRolesAndGamemodeCmd.GetValue()) return; switch (Options.Gamemode.GetValue()) @@ -558,7 +717,7 @@ public static class RPCHandlerPatch if (text == "/r juggernaut"){ Utils.ModeratorChatCommand(Translator.Get("juggernautPublic", Options.KillsNeededForJuggernaut.GetInt()), "", false);} - if (text == "/r speedrunner"){ + if (text == "/r tasker"){ Utils.ModeratorChatCommand(Translator.Get("speedrunnerPublic"), "", false);} if (text.StartsWith("/t ")) @@ -569,7 +728,7 @@ public static class RPCHandlerPatch { if (templateMessage.Length < 121) { - Utils.ModeratorChatCommand(templateMessage, "", false); + Utils.ModeratorChatCommand(BanManager.CheckTemplate(templateMessage), "", false); } else { @@ -577,7 +736,6 @@ public static class RPCHandlerPatch } } } - break; } } diff --git a/Patches/ClientOptionsPatch.cs b/Patches/ClientOptionsPatch.cs index 7bb5704..0122e7b 100644 --- a/Patches/ClientOptionsPatch.cs +++ b/Patches/ClientOptionsPatch.cs @@ -15,6 +15,7 @@ namespace AmongUsRevamped private static ClientOptionItem DarkTheme; private static ClientOptionItem LobbyMusic; private static ClientOptionItem DisableInfoWhenDead; + private static ClientOptionItem DisableCommandHelper; public static void Postfix(OptionsMenuBehaviour __instance) { @@ -57,6 +58,9 @@ namespace AmongUsRevamped if (LobbyMusic == null || LobbyMusic.ToggleButton == null) LobbyMusic = ClientOptionItem.Create(Translator.Get("enableLobbyMusic"), Main.LobbyMusic, __instance); + + if (DisableCommandHelper == null || DisableCommandHelper.ToggleButton == null) + DisableCommandHelper = ClientOptionItem.Create(Translator.Get("disableCommandHelper"), Main.DisableCommandHelper, __instance); } } diff --git a/Patches/EndGamePatches.cs b/Patches/EndGamePatches.cs index 5af8a00..38d8e56 100644 --- a/Patches/EndGamePatches.cs +++ b/Patches/EndGamePatches.cs @@ -53,43 +53,43 @@ class NormalGameEndChecker if (Winner == "Jester") { - LastWinReason = $"Jester wins! (Voted)\n\nImpostors: {impostorList}"; + LastWinReason = Translator.Get("jesterWin") + impostorList; canUpdateWinnerText = false; return; } if (Winner == "Juggernaut") { - LastWinReason = $"Impostors win! (Juggernaut killed {Options.KillsNeededForJuggernaut.GetInt()} players)\n\nImpostor: {impostorList}"; + LastWinReason = Translator.Get("juggernautWin", Options.KillsNeededForJuggernaut.GetInt()) + impostorList; canUpdateWinnerText = false; return; } if (Winner == "Speedrunner") { - LastWinReason = $"Crewmates win! (Speedrunner finished tasks)\n\nImpostor: {impostorList}"; + LastWinReason = Translator.Get("speedrunnerWin") + impostorList; canUpdateWinnerText = false; return; } if (Utils.AliveImpostors == 0 || Winner == "Crewmate") { - LastWinReason = $"Crewmates win!\n\nImpostors: {impostorList}"; + LastWinReason = Translator.Get("crewmateWin") + impostorList; canUpdateWinnerText = false; } else if (Utils.AliveImpostors >= Utils.AliveCrewmates || Winner == "Impostor") { - LastWinReason = $"Impostors win!\n\nImpostor: {impostorList}"; + LastWinReason = Translator.Get("impostorWin") + impostorList; canUpdateWinnerText = false; } else if (GameData.Instance != null && GameData.Instance.TotalTasks > 0 && GameData.Instance.CompletedTasks >= GameData.Instance.TotalTasks || Winner == "CrewmateTasks") { - LastWinReason = $"Crewmates win! ({Options.TaskPercentNeededToWin.GetInt()}% Tasks)\n\nImpostors: {impostorList}"; + LastWinReason = Translator.Get("crewmateWinTasks", Options.TaskPercentNeededToWin.GetInt()) + impostorList; canUpdateWinnerText = false; } else if (Options.Gamemode.GetValue() < 2 || Winner == "ImpostorSabotage") { - LastWinReason = $"Impostors win! (Sabotage)\n\nImpostors: {impostorList}" + (string.IsNullOrEmpty(customRoles) ? "" : "\n\n" + customRoles); + LastWinReason = Translator.Get("impostorWinMisc") + impostorList; } } } diff --git a/Patches/ExilePatch.cs b/Patches/ExilePatch.cs index 30ee3f3..5cf1ee0 100644 --- a/Patches/ExilePatch.cs +++ b/Patches/ExilePatch.cs @@ -38,11 +38,11 @@ class ExileControllerWrapUpPatch } else { - if (!PlayerControlCompleteTaskPatch.playerTasksCompleted.ContainsKey(p)) + if (!PlayerControlCompleteTaskPatch.playerTasksCompleted.ContainsKey(p.PlayerId)) { - PlayerControlCompleteTaskPatch.playerTasksCompleted[p] = 0; + PlayerControlCompleteTaskPatch.playerTasksCompleted[p.PlayerId] = 0; } - p.cosmetics.nameText.text = $"{p.Data.PlayerName}({PlayerControlCompleteTaskPatch.playerTasksCompleted[p]}/{PlayerControlCompleteTaskPatch.tasksPerPlayer[p]})"; + p.cosmetics.nameText.text = $"{p.Data.PlayerName}({PlayerControlCompleteTaskPatch.playerTasksCompleted[p.PlayerId]}/{PlayerControlCompleteTaskPatch.tasksPerPlayer[p.PlayerId]})"; } } } diff --git a/Patches/IntroPatch.cs b/Patches/IntroPatch.cs index 49e4a44..5520eee 100644 --- a/Patches/IntroPatch.cs +++ b/Patches/IntroPatch.cs @@ -15,16 +15,16 @@ internal static class CoShowIntroPatch if (!AmongUsClient.Instance.AmHost) return; - AbilityManagement.SendRoleList(DestroyableSingleton.Instance.Chat, AbilityManagement.RoleList(), true); + AbilityManagement.SendRoleMessages(); foreach (var p in PlayerControl.AllPlayerControls) { p.cosmetics.nameText.text = p.Data.PlayerName; - MurderPlayerPatch.killCount[p.Data.PlayerId] = 0; - MurderPlayerPatch.misfireCount[p.Data.PlayerId] = 0; - PlayerControlCompleteTaskPatch.playerTasksCompleted[p] = 0; - PlayerControlCompleteTaskPatch.tasksPerPlayer[p] = 0; + MurderPlayerPatch.killCount[p.PlayerId] = 0; + MurderPlayerPatch.misfireCount[p.PlayerId] = 0; + PlayerControlCompleteTaskPatch.playerTasksCompleted[p.PlayerId] = 0; + PlayerControlCompleteTaskPatch.tasksPerPlayer[p.PlayerId] = 0; Logger.Info($" {p.Data.PlayerName} -> {p.Data.RoleType}", "RoleInfo"); } diff --git a/Patches/JoinAndLeavePatches.cs b/Patches/JoinAndLeavePatches.cs index 0a7e341..98daf71 100644 --- a/Patches/JoinAndLeavePatches.cs +++ b/Patches/JoinAndLeavePatches.cs @@ -51,6 +51,7 @@ internal static class OnGameJoinedPatch [HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnPlayerJoined))] class OnPlayerJoinedPatch { + public static int JoinNum; public static bool HasInvalidFriendCode(string friendcode) { if (string.IsNullOrEmpty(friendcode)) @@ -97,6 +98,18 @@ class OnPlayerJoinedPatch Logger.SendInGame($" {Client.PlayerName} Was banned for having an invalid FriendCode"); } } + + if (Options.EnableJoinMessages.GetBool()) + { + JoinNum++; + BanManager.Templates.TryGetValue("welcome", out string msg); + + if (JoinNum >= Options.MessagePerPlayerNum.GetInt()) + { + JoinNum = 0; + Utils.ModeratorChatCommand($"{msg}", "", false); + } + } } } } @@ -106,10 +119,11 @@ class OnPlayerLeftPatch { static void Postfix([HarmonyArgument(0)] ClientData client) { - if (!AmongUsClient.Instance.AmHost || !Utils.InGame) return; - { - PlayerControlCompleteTaskPatch.CalculateTaskWin(); - } + if (!AmongUsClient.Instance.AmHost) return; + Logger.Info($" {client.PlayerName} left the game", "OnPlayerLeft"); + + if (!Utils.InGame) return; + PlayerControlCompleteTaskPatch.CalculateTaskWin(); } } @@ -127,14 +141,14 @@ public static class SetLevelPatch if (!Options.TempBanLowLevelPlayer.GetBool()) { AmongUsClient.Instance.KickPlayer(__instance.Data.ClientId, false); - Logger.Info($" {__instance.Data.PlayerName} was kicked for being under level {Options.KickLowLevelPlayer.GetInt()}", "KickLowLevelPlayer"); - Logger.SendInGame($" {__instance.Data.PlayerName} was kicked for being under level {Options.KickLowLevelPlayer.GetInt()}"); + Logger.Info($" {__instance.Data.PlayerName} (level {level}) was kicked for being under level {Options.KickLowLevelPlayer.GetInt()}", "KickLowLevelPlayer"); + Logger.SendInGame($" {__instance.Data.PlayerName} (level {level}) was kicked for being under level {Options.KickLowLevelPlayer.GetInt()}"); } else { AmongUsClient.Instance.KickPlayer(__instance.Data.ClientId, true); - Logger.Info($" {__instance.Data.PlayerName} was banned for being under level {Options.KickLowLevelPlayer.GetInt()} ", "BanLowLevelPlayer"); - Logger.SendInGame($" {__instance.Data.PlayerName} was banned for being under level {Options.KickLowLevelPlayer.GetInt()}"); + Logger.Info($" {__instance.Data.PlayerName} (level {level}) was banned for being under level {Options.KickLowLevelPlayer.GetInt()} ", "BanLowLevelPlayer"); + Logger.SendInGame($" {__instance.Data.PlayerName} (level {level}) was banned for being under level {Options.KickLowLevelPlayer.GetInt()}"); } HandledLevelKicks.Add(__instance); } diff --git a/Patches/MeetingPatches.cs b/Patches/MeetingPatches.cs index 98d3e85..5befd93 100644 --- a/Patches/MeetingPatches.cs +++ b/Patches/MeetingPatches.cs @@ -27,13 +27,13 @@ public static class CheckForEndVotingPatch visualVotes.Add(new MeetingHud.VoterState { VoterId = voterId, VotedForId = votedFor }); - if (!PlayerControlCompleteTaskPatch.playerTasksCompleted.ContainsKey(pc)) PlayerControlCompleteTaskPatch.playerTasksCompleted[pc] = 0; + if (!PlayerControlCompleteTaskPatch.playerTasksCompleted.ContainsKey(voterId)) PlayerControlCompleteTaskPatch.playerTasksCompleted[voterId] = 0; if (!MurderPlayerPatch.killCount.ContainsKey(voterId)) MurderPlayerPatch.killCount[voterId] = 0; int extraVotes = 0; int extraVotesCrewmate = Options.ExtraVotesCrewmate.GetInt(); int extraVotesImpostor = Options.ExtraVotesImpostor.GetInt(); - int extraVotesPerTask = (int)(Options.ExtraVotesPerTask.GetFloat()*PlayerControlCompleteTaskPatch.playerTasksCompleted[pc]+0.1f); + int extraVotesPerTask = (int)(Options.ExtraVotesPerTask.GetFloat()*PlayerControlCompleteTaskPatch.playerTasksCompleted[voterId]+0.1f); int extraVotesPerKill = (int)(Options.ExtraVotesPerKill.GetFloat()*MurderPlayerPatch.killCount[voterId]+0.1f); if (!votes.TryGetValue(votedFor, out int currentVotes)) currentVotes = 0; diff --git a/Patches/PlayerControlPatches.cs b/Patches/PlayerControlPatches.cs index c615608..4826e7b 100644 --- a/Patches/PlayerControlPatches.cs +++ b/Patches/PlayerControlPatches.cs @@ -67,7 +67,7 @@ internal static class MurderPlayerPatch } else { - p.cosmetics.nameText.text = $"{p.Data.PlayerName}({PlayerControlCompleteTaskPatch.playerTasksCompleted[p]}/{PlayerControlCompleteTaskPatch.tasksPerPlayer[p]}) - {Utils.GetRoleText(p)}"; + p.cosmetics.nameText.text = $"{p.Data.PlayerName}({PlayerControlCompleteTaskPatch.playerTasksCompleted[p.PlayerId]}/{PlayerControlCompleteTaskPatch.tasksPerPlayer[p.PlayerId]}) - {Utils.GetRoleText(p)}"; } } } @@ -145,8 +145,8 @@ internal static class CheckShapeshiftPatch [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CompleteTask))] class PlayerControlCompleteTaskPatch { - public static Dictionary playerTasksCompleted = new Dictionary(); - public static Dictionary tasksPerPlayer = new Dictionary(); + public static Dictionary playerTasksCompleted = new Dictionary(); + public static Dictionary tasksPerPlayer = new Dictionary(); public static List ignoredRoles = new List {"Jester"}; public static int ignoredTasks; public static int ignoredCompletedTasks; @@ -158,32 +158,31 @@ class PlayerControlCompleteTaskPatch foreach (var p in PlayerControl.AllPlayerControls) { -/* - if (ignoredRoles.Contains(CustomRoleManagement.GetRole(p.PlayerId)) && !tasksInitiated) + if (AbilityManagement.IsJester(p) && !tasksInitiated) { ignoredTasks += p.Data.Tasks.Count; tasksInitiated = true; } -*/ - if (!playerTasksCompleted.ContainsKey(p)) + + if (!playerTasksCompleted.ContainsKey(p.PlayerId)) { - playerTasksCompleted[p] = 0; + playerTasksCompleted[p.PlayerId] = 0; } - tasksPerPlayer[p] = p.Data.Tasks.Count; + tasksPerPlayer[p.PlayerId] = p.Data.Tasks.Count; } - playerTasksCompleted[__instance]++; -/* - if (ignoredRoles.Contains(CustomRoleManagement.GetRole(__instance.PlayerId))) + playerTasksCompleted[__instance.PlayerId]++; + + if (AbilityManagement.IsJester(__instance)) { - ignoredCompletedTasks = playerTasksCompleted[__instance]; + ignoredCompletedTasks = playerTasksCompleted[__instance.PlayerId]; } -*/ + Logger.Info($" {__instance.Data.PlayerName} completed {idx}", "TaskPatch"); if (Options.Gamemode.GetValue() < 2) { - if (AbilityManagement.IsSpeedrunner(__instance) && !__instance.Data.IsDead && playerTasksCompleted[__instance] >= __instance.Data.Tasks.Count) + if (AbilityManagement.IsSpeedrunner(__instance) && !__instance.Data.IsDead && playerTasksCompleted[__instance.PlayerId] >= __instance.Data.Tasks.Count) { Logger.Info($"Speedrunner {__instance.Data.PlayerName} won", "TaskPatch"); Utils.ContinueEndGame((byte)GameOverReason.CrewmatesByVote); @@ -195,7 +194,7 @@ class PlayerControlCompleteTaskPatch if (Options.Gamemode.GetValue() == 3) { - if (!__instance.Data.IsDead && playerTasksCompleted[__instance] >= __instance.Data.Tasks.Count) + if (!__instance.Data.IsDead && playerTasksCompleted[__instance.PlayerId] >= __instance.Data.Tasks.Count) { Utils.CustomWinnerEndGame(__instance, 1); NormalGameEndChecker.LastWinReason = $"{__instance.Data.PlayerName} wins! (Completed tasks)"; @@ -206,7 +205,7 @@ class PlayerControlCompleteTaskPatch if (PlayerControl.LocalPlayer.Data.IsDead && !Main.DisableInfoWhenDead.Value) { TMP_Text nameText = __instance.cosmetics.nameText; - nameText.text = $"{__instance.Data.PlayerName}({playerTasksCompleted[__instance]}/{tasksPerPlayer[__instance]}) - {Utils.GetRoleText(__instance)}"; + nameText.text = $"{__instance.Data.PlayerName}({playerTasksCompleted[__instance.PlayerId]}/{tasksPerPlayer[__instance.PlayerId]}) - {Utils.GetRoleText(__instance)}"; } } diff --git a/README.md b/README.md index 2d31f50..e8fcc75 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,14 @@ **** โ€Ž -# ๐ŸŽฎ Features (v1.7.4): +# ๐ŸŽฎ Features (v1.7.5): ## ๐ŸŒŸ Custom Abilities: - Mayor (Crewmate) - The Mayor has a configurable amount of extra votes - Jester (Crewmate) - The Jester wins alone by getting ejected, can win with Crewmates -- Speedrunner (Crewmate) -- The Crewmates win if the Speedrunner completes tasks and is alive +- Tasker (Crewmate) +- The Crewmates win if the Tasker completes tasks and is alive - Workhorse (Crewmate) - The Workhorse gains additional votes per completed task - Tyrant (Impostor) @@ -49,8 +49,7 @@ - To check ability descriptions, type /r {ability} ## โ™ ๏ธ Client Side settings: -- Game Master -- Unlock FPS +- Game Master (Spectator) - Show FPS - Dark Theme - Toggle Lobby Music @@ -71,24 +70,26 @@ - Automatically start game - Automatically rejoin lobby - Automatically send winner info +- Enable (configurable) Welcome Messages +- The Welcome Template is in Templates.txt ## ๐Ÿ”ง Gameplay Settings: - Dead impostors can sabotage - Disable critical sabotages (invividual) - Disable door sabotages - Disable meeting calls first 30s -- Disable body reports - Disable devices (per map, individual) - Override decontamination time (per map) - Disable spore triggers on The Fungle - % Tasks completed for Crewmates to win - Enable/Disable any task - All players have same tasks -- Hide and Seek: Custom Impostor count +- Hide and Seek: Custom Seeker count ## ๐Ÿ† Custom Gamemodes: - 0 Kill Cooldown - Shift and Seek - Speedrun ## โ“ Other Improvements: +- Command Helper - Creatable and customizable Templates - Eht Dleks (Reverse Skeld) Map - Ability to cancel starting countdown @@ -96,7 +97,7 @@ - Faster startup time - Custom anticheat system - Zoom out in lobby or when dead -- See player kill/task count when dead +- See player kill/task count and Role when dead - Higher and more accurate Option ranges - ๐ŸŽ‰ And this all works in public lobbies! @@ -114,21 +115,24 @@ ### Chat Commands | Command | Function | | ------------------------------------------- | ------------------------------------------------- | -| /h
/help | Show command help | -| /l
/win | Show winner | -| /r | Show current gamemode/roles description | -| /0kc
/sns
/sp | Show respective gamemode description | +| /help | Show command help | +| /l
/lastgame | Send last game info | +| /r | Send current gamemode/roles description | +| /r | Send specific Ability info | +| /0kc
/sns
/sp | Send respective gamemode description | | /ban | Ban a player by name | | /kick | Kick a player by name | | /cban | Ban a player by color | | /ckick | Kick a player by color | | /dump | Copy your LogOutput file | -| /endgame | Instantly end the game | -| /endmeeting | Instantly end an ongoing meeting | -| /aur | Sends AUR socials (GitHub, Discord) | -| /color | Sets color. Can be used to bypass color limit | -| /reload | Resets the *Language*.JSON file to default | -| /start | Starts game countdown | +| /eg
/endgame | Instantly end an ongoing game | +| /em
/endmeeting | Instantly end an ongoing meeting | +| /aur
/socials | Send AUR socials (GitHub, Discord) | +| /col
/color | Set color. Can be used to bypass color limit | +| /reload | Reset the *Language*.JSON file to default | +| /s
/moderator
/admin | Add a user to respective list by name | +| /t