diff --git a/Modules/OptionHolder.cs b/Modules/OptionHolder.cs index 631955808..eb3964f9e 100644 --- a/Modules/OptionHolder.cs +++ b/Modules/OptionHolder.cs @@ -751,6 +751,7 @@ public static class Options public static OptionItem ApplyBanList; public static OptionItem ApplyModeratorList; public static OptionItem ApplyVIPList; + public static OptionItem ApplyAdminList; public static OptionItem AutoWarnStopWords; public static OptionItem DIYGameSettings; @@ -1007,7 +1008,8 @@ public static class Options Command.UsageLevels.Everyone => ":purple_circle: Everyone", Command.UsageLevels.Modded => ":green_circle: Modded Clients", Command.UsageLevels.Host => ":yellow_circle: Host", - Command.UsageLevels.HostOrModerator => ":red_circle: Host And Moderators", + Command.UsageLevels.HostOrModerator => ":red_circle: Host, Moderators, And Admins", + Command.UsageLevels.HostOrAdmin => ":white_circle: Host And Admins", _ => string.Empty }; @@ -1534,6 +1536,7 @@ public static class Options ApplyBanList = new BooleanOptionItem(19304, "ApplyBanList", true, TabGroup.SystemSettings, true); ApplyModeratorList = new BooleanOptionItem(19305, "ApplyModeratorList", true, TabGroup.SystemSettings); ApplyVIPList = new BooleanOptionItem(19306, "ApplyVIPList", true, TabGroup.SystemSettings); + ApplyAdminList = new BooleanOptionItem(19330, "ApplyAdminList", true, TabGroup.SystemSettings); LoadingPercentage = 61; diff --git a/Modules/RPC.cs b/Modules/RPC.cs index 7107d06cd..d2882883f 100644 --- a/Modules/RPC.cs +++ b/Modules/RPC.cs @@ -671,8 +671,10 @@ internal static class RPCHandlerPatch PlayerControl player = reader.ReadByte().GetPlayer(); string text = reader.ReadString(); bool modCommand = reader.ReadBoolean(); + bool adminCommand = reader.ReadBoolean(); if (modCommand && !ChatCommands.IsPlayerModerator(player.FriendCode)) break; + if (adminCommand && !ChatCommands.IsPlayerAdmin(player.FriendCode)) break; const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public; typeof(ChatCommands).GetMethod(methodName, flags)?.Invoke(null, [player, text, text.Split(' ')]); diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 511530688..f0b057c2a 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -73,7 +73,13 @@ Symbols Emoji: ™ 〰 🆗 🆕 🆙 🆒 🆓 🆖 🅿 Ⓜ 🆑 🆘 🆚 ⚠ public static class Utils { public const string EmptyMessage = "."; - private static readonly DateTime TimeStampStartTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + private static readonly DateTime Epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + private static readonly DateTime StartTime = DateTime.UtcNow; + private static readonly long EpochStartSeconds = (long)(StartTime - Epoch).TotalSeconds; + private static readonly Stopwatch Stopwatch = Stopwatch.StartNew(); + + public static long TimeStamp => EpochStartSeconds + (long)Stopwatch.Elapsed.TotalSeconds; private static readonly StringBuilder SelfSuffix = new(); private static readonly StringBuilder SelfMark = new(20); @@ -88,7 +94,6 @@ public static class Utils private static readonly Dictionary LongRoleDescriptions = []; - public static long TimeStamp => (long)(DateTime.Now.ToUniversalTime() - TimeStampStartTime).TotalSeconds; public static bool DoRPC => AmongUsClient.Instance.AmHost && Main.AllPlayerControls.Any(x => x.IsModdedClient() && !x.IsHost()); public static int TotalTaskCount => Main.RealOptionsData.GetInt(Int32OptionNames.NumCommonTasks) + Main.RealOptionsData.GetInt(Int32OptionNames.NumLongTasks) + Main.RealOptionsData.GetInt(Int32OptionNames.NumShortTasks); private static int AllPlayersCount => Main.PlayerStates.Values.Count(state => state.countTypes != CountTypes.OutOfGame); @@ -97,7 +102,7 @@ public static class Utils public static long GetTimeStamp(DateTime? dateTime = null) { - return (long)((dateTime ?? DateTime.Now).ToUniversalTime() - TimeStampStartTime).TotalSeconds; + return (long)((dateTime ?? DateTime.Now).ToUniversalTime() - Epoch).TotalSeconds; } public static void ErrorEnd(string text) diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index fb5636e64..bc14ee4a5 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -28,7 +28,8 @@ internal class Command(string[] commandForms, string arguments, string descripti Everyone, Modded, Host, - HostOrModerator + HostOrModerator, + HostOrAdmin } public enum UsageTimes @@ -70,6 +71,7 @@ internal class Command(string[] commandForms, string arguments, string descripti case UsageLevels.Host when !pc.IsHost(): case UsageLevels.Modded when !pc.IsModdedClient(): case UsageLevels.HostOrModerator when !pc.IsHost() && (AmongUsClient.Instance.AmHost && !ChatCommands.IsPlayerModerator(pc.FriendCode)): + case UsageLevels.HostOrAdmin when !pc.IsHost() && AmongUsClient.Instance.AmHost && !ChatCommands.IsPlayerAdmin(pc.FriendCode): if (sendErrorMessage) Utils.SendMessage("\n", pc.PlayerId, GetString($"Commands.NoAccess.Level.{UsageLevel}")); return false; } @@ -159,12 +161,12 @@ internal static class ChatCommands new(["chat", "сообщение", "腹语者发送消息"], "{message}", GetString("CommandDescription.Chat"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, ChatCommand, true, true, [GetString("CommandArgs.Chat.Message")]), new(["check", "проверить", "检查", "veificar"], "{id} {role}", GetString("CommandDescription.Check"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, CheckCommand, true, true, [GetString("CommandArgs.Check.Id"), GetString("CommandArgs.Check.Role")]), new(["ban", "kick", "бан", "кик", "забанить", "кикнуть", "封禁", "踢出", "banir", "expulsar"], "{id}", GetString("CommandDescription.Ban"), Command.UsageLevels.HostOrModerator, Command.UsageTimes.Always, BanKickCommand, true, false, [GetString("CommandArgs.Ban.Id")]), - new(["exe", "выкинуть", "驱逐", "executar"], "{id}", GetString("CommandDescription.Exe"), Command.UsageLevels.Host, Command.UsageTimes.Always, ExeCommand, true, false, [GetString("CommandArgs.Exe.Id")]), + new(["exe", "выкинуть", "驱逐", "executar"], "{id}", GetString("CommandDescription.Exe"), Command.UsageLevels.HostOrAdmin, Command.UsageTimes.Always, ExeCommand, true, false, [GetString("CommandArgs.Exe.Id")]), new(["kill", "убить", "击杀", "matar"], "{id}", GetString("CommandDescription.Kill"), Command.UsageLevels.Host, Command.UsageTimes.Always, KillCommand, true, false, [GetString("CommandArgs.Kill.Id")]), new(["colour", "color", "цвет", "更改颜色", "cor"], "{color}", GetString("CommandDescription.Colour"), Command.UsageLevels.Everyone, Command.UsageTimes.InLobby, ColorCommand, true, false, [GetString("CommandArgs.Colour.Color")]), new(["id", "guesslist", "айди", "ID列表"], "", GetString("CommandDescription.ID"), Command.UsageLevels.Everyone, Command.UsageTimes.Always, IDCommand, true, false), new(["changerole", "изменитьроль", "измроль", "修改职业", "mudar-função"], "{role}", GetString("CommandDescription.ChangeRole"), Command.UsageLevels.Host, Command.UsageTimes.InGame, ChangeRoleCommand, true, false, [GetString("CommandArgs.ChangeRole.Role")]), - new(["end", "закончить", "завершить", "结束游戏", "encerrar", "finalizar", "fim"], "", GetString("CommandDescription.End"), Command.UsageLevels.Host, Command.UsageTimes.InGame, EndCommand, true, false), + new(["end", "закончить", "завершить", "结束游戏", "encerrar", "finalizar", "fim"], "", GetString("CommandDescription.End"), Command.UsageLevels.HostOrAdmin, Command.UsageTimes.InGame, EndCommand, true, false), new(["cosid", "костюм", "одежда", "服装ID"], "", GetString("CommandDescription.CosID"), Command.UsageLevels.Modded, Command.UsageTimes.Always, CosIDCommand, true, false), new(["mt", "hy", "собрание", "开会/结束会议"], "", GetString("CommandDescription.MTHY"), Command.UsageLevels.Host, Command.UsageTimes.InGame, MTHYCommand, true, false), new(["csd", "кзвук", "自定义播放声音"], "{sound}", GetString("CommandDescription.CSD"), Command.UsageLevels.Modded, Command.UsageTimes.Always, CSDCommand, true, false, [GetString("CommandArgs.CSD.Sound")]), @@ -208,6 +210,8 @@ internal static class ChatCommands new(["forge"], "{id} {role}", GetString("CommandDescription.Forge"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, ForgeCommand, true, true, [GetString("CommandArgs.Forge.Id"), GetString("CommandArgs.Forge.Role")]), new(["choose", "pick", "выбрать", "选择", "escolher"], "{role}", GetString("CommandDescription.Choose"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, ChooseCommand, true, true, [GetString("CommandArgs.Choose.Role")]), new(["copypreset", "presetcopy", "скопироватьсохранение", "скопироватьсохр", "复制预设", "copiar"], "{sourcepreset} {targetpreset}", GetString("CommandDescription.CopyPreset"), Command.UsageLevels.Host, Command.UsageTimes.InLobby, CopyPresetCommand, true, false, [GetString("CommandArgs.CopyPreset.SourcePreset"), GetString("CommandArgs.CopyPreset.TargetPreset")]), + new(["addadmin", "добавитьадмин", "добадмин", "指定管理员", "admin-add"], "{id}", GetString("CommandDescription.AddAdmin"), Command.UsageLevels.Host, Command.UsageTimes.Always, AddAdminCommand, true, false, [GetString("CommandArgs.AddAdmin.Id")]), + new(["deleteadmin", "удалитьадмин", "убратьадмин", "удалитьадминку", "убратьадминку", "删除管理员", "admin-remover"], "{id}", GetString("CommandDescription.DeleteAdmin"), Command.UsageLevels.Host, Command.UsageTimes.Always, DeleteAdminCommand, true, false, [GetString("CommandArgs.DeleteAdmin.Id")]), // Commands with action handled elsewhere new(["shoot", "guess", "bet", "bt", "st", "угадать", "бт", "猜测", "赌", "adivinhar"], "{id} {role}", GetString("CommandDescription.Guess"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, (_, _, _) => { }, true, false, [GetString("CommandArgs.Guess.Id"), GetString("CommandArgs.Guess.Role")]), @@ -221,12 +225,16 @@ internal static class ChatCommands private static string[] ModsFileCache = []; private static string[] VIPsFileCache = []; + private static string[] AdminsFileCache = []; private static long LastModFileUpdate; private static long LastVIPFileUpdate; + private static long LastAdminFileUpdate; // Function to check if a Player is Moderator public static bool IsPlayerModerator(string friendCode) { + if (IsPlayerAdmin(friendCode)) return true; + friendCode = friendCode.Replace(':', '#'); if (friendCode == "" || friendCode == string.Empty || !Options.ApplyModeratorList.GetBool()) return false; @@ -234,7 +242,8 @@ internal static class ChatCommands long now = Utils.TimeStamp; string[] friendCodes; - if (LastModFileUpdate + 5 > now) { friendCodes = ModsFileCache; } + if (LastModFileUpdate + 5 > now) + friendCodes = ModsFileCache; else { var friendCodesFilePath = $"{Main.DataPath}/EHR_DATA/Moderators.txt"; @@ -262,7 +271,8 @@ internal static class ChatCommands long now = Utils.TimeStamp; string[] friendCodes; - if (LastVIPFileUpdate + 5 > now) { friendCodes = VIPsFileCache; } + if (LastVIPFileUpdate + 5 > now) + friendCodes = VIPsFileCache; else { var friendCodesFilePath = $"{Main.DataPath}/EHR_DATA/VIPs.txt"; @@ -280,6 +290,35 @@ internal static class ChatCommands return friendCodes.Any(code => code.Contains(friendCode, StringComparison.OrdinalIgnoreCase)); } + // Function to check if a player is an Admin + public static bool IsPlayerAdmin(string friendCode) + { + friendCode = friendCode.Replace(':', '#'); + + if (friendCode == "" || friendCode == string.Empty || !Options.ApplyAdminList.GetBool()) return false; + + long now = Utils.TimeStamp; + string[] friendCodes; + + if (LastAdminFileUpdate + 5 > now) + friendCodes = AdminsFileCache; + else + { + var friendCodesFilePath = $"{Main.DataPath}/EHR_DATA/Admins.txt"; + + if (!File.Exists(friendCodesFilePath)) + { + File.WriteAllText(friendCodesFilePath, string.Empty); + return false; + } + + friendCodes = AdminsFileCache = File.ReadAllLines(friendCodesFilePath); + LastAdminFileUpdate = now; + } + + return friendCodes.Any(code => code.Contains(friendCode, StringComparison.OrdinalIgnoreCase)); + } + public static bool Prefix(ChatController __instance) { if (__instance.quickChatField.visible) return true; @@ -411,7 +450,7 @@ internal static class ChatCommands } } - private static void RequestCommandProcessingFromHost(string methodName, string text, bool modCommand = false) + private static void RequestCommandProcessingFromHost(string methodName, string text, bool modCommand = false, bool adminCommand = false) { PlayerControl pc = PlayerControl.LocalPlayer; MessageWriter w = AmongUsClient.Instance.StartRpcImmediately(pc.NetId, (byte)CustomRPC.RequestCommandProcessing, SendOption.Reliable, AmongUsClient.Instance.HostId); @@ -419,11 +458,57 @@ internal static class ChatCommands w.Write(pc.PlayerId); w.Write(text); w.Write(modCommand); + w.Write(adminCommand); AmongUsClient.Instance.FinishRpcImmediately(w); } // --------------------------------------------------------------------------------------------------------------------------------------------- + private static void DeleteAdminCommand(PlayerControl player, string text, string[] args) + { + if (!AmongUsClient.Instance.AmHost) + { + RequestCommandProcessingFromHost(nameof(DeleteAdminCommand), text); + return; + } + + if (args.Length < 2 || !byte.TryParse(args[1], out byte remAdminId)) return; + + PlayerControl remAdminPc = Utils.GetPlayerById(remAdminId); + if (remAdminPc == null) return; + + string remFc = remAdminPc.FriendCode.Replace(':', '#'); + + if (!IsPlayerAdmin(remFc)) + { + Utils.SendMessage(GetString("PlayerNotAdmin"), player.PlayerId); + return; + } + + File.WriteAllLines($"{Main.DataPath}/EHR_DATA/Admins.txt", File.ReadAllLines($"{Main.DataPath}/EHR_DATA/Admins.txt").Where(x => !x.Contains(remFc))); + Utils.SendMessage(GetString("PlayerRemovedFromAdminList"), player.PlayerId); + } + + private static void AddAdminCommand(PlayerControl player, string text, string[] args) + { + if (!AmongUsClient.Instance.AmHost) + { + RequestCommandProcessingFromHost(nameof(AddAdminCommand), text); + return; + } + + if (args.Length < 2 || !byte.TryParse(args[1], out byte newAdminId)) return; + + PlayerControl newAdminPc = Utils.GetPlayerById(newAdminId); + if (newAdminPc == null) return; + + string fc = newAdminPc.FriendCode.Replace(':', '#'); + if (IsPlayerModerator(fc)) Utils.SendMessage(GetString("PlayerAlreadyAdmin"), player.PlayerId); + + File.AppendAllText($"{Main.DataPath}/EHR_DATA/Admins.txt", $"\n{fc}"); + Utils.SendMessage(GetString("PlayerAddedToAdminList"), player.PlayerId); + } + private static void CopyPresetCommand(PlayerControl player, string text, string[] args) { if (args.Length < 3 || !int.TryParse(args[1], out int sourcePresetId) || sourcePresetId is < 1 or > 10 || (!int.TryParse(args[2], out int targetPreset) && targetPreset is < 1 or > 10)) return; @@ -1582,10 +1667,12 @@ internal static class ChatCommands { if (!AmongUsClient.Instance.AmHost) { - RequestCommandProcessingFromHost(nameof(EndCommand), text); + RequestCommandProcessingFromHost(nameof(EndCommand), text, adminCommand: true); return; } + if (!player.IsHost() && !IsPlayerAdmin(player.FriendCode)) return; + CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Draw); GameManager.Instance.LogicFlow.CheckEndCriteria(); } @@ -1704,10 +1791,12 @@ internal static class ChatCommands { if (!AmongUsClient.Instance.AmHost) { - RequestCommandProcessingFromHost(nameof(ExeCommand), text); + RequestCommandProcessingFromHost(nameof(ExeCommand), text, adminCommand: true); return; } + if (!player.IsHost() && !IsPlayerAdmin(player.FriendCode)) return; + if (GameStates.IsLobby) { Utils.SendMessage(GetString("Message.CanNotUseInLobby"), player.PlayerId, sendOption: SendOption.None); @@ -2303,7 +2392,12 @@ internal static class ChatCommands if (remModPc == null) return; string remFc = remModPc.FriendCode.Replace(':', '#'); - if (!IsPlayerModerator(remFc)) Utils.SendMessage(GetString("PlayerNotMod"), player.PlayerId); + + if (!IsPlayerModerator(remFc)) + { + Utils.SendMessage(GetString("PlayerNotMod"), player.PlayerId); + return; + } File.WriteAllLines($"{Main.DataPath}/EHR_DATA/Moderators.txt", File.ReadAllLines($"{Main.DataPath}/EHR_DATA/Moderators.txt").Where(x => !x.Contains(remFc))); Utils.SendMessage(GetString("PlayerRemovedFromModList"), player.PlayerId); @@ -2323,7 +2417,12 @@ internal static class ChatCommands if (newModPc == null) return; string fc = newModPc.FriendCode.Replace(':', '#'); - if (IsPlayerModerator(fc)) Utils.SendMessage(GetString("PlayerAlreadyMod"), player.PlayerId); + + if (IsPlayerModerator(fc)) + { + Utils.SendMessage(GetString("PlayerAlreadyMod"), player.PlayerId); + return; + } File.AppendAllText($"{Main.DataPath}/EHR_DATA/Moderators.txt", $"\n{fc}"); Utils.SendMessage(GetString("PlayerAddedToModList"), player.PlayerId); diff --git a/Patches/GameStartManagerPatch.cs b/Patches/GameStartManagerPatch.cs index b15e989ea..d341c5525 100644 --- a/Patches/GameStartManagerPatch.cs +++ b/Patches/GameStartManagerPatch.cs @@ -33,6 +33,17 @@ public static class GameStartManagerPatch private static TextMeshPro WarningText; public static float Timer => Math.Max(0, 597f - (Utils.TimeStamp - TimerStartTS)); + [HarmonyPatch(typeof(TimerTextTMP), nameof(TimerTextTMP.GetTextString))] + private static class TimerTextTMPGetTextStringPatch + { + public static bool Prefix(TimerTextTMP __instance, ref string __result) + { + int seconds = __instance.GetSecondsRemaining(); + __result = string.Format(GetString("LobbyTimer"), seconds / 60, seconds % 60); + return false; + } + } + [HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Start))] public static class GameStartManagerStartPatch { diff --git a/Patches/MeetingHudPatch.cs b/Patches/MeetingHudPatch.cs index 59d0f136d..7e42f8300 100644 --- a/Patches/MeetingHudPatch.cs +++ b/Patches/MeetingHudPatch.cs @@ -421,7 +421,7 @@ internal static class CheckForEndVotingPatch case 2: name = string.Format(GetString("PlayerIsRole"), coloredRealName, coloredRole); - if (Options.ShowTeamNextToRoleNameOnEject.GetBool()) + if (Options.ShowTeamNextToRoleNameOnEject.GetBool() && !(crole.IsVanilla() || crole.ToString().EndsWith("EHR"))) { name += " ("; CustomTeamManager.CustomTeam team = CustomTeamManager.GetCustomTeam(player.PlayerId); diff --git a/README.md b/README.md index 3c3ec9ecc..d4e04c1f4 100644 --- a/README.md +++ b/README.md @@ -206,21 +206,23 @@ You can also report bugs and suggest features in the #bug-reports and #suggestio :x: Can never use the command
:question: Host setting determines
-| Feature | Regular Players | VIP | Moderator | Host | -|-----------|-----------------|--------------------|--------------------|--------------------| -| /color | :question: | :heavy_check_mark: | :question: | :heavy_check_mark: | -| /rename | :question: | :heavy_check_mark: | :question: | :heavy_check_mark: | -| /tpin | :question: | :heavy_check_mark: | :question: | :heavy_check_mark: | -| /tpout | :question: | :heavy_check_mark: | :question: | :heavy_check_mark: | -| /kick | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| /ban | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| /say | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| /poll | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| /mute | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| /ds | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| /gmpoll | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| /fix | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| Lobby tag | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Feature | Regular Players | VIP | Moderator | Admin | Host | +|-----------|-----------------|--------------------|--------------------|--------------------|--------------------| +| /color | :question: | :heavy_check_mark: | :question: | :question: | :heavy_check_mark: | +| /rename | :question: | :heavy_check_mark: | :question: | :question: | :heavy_check_mark: | +| /tpin | :question: | :heavy_check_mark: | :question: | :question: | :heavy_check_mark: | +| /tpout | :question: | :heavy_check_mark: | :question: | :question: | :heavy_check_mark: | +| /kick | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /ban | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /say | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /poll | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /mute | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /ds | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /gmpoll | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /fix | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| /exe | :x: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | +| /end | :x: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | +| Lobby tag | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index 3d591fe61..9b1a22b1a 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -1865,6 +1865,7 @@ "DisableCrackedGlass": "Disable Cracked Glass on Meeting Screen", "ApplyModeratorList": "Apply Moderator List", "ApplyVIPList": "Apply VIP List", + "ApplyAdminList": "Apply Admin List", "KickCommandDisabled": "The kick command is currently disabled.", "KickCommandNoAccess": "You do not have access to the kick command.", "KickCommandInvalidID": "Invalid player ID specified.\\nPlease use '/kick [playerID]' to kick a player.", @@ -1874,6 +1875,7 @@ "KickCommandKickedRole": "Their role was", "ModeratorTag": "<#8000ff>Moderator", "VIPTag": "<#ffff00>VIP", + "AdminTag": "<#ff0000>Admin", "EnableAFKDetector": "Enable AFK Detector (Also Used To Detect And Fix Black Screens)", "AFKWarning": "<#ffff00>Please move to avoid being marked as AFK <#ffffff>({0})", "AFKSuffix": "<#ffa500>(AFK)", @@ -2364,7 +2366,8 @@ "EnabledGMWarning": "You have enabled Game Master. This will make you a ghost at the start of every game. Due to an unknown issue, games may end with the 'Everyone died' reason instantly, if this happens, please disable Game Master.", "Commands.NoAccess.Level.Host": "<#ff5555>X <#bb0000>This command can only be used by <#ffffff>The Host", "Commands.NoAccess.Level.Modded": "<#ff5555>X <#bb0000>This command can only be used by <#ffffff>Modded Clients", - "Commands.NoAccess.Level.HostOrModerator": "<#ff5555>X <#bb0000>This command can only be used by <#ffffff>The Host & Moderators", + "Commands.NoAccess.Level.HostOrModerator": "<#ff5555>X <#bb0000>This command can only be used by <#ffffff>The Host & Moderators & Admins", + "Commands.NoAccess.Level.HostOrAdmin": "<#ff5555>X <#bb0000>This command can only be used by <#ffffff>The Host & Admins", "Commands.NoAccess.Time.InLobby": "<#ff5555>X <#bb0000>This command can only be used <#ffffff>In Lobby", "Commands.NoAccess.Time.InGame": "<#ff5555>X <#bb0000>This command can only be used <#ffffff>In Game", "Commands.NoAccess.Time.InMeeting": "<#ff5555>X <#bb0000>This command can only be used <#ffffff>In Meetings", @@ -2462,6 +2465,8 @@ "CommandDescription.Forge": "As the Forger, forge a fake role for a player.", "CommandDescription.Choose": "Choose your role as the Pawn after completing all tasks.", "CommandDescription.CopyPreset": "Copy all settings from a preset to another preset.", + "CommandDescription.AddAdmin": "Add a player to the list of admins", + "CommandDescription.DeleteAdmin": "Remove a player from the list of admins", "CommandArgs.ChangeSetting.Name": "The setting's name to change (leave blank to view all settings)", "CommandArgs.ChangeSetting.UnknownValue": "(leave blank to view what to put here)", "CommandArgs.Rename.Name": "Your new name", @@ -2548,6 +2553,8 @@ "CommandArgs.Choose.Role": "The role to choose", "CommandArgs.CopyPreset.SourcePreset": "The preset to copy all settings from", "CommandArgs.CopyPreset.TargetPreset": "The preset to paste all settings to", + "CommandArgs.AddAdmin.Id": "The player's ID to add to the list of admins", + "CommandArgs.DeleteAdmin.Id": "The player's ID to remove from the list of admins", "Commands.ChangeSettingHelp": "Arguments:\\n- map (theskeld/mirahq/polus/dlekseht/airship/thefungle/custom)\\n- impostors (number)\\n- players (number)\\n- recommended (on/off)\\n- confirmejects (on/off)\\n- emergencymeetings (number)\\n- anonymousvotes (on/off)\\n- emergencycooldown (number)\\n- discussiontime (number)\\n- votingtime (number)\\n- playerspeed (float)\\n- crewmatevision (float)\\n- impostorvision (float)\\n- killcooldown (float)\\n- killdistance (short/medium/long/custom)\\n- taskbarupdates (always/meetings/never)\\n- visualtasks (on/off)\\n- commontasks (number)\\n- longtasks (number)\\n- shorttasks (number)\\n- scientistcount (number)\\n- scientistchance (number)\\n- vitalsdisplaycooldown (float)\\n- batteryduration (float)\\n- engineercount (number)\\n- engineerchance (number)\\n- ventusecooldown (float)\\n- maxtimeinvents (float)\\n- guardianangelcount (number)\\n- guardianangelchance (number)\\n- protectcooldown (float)\\n- protectduration (float)\\n- protectvisibletoimpostors (on/off)\\n- shapeshiftercount (number)\\n- shapeshifterchance (number)\\n- shapeshiftduration (float)\\n- shapeshiftcooldown (float)\\n- leaveshapeshiftevidence (on/off)\\n- phantomcount (number)\\n- phantomchance (number)\\n- inviscooldown (float)\\n- invisduration (float)\\n- noisemakercount (number)\\n- noisemakerchance (number)\\n- noisemakerimpostoralert (on/off)\\n- noisemakeralertduration (number)\\n- trackercount (number)\\n- trackerchance (number)\\n- trackduration (float)\\n- trackcooldown (float)\\n- trackdelay (float)\\n- ghostdotasks (on/off)\\n\\nNotes:\\n1. Upper and lowercase matters\\n2. Where it says custom, you obviously put a number argument after it\\n3. A float is a single precision floating number, like 1.7\\n4. \"ghostdotasks\" causes issues if you set it\\n5. Example uses:\\n - \"/cs map polus\"\\n - \"/cs killdistance custom 4\"\\n - \"/cs trackdelay 1,7\"\\n - \"/cs confirmejects on\"", "AddTagSuccess": "<#00ffa5>✓ Suceessfully created the tag {0} for {1}. If you want to change it, just use this command again and it will override the current tag. To delete it, simply type <#00a5ff>/deletetag {2}!", "DeleteTagSuccess": "<#00ffa5>✓ Successfully deleted {0}'s tag.", @@ -8688,6 +8695,10 @@ "PlayerAddedToVIPList": "Player successfully added to the VIP list.", "PlayerRemovedFromVIPList": "Player successfully removed from the VIP list.", "PlayerNotVIP": "This player is not a VIP, nothing was changed.", + "PlayerNotAdmin": "This player is not an admin, nothing was changed.", + "PlayerRemovedFromAdminList": "Player successfully removed from the admin list.", + "PlayerAlreadyAdmin": "This player is already an admin, nothing was changed.", + "PlayerAddedToAdminList": "Player successfully added to the admin list.", "Goose": "Goose", "GooseInfo": "Honk at players to annoy them", "GooseInfoLong": "(Crewmates):\\nAs the Goose, you can honk at players to annoy them. You can drag them around and make them unable to use their abilities while you're honking at them.", @@ -9701,6 +9712,7 @@ "SubmergedRoomName.133": "Ballast", "SubmergedRoomName.134": "Lower Central", "SubmergedRoomName.135": "Lower Lobby", + "LobbyTimer": "Lobby closes in {0}m {1}s", "ModLanguage": "Mod Language", "UseGameLanguage": "Use Game Language", "Hungarian": "Hungarian", diff --git a/Roles/Crewmate/Addict.cs b/Roles/Crewmate/Addict.cs index cac10afc4..e14fe2010 100644 --- a/Roles/Crewmate/Addict.cs +++ b/Roles/Crewmate/Addict.cs @@ -120,7 +120,7 @@ public class Addict : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = VentCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnEnterVent(PlayerControl pc, Vent vent) diff --git a/Roles/Crewmate/Adventurer.cs b/Roles/Crewmate/Adventurer.cs index 2417f83e4..c3b30451d 100644 --- a/Roles/Crewmate/Adventurer.cs +++ b/Roles/Crewmate/Adventurer.cs @@ -134,7 +134,7 @@ internal class Adventurer : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = 0.1f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnExitVent(PlayerControl pc, Vent vent) diff --git a/Roles/Crewmate/Alchemist.cs b/Roles/Crewmate/Alchemist.cs index 4f43a63b4..da8820950 100644 --- a/Roles/Crewmate/Alchemist.cs +++ b/Roles/Crewmate/Alchemist.cs @@ -262,7 +262,7 @@ public class Alchemist : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = VentCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } bool OnCoEnterVent(PlayerPhysics instance, int ventId) diff --git a/Roles/Crewmate/Altruist.cs b/Roles/Crewmate/Altruist.cs index 9180d97bb..6d3e2636f 100644 --- a/Roles/Crewmate/Altruist.cs +++ b/Roles/Crewmate/Altruist.cs @@ -57,7 +57,7 @@ public class Altruist : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = 0.1f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public static bool OnAnyoneCheckReportDeadBody(PlayerControl reporter, NetworkedPlayerInfo target) diff --git a/Roles/Crewmate/Astral.cs b/Roles/Crewmate/Astral.cs index b3beca224..7c4836597 100644 --- a/Roles/Crewmate/Astral.cs +++ b/Roles/Crewmate/Astral.cs @@ -50,7 +50,7 @@ public class Astral : RoleBase if (Options.UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = AbilityCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; try { AURoleOptions.GuardianAngelCooldown = 900f; } catch { } diff --git a/Roles/Crewmate/CameraMan.cs b/Roles/Crewmate/CameraMan.cs index afbb2c394..7b796c130 100644 --- a/Roles/Crewmate/CameraMan.cs +++ b/Roles/Crewmate/CameraMan.cs @@ -79,7 +79,7 @@ public class CameraMan : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = VentCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnEnterVent(PlayerControl pc, Vent vent) diff --git a/Roles/Crewmate/Catcher.cs b/Roles/Crewmate/Catcher.cs index ff70e781e..c9af0188c 100644 --- a/Roles/Crewmate/Catcher.cs +++ b/Roles/Crewmate/Catcher.cs @@ -85,7 +85,7 @@ public class Catcher : RoleBase if (Options.UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = AbilityCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } private void PlaceTrap(PlayerControl pc) diff --git a/Roles/Crewmate/Clairvoyant.cs b/Roles/Crewmate/Clairvoyant.cs index 3f87cb231..bd275d46a 100644 --- a/Roles/Crewmate/Clairvoyant.cs +++ b/Roles/Crewmate/Clairvoyant.cs @@ -41,7 +41,7 @@ public class Clairvoyant : RoleBase if (Options.UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = 0.1f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } private static void UseAbility(PlayerControl pc) diff --git a/Roles/Crewmate/Convener.cs b/Roles/Crewmate/Convener.cs index 5997486f8..505083000 100644 --- a/Roles/Crewmate/Convener.cs +++ b/Roles/Crewmate/Convener.cs @@ -47,7 +47,7 @@ internal class Convener : RoleBase if (Options.UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = CD.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnPet(PlayerControl pc) diff --git a/Roles/Crewmate/Dad.cs b/Roles/Crewmate/Dad.cs index 6100b121b..a7680a9d5 100644 --- a/Roles/Crewmate/Dad.cs +++ b/Roles/Crewmate/Dad.cs @@ -183,7 +183,7 @@ public class Dad : RoleBase } AURoleOptions.EngineerCooldown = 0.1f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnReportDeadBody() diff --git a/Roles/Crewmate/DovesOfNeace.cs b/Roles/Crewmate/DovesOfNeace.cs index b3e853320..169bd1f5a 100644 --- a/Roles/Crewmate/DovesOfNeace.cs +++ b/Roles/Crewmate/DovesOfNeace.cs @@ -49,7 +49,7 @@ internal class DovesOfNeace : RoleBase if (UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = DovesOfNeaceCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void SetButtonTexts(HudManager hud, byte id) diff --git a/Roles/Crewmate/Drainer.cs b/Roles/Crewmate/Drainer.cs index b75bf2ca2..5c4231e93 100644 --- a/Roles/Crewmate/Drainer.cs +++ b/Roles/Crewmate/Drainer.cs @@ -60,7 +60,7 @@ public class Drainer : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte id) { AURoleOptions.EngineerCooldown = VentCD.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public static void OnAnyoneExitVent(PlayerControl pc) diff --git a/Roles/Crewmate/Druid.cs b/Roles/Crewmate/Druid.cs index 2ee5693f5..4dbcbd5fe 100644 --- a/Roles/Crewmate/Druid.cs +++ b/Roles/Crewmate/Druid.cs @@ -78,7 +78,7 @@ public class Druid : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = VentCooldown.GetInt(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public static void SendRPCAddTrigger(bool add, byte playerId, Vector2 position, string roomName = "") diff --git a/Roles/Crewmate/Grenadier.cs b/Roles/Crewmate/Grenadier.cs index 25a24e6c6..095c244fd 100644 --- a/Roles/Crewmate/Grenadier.cs +++ b/Roles/Crewmate/Grenadier.cs @@ -62,7 +62,7 @@ internal class Grenadier : RoleBase if (UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = GrenadierSkillCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override string GetProgressText(byte playerId, bool comms) diff --git a/Roles/Crewmate/Lighter.cs b/Roles/Crewmate/Lighter.cs index b4c78a687..059d7f174 100644 --- a/Roles/Crewmate/Lighter.cs +++ b/Roles/Crewmate/Lighter.cs @@ -62,7 +62,7 @@ internal class Lighter : RoleBase { if (!UsePets.GetBool()) { - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; AURoleOptions.EngineerCooldown = LighterSkillCooldown.GetFloat(); } diff --git a/Roles/Crewmate/Mayor.cs b/Roles/Crewmate/Mayor.cs index 69f5e6ec1..ef61a7a5a 100644 --- a/Roles/Crewmate/Mayor.cs +++ b/Roles/Crewmate/Mayor.cs @@ -43,7 +43,7 @@ internal class Mayor : RoleBase ? opt.GetInt(Int32OptionNames.EmergencyCooldown) : 300f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void SetButtonTexts(HudManager hud, byte id) diff --git a/Roles/Crewmate/Mole.cs b/Roles/Crewmate/Mole.cs index 35a401083..a5d104146 100644 --- a/Roles/Crewmate/Mole.cs +++ b/Roles/Crewmate/Mole.cs @@ -35,7 +35,7 @@ internal class Mole : RoleBase { if (UsePets.GetBool()) return; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; AURoleOptions.EngineerCooldown = CD.GetFloat(); } diff --git a/Roles/Crewmate/NiceHacker.cs b/Roles/Crewmate/NiceHacker.cs index da999a9bb..13e72c38f 100644 --- a/Roles/Crewmate/NiceHacker.cs +++ b/Roles/Crewmate/NiceHacker.cs @@ -86,7 +86,7 @@ public class NiceHacker : RoleBase if (UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = AbilityCD.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public static void SendRPC(byte playerId, float secondsLeft) diff --git a/Roles/Crewmate/Oxyman.cs b/Roles/Crewmate/Oxyman.cs index 481a68e8e..5aa2c5c4c 100644 --- a/Roles/Crewmate/Oxyman.cs +++ b/Roles/Crewmate/Oxyman.cs @@ -71,7 +71,7 @@ public class Oxyman : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = 0f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnEnterVent(PlayerControl pc, Vent vent) diff --git a/Roles/Crewmate/Paranoia.cs b/Roles/Crewmate/Paranoia.cs index 6d56fafb5..c39d9a419 100644 --- a/Roles/Crewmate/Paranoia.cs +++ b/Roles/Crewmate/Paranoia.cs @@ -49,7 +49,7 @@ internal class Paranoia : RoleBase ? ParanoiaVentCooldown.GetFloat() : 300f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void SetButtonTexts(HudManager hud, byte id) diff --git a/Roles/Crewmate/Perceiver.cs b/Roles/Crewmate/Perceiver.cs index c80524054..850c001b7 100644 --- a/Roles/Crewmate/Perceiver.cs +++ b/Roles/Crewmate/Perceiver.cs @@ -55,7 +55,7 @@ internal class Perceiver : RoleBase if (Options.UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = CD.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnPet(PlayerControl pc) diff --git a/Roles/Crewmate/Rhapsode.cs b/Roles/Crewmate/Rhapsode.cs index 85fef3c5f..a96db2d62 100644 --- a/Roles/Crewmate/Rhapsode.cs +++ b/Roles/Crewmate/Rhapsode.cs @@ -80,7 +80,7 @@ public class Rhapsode : RoleBase if (Options.UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = AbilityCooldown.GetInt(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnEnterVent(PlayerControl pc, Vent vent) diff --git a/Roles/Crewmate/SecurityGuard.cs b/Roles/Crewmate/SecurityGuard.cs index 20a1a46c3..4493d2c63 100644 --- a/Roles/Crewmate/SecurityGuard.cs +++ b/Roles/Crewmate/SecurityGuard.cs @@ -51,7 +51,7 @@ internal class SecurityGuard : RoleBase { if (UsePets.GetBool()) return; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; AURoleOptions.EngineerCooldown = SecurityGuardSkillCooldown.GetFloat(); } diff --git a/Roles/Crewmate/Sentinel.cs b/Roles/Crewmate/Sentinel.cs index 206b72039..ad0ad9f28 100644 --- a/Roles/Crewmate/Sentinel.cs +++ b/Roles/Crewmate/Sentinel.cs @@ -182,7 +182,7 @@ internal class Sentinel : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = PatrolCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnFixedUpdate(PlayerControl pc) diff --git a/Roles/Crewmate/Telekinetic.cs b/Roles/Crewmate/Telekinetic.cs index 783619e27..2870e759c 100644 --- a/Roles/Crewmate/Telekinetic.cs +++ b/Roles/Crewmate/Telekinetic.cs @@ -64,7 +64,7 @@ public class Telekinetic : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = 0f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void OnFixedUpdate(PlayerControl pc) diff --git a/Roles/Crewmate/Tether.cs b/Roles/Crewmate/Tether.cs index 1b07b8e0d..811e8d37b 100644 --- a/Roles/Crewmate/Tether.cs +++ b/Roles/Crewmate/Tether.cs @@ -111,7 +111,7 @@ public class Tether : RoleBase if (UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = VentCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override bool OnVote(PlayerControl pc, PlayerControl target) diff --git a/Roles/Crewmate/TimeMaster.cs b/Roles/Crewmate/TimeMaster.cs index 98929638b..e746f5004 100644 --- a/Roles/Crewmate/TimeMaster.cs +++ b/Roles/Crewmate/TimeMaster.cs @@ -66,7 +66,7 @@ internal class TimeMaster : RoleBase if (UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = TimeMasterSkillCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override void SetButtonTexts(HudManager hud, byte id) diff --git a/Roles/Crewmate/Ventguard.cs b/Roles/Crewmate/Ventguard.cs index c93d36ade..b50ea8b7f 100644 --- a/Roles/Crewmate/Ventguard.cs +++ b/Roles/Crewmate/Ventguard.cs @@ -57,7 +57,7 @@ internal class Ventguard : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; AURoleOptions.EngineerCooldown = 15f; } diff --git a/Roles/Crewmate/Veteran.cs b/Roles/Crewmate/Veteran.cs index 14774f9c3..6b569cec9 100644 --- a/Roles/Crewmate/Veteran.cs +++ b/Roles/Crewmate/Veteran.cs @@ -54,7 +54,7 @@ internal class Veteran : RoleBase if (UsePets.GetBool()) return; AURoleOptions.EngineerCooldown = VeteranSkillCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override string GetProgressText(byte playerId, bool comms) diff --git a/Roles/Neutral/Magistrate.cs b/Roles/Neutral/Magistrate.cs index f163f5e8c..6d147e662 100644 --- a/Roles/Neutral/Magistrate.cs +++ b/Roles/Neutral/Magistrate.cs @@ -45,7 +45,7 @@ public class Magistrate : RoleBase { if (AbilityTrigger != AbilityTriggers.Vent) return; AURoleOptions.EngineerCooldown = 0.1f; - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override bool CanUseImpostorVentButton(PlayerControl pc) diff --git a/Roles/Neutral/Mario.cs b/Roles/Neutral/Mario.cs index 6f58ce813..2e7e9e05f 100644 --- a/Roles/Neutral/Mario.cs +++ b/Roles/Neutral/Mario.cs @@ -49,7 +49,7 @@ internal class Mario : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = MarioVentCD.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; } public override string GetProgressText(byte playerId, bool comms) diff --git a/Roles/Neutral/Tank.cs b/Roles/Neutral/Tank.cs index 6cc0eaef3..f38709685 100644 --- a/Roles/Neutral/Tank.cs +++ b/Roles/Neutral/Tank.cs @@ -47,7 +47,7 @@ public class Tank : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.EngineerCooldown = VentCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 0.1f; + AURoleOptions.EngineerInVentMaxTime = 0.3f; Main.AllPlayerSpeed[playerId] = Speed.GetFloat(); }