Compare commits

...
36 Commits
Author SHA1 Message Date
Ape 8e013830b6 1.8.0 2026-06-07 13:52:31 +02:00
Ape 5e74dd1f84 1.7.7 2026-06-05 12:56:13 +02:00
Ape ca39da4d64 fix (3) 2026-06-04 15:35:43 +02:00
Ape 5558350749 fix (2) 2026-06-04 15:34:20 +02:00
Ape 9a0b38c276 Fix 2026-06-04 15:31:03 +02:00
Ape 0f2516fdf5 Mostly bug fixes, some changes 2026-06-04 15:17:19 +02:00
Ape 3ead1b0a69 Whoops 2026-06-02 21:30:07 +02:00
Ape 4e912082db A few small changes 2026-06-02 17:42:13 +02:00
Ape 3c380c1b51 1.7.4 2026-05-31 00:54:48 +02:00
Ape 71461583b3 That was not a fun surpirse 2026-05-29 16:46:00 +02:00
Ape 81c20d4706 1.7.3 Part Three 2026-05-29 15:41:12 +02:00
Ape 94c0049939 1.7.3 Part Two 2026-05-29 15:28:48 +02:00
Ape 1c3224396c 1.7.3 Part One 2026-05-29 00:01:19 +02:00
Ape de4f057899 1.7.2 2026-05-14 21:59:09 +02:00
Ape 3e4d833b66 1.7.1 2026-04-12 19:07:06 +02:00
Ape 6a5fbe7300 1.7.0 2026-04-01 12:58:58 +02:00
Ape fbf9b2b6eb 3 Small fixes 2026-04-01 12:49:21 +02:00
Ape 7da659af7b 1.6.6 2026-03-30 17:42:23 +02:00
Ape 58df006f07 Yeah I still can't fix the dumb level stuff 2026-03-30 17:38:29 +02:00
Ape 0f373b8328 Super important change 2026-03-27 20:08:15 +01:00
Ape 16ed549de4 Update ExilePatch.cs 2026-03-27 20:06:29 +01:00
Ape bc2aa74046 .. Why did it do that? 2026-03-27 19:58:41 +01:00
Ape 45859032bd Merge branch 'main' of https://github.com/ApeMV/AmongUsRevamped 2026-03-27 19:57:32 +01:00
Ape 66a5eb0b09 Small fixes and optimize FixedUpdate 2026-03-27 19:55:57 +01:00
Ape 95306ba8a9 1.6.4 2026-03-22 13:30:08 +01:00
Ape 2ee17166f2 The sizes of your fixes don't matter 2026-03-22 13:09:14 +01:00
Ape 10bae07af1 The size of your fix doesn't matter 2026-03-03 20:47:17 +01:00
Ape df0a68ff19 1.6.2 2026-02-25 14:58:09 +01:00
Ape 69ecb3c7a0 Fix start detection, few more strings 2026-02-25 14:26:50 +01:00
Ape b30fa9a1e7 Finishing what was started III 2026-02-24 22:15:33 +01:00
Ape aa56c78c70 Finishing what was started II 2026-02-23 21:52:31 +01:00
Ape cd1de51a1f Finishing what was started I 2026-02-22 23:29:30 +01:00
Ape 6d0d80b736 Experimental chat in game 2026-02-22 18:37:15 +01:00
Ape 9af84609d9 New moderator system and /reload fix 2026-02-21 23:28:41 +01:00
Ape af67b4a0c4 1.6.0 2026-02-21 16:44:26 +01:00
Ape c4b6e5709f Fix role assign problems and some strings 2026-02-21 16:42:22 +01:00
30 changed files with 2135 additions and 465 deletions

No files matched your search

+9 -3
View File
@@ -30,11 +30,12 @@ public partial class Main : BasePlugin
public static ConfigEntry<string> Preset5 { get; private set; }
public static ConfigEntry<bool> GM { get; private set; }
public static ConfigEntry<bool> UnlockFps { get; private set; }
public static ConfigEntry<bool> ShowFps { get; private set; }
public static ConfigEntry<bool> AutoStart { get; private set; }
public static ConfigEntry<bool> DarkTheme { get; private set; }
public static ConfigEntry<bool> LobbyMusic { get; private set; }
public static ConfigEntry<bool> DisableInfoWhenDead { get; private set; }
public static ConfigEntry<bool> 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,11 +43,12 @@ public partial class Main : BasePlugin
public static bool HasArgumentException;
public static string CredentialsText;
public const string ModVersion = "v1.5.3";
public const string ModVersion = "v1.8.0";
public static float GameTimer;
public static readonly Dictionary<int, int> SayStartTimes = [];
public static readonly Dictionary<int, int> SayDeniedWordTimes = [];
public static PlayerControl[] AllPlayerControls
{
@@ -85,16 +87,20 @@ public partial class Main : BasePlugin
AutoStart = Config.Bind("Client Options", "Auto Start", false);
GM = Config.Bind("Client Options", "Game Master", false);
UnlockFps = Config.Bind("Client Options", "Unlock FPS", false);
ShowFps = Config.Bind("Client Options", "Show FPS", false);
AutoStart = Config.Bind("Client Options", "Auto Start", false);
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();
ConsoleManager.DetachConsole();
}
[HarmonyPatch(typeof(ModManager), nameof(ModManager.LateUpdate))]
+1 -1
View File
@@ -18,7 +18,7 @@
<ItemGroup>
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" ExcludeAssets="runtime;native" />
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.11.18" PrivateAssets="all" Condition="'$(Configuration)' == 'Release'"/>
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2026.6.5" PrivateAssets="all" Condition="'$(Configuration)' == 'Release'"/>
<PackageReference Include="AmongUs.GameLibs.Android" Version="2025.10.14" PrivateAssets="all" Condition="'$(Configuration)' == 'Android'"/>
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
+112 -31
View File
@@ -20,9 +20,14 @@ public static class BanManager
#endif
public static string RemoveHtmlTags(this string str) => Regex.Replace(str, "<[^>]*?>", "");
private static readonly string DenyNameListPath = $"{DataPath}/AUR-DATA/DenyNameList.txt";
private static string BanListPath = $"{DataPath}/AUR-DATA/BanList.txt";
private static string ModeratorListPath = $"{DataPath}/AUR-DATA/ModeratorList.txt";
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";
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<string, string> Templates = new();
public static List<string> TempBanWhiteList = [];
public static void Init()
{
@@ -30,21 +35,15 @@ public static class BanManager
{
if (!Directory.Exists($"{DataPath}/AUR-DATA")) Directory.CreateDirectory($"{DataPath}/AUR-DATA");
if (!File.Exists(DenyNameListPath))
{
Logger.Warn("Creating a new DenyNameList.txt file", "BanManager");
File.Create(DenyNameListPath).Close();
}
if (!File.Exists(BanListPath))
{
Logger.Warn("Creating a new BanList.txt file", "BanManager");
File.Create(BanListPath).Close();
}
if (!File.Exists(ModeratorListPath))
{
Logger.Warn("Creating a new ModeratorList.txt file", "BanManager");
File.Create(ModeratorListPath).Close();
}
CheckFile(DenyNameListPath, Translator.Get("bannameWelcome"), "DeniedNames.txt");
CheckFile(BanListPath, Translator.Get("banlistWelcome"), "Banlist.txt");
CheckFile(BanWordPath, Translator.Get("banwordWelcome"), "DeniedWords.txt");
CheckFile(VipListPath, Translator.Get("vipWelcome"), "VIP.txt");
CheckFile(ModeratorListPath, Translator.Get("moderatorWelcome"), "Moderator.txt");
CheckFile(AdminListPath, Translator.Get("adminWelcome"), "Admin.txt");
CheckFile(TemplatePath, Translator.Get("templateWelcome"), "Templates.txt");
LoadTemplates();
}
catch (Exception ex)
@@ -99,7 +98,7 @@ public static class BanManager
string friendcode = player?.FriendCode;
// Check file BanList.txt
if (Options.ApplyBanList.GetBool() && CheckBanList(friendcode, player?.GetHashedPuid()))
if (CheckBanList(friendcode, player?.GetHashedPuid()))
{
AmongUsClient.Instance.KickPlayer(player.Id, true);
Logger.Info($"{player.PlayerName} was in the BanList and has been banned", "BanListBan");
@@ -135,6 +134,7 @@ public static class BanManager
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.StartsWith("#")) continue;
if (line == "") continue;
if (!OnlyCheckPuid)
{
@@ -152,30 +152,111 @@ public static class BanManager
}
public static bool IsPlayerInDenyName(ClientData client, string name)
{
if (name == "" || !AmongUsClient.Instance.AmHost || !Options.ApplyDenyNameList.GetBool()) return false;
if (name == "" || !AmongUsClient.Instance.AmHost) return false;
var deniedNames = File.ReadAllLines(DenyNameListPath);
var deniedNames = File.ReadAllLines(DenyNameListPath).Where(x => !x.StartsWith("#"));
if (deniedNames.Where(code => !string.IsNullOrWhiteSpace(code)).Any(code => name.Contains(code, StringComparison.OrdinalIgnoreCase)))
{
AmongUsClient.Instance.KickPlayer(client.Id, false);
Logger.Info($" {name} was kicked because their name was in DenyNameList.txt", "Kick");
Logger.SendInGame($" {name} was kicked because their name was in DenyNameList.txt");
Logger.SendInGame($"{name} was kicked because their name was in DenyNameList.txt");
return true;
}
else return false;
}
}
[HarmonyPatch(typeof(BanMenu), nameof(BanMenu.Select))]
class BanMenuSelectPatch
{
public static void Postfix(BanMenu __instance, int clientId)
public static bool IsWordBanned(PlayerControl player, string input)
{
ClientData recentClient = AmongUsClient.Instance.GetRecentClient(clientId);
if (recentClient == null) return;
if (input == "" || !AmongUsClient.Instance.AmHost || Utils.CheckAccessLevel(player.Data.FriendCode) > 0) return false;
if (!BanManager.CheckBanList(recentClient?.FriendCode, recentClient?.GetHashedPuid()))
__instance.BanButton.GetComponent<ButtonRolloverHandler>().SetEnabledColors();
int clientId = player.Data.ClientId;
var bannedWords = File.ReadAllLines(BanWordPath).Where(x => !x.StartsWith("#"));
if (bannedWords.Where(code => !string.IsNullOrWhiteSpace(code)).Any(code => input.Contains(code, StringComparison.OrdinalIgnoreCase)))
{
if (!Main.SayDeniedWordTimes.ContainsKey(clientId))
{
Main.SayDeniedWordTimes.Add(clientId, 0);
}
Main.SayDeniedWordTimes[clientId]++;
if (Main.SayDeniedWordTimes[clientId] >= Options.DeniedWordsToKick.GetInt())
{
AmongUsClient.Instance.KickPlayer(clientId, false);
Logger.Info(Translator.Get("banWordKick", player.Data.PlayerName, Options.DeniedWordsToKick.GetInt()), "DeniedWordKick");
Logger.SendInGame(Translator.Get("banWordKick", player.Data.PlayerName, Options.DeniedWordsToKick.GetInt()));
}
return true;
}
else return false;
}
[HarmonyPatch(typeof(BanMenu), nameof(BanMenu.Select))]
class BanMenuSelectPatch
{
public static void Postfix(BanMenu __instance, int clientId)
{
ClientData recentClient = AmongUsClient.Instance.GetRecentClient(clientId);
if (recentClient == null) return;
if (!BanManager.CheckBanList(recentClient?.FriendCode, recentClient?.GetHashedPuid()))
__instance.BanButton.GetComponent<ButtonRolloverHandler>().SetEnabledColors();
}
}
public static void LoadTemplates()
{
Templates.Clear();
if (!File.Exists(TemplatePath)) return;
foreach (var line in File.ReadAllLines(TemplatePath))
{
if (string.IsNullOrWhiteSpace(line)) continue;
if (line.StartsWith("#")) continue;
int splitIndex = line.IndexOf(':');
if (splitIndex == -1) continue;
string key = line[..splitIndex].Trim().ToLower();
string value = line[(splitIndex + 1)..].Trim();
if (!Templates.ContainsKey(key)) Templates.Add(key, value);
}
}
private static void CheckFile(string path, string defaultContent, string name)
{
try
{
if (!File.Exists(path))
{
Logger.Warn($"Creating a new {name} file", "BanManager");
File.WriteAllText(path, defaultContent);
}
}
catch (Exception ex)
{
Logger.Exception(ex, "BanManager");
}
}
public static string CheckTemplate(string text)
{
Dictionary<string, string> variables = new()
{
{ "ModVersion", Main.ModVersion }
};
foreach (var kvp in variables)
{
text = text.Replace($"{{{kvp.Key}}}", kvp.Value);
}
return text;
}
}
+156
View File
@@ -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<Cmd> 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 || HudManager.Instance.Chat.freeChatField.textArea == null || __instance != HudManager.Instance.Chat.freeChatField.textArea) return;
if (Main.DisableCommandHelper.Value || !AmongUsClient.Instance.AmHost)
{
if (HelperText != null) 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<size=80%><color=#FF0000>{v.Description}</color></size>";
}
else if (u != null)
{
HelperText.text = u.Prompt;
}
else
{
HelperText.enabled = false;
return;
}
HelperText.enabled = true;
}
}
+189 -86
View File
@@ -38,12 +38,6 @@ namespace AmongUsRevamped
taskOptionsLoad = Task.Run(Load);
}
//[HarmonyPatch(typeof(MainMenuManager), nameof(MainMenuManager.Start)), HarmonyPostfix]
//public static void WaitOptionsLoad()
//{
//taskOptionsLoad.Wait();
//}
public const int PresetId = 0;
private static readonly string[] presets =
@@ -54,12 +48,21 @@ namespace AmongUsRevamped
public static readonly string[] gameModes =
{
"None", "0 Kill Cooldown", "Shift And Seek", "Speedrun"
"Standard", "0 Kill Cooldown", "Shift And Seek", "Speedrun"
};
public static readonly string[] colorLevels =
public static readonly string[] accessLevels =
{
"Moderators", "Everyone", "Nobody"
"Everyone", "<color=yellow>VIP</color> And Above", "<color=purple>Moderator</color> And Above", "<color=red>Admin</color>", "Only You"
};
public static readonly string[] crewmateAbilities =
{
"Mayor", "Workhorse", "Jester", "Tasker", "None"
};
public static readonly string[] impostorAbilities =
{
"Tyrant", "Stealer", "Juggernaut", "None"
};
//System
@@ -68,15 +71,13 @@ namespace AmongUsRevamped
public static OptionItem TabGroupMain;
public static OptionItem KickLowLevelPlayer;
public static OptionItem DontKickLevelOnes;
public static OptionItem TempBanLowLevelPlayer;
public static OptionItem KickInvalidFriendCodes;
public static OptionItem TempBanInvalidFriendCodes;
public static OptionItem ApplyBanList;
public static OptionItem ApplyDenyNameList;
public static OptionItem ApplyModeratorList;
public static OptionItem ModeratorCanUseCommand;
public static OptionItem DeniedWordsToKick;
public static OptionItem AutoKickStart;
public static OptionItem AutoKickStartAsBan;
@@ -90,6 +91,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;
@@ -97,6 +100,15 @@ namespace AmongUsRevamped
public static OptionItem ColorCommandLevel;
public static OptionItem AllowFortegreen;
public static OptionItem NoGameEnd;
public static OptionItem TabGroupAccess;
public static OptionItem SlashColorCmd;
public static OptionItem SlashRolesAndGamemodeCmd;
public static OptionItem SlashLastGameCmd;
public static OptionItem SlashKickCmd;
public static OptionItem SlashBanCmd;
public static OptionItem SlashEndMeetingCmd;
public static OptionItem SlashStartAndEndGameCmd;
//Gameplay
public static OptionItem TabGroupSabotages;
@@ -112,13 +124,13 @@ namespace AmongUsRevamped
public static OptionItem TabGroupGameplayGeneral;
public static OptionItem DisableAnnoyingMeetingCalls;
public static OptionItem DisableReport;
public static OptionItem ChangeDecontaminationTime;
public static OptionItem DecontaminationTimeOnMiraHQ;
public static OptionItem DecontaminationDoorOpenTimeOnMiraHQ;
public static OptionItem DecontaminationTimeOnPolus;
public static OptionItem DecontaminationDoorOpenTimeOnPolus;
public static OptionItem DisableSporeTrigger;
public static OptionItem DisableDevices;
private static OptionItem DisableSkeldDevices;
@@ -143,8 +155,8 @@ namespace AmongUsRevamped
public static OptionItem TabGroupTasks;
public static OptionItem OverrideTaskSettings;
public static OptionItem AllPlayersSameTasks;
public static OptionItem TaskPercentNeededToWin;
public static OptionItem DisableMiraTasks;
@@ -250,7 +262,6 @@ namespace AmongUsRevamped
public static OptionItem DisableSubmitScan;
public static OptionItem DisableUploadData;
// Gamemode
public static OptionItem TabGroupHNS;
public static OptionItem NumSeekers;
@@ -259,6 +270,7 @@ namespace AmongUsRevamped
public static OptionItem TabGroupSNS;
public static OptionItem SNSSettingsOverride;
public static OptionItem SNSChatInGame;
public static OptionItem CrewAutoWinsGameAfter;
public static OptionItem CantKillTime;
public static OptionItem MisfiresToSuicide;
@@ -274,15 +286,53 @@ namespace AmongUsRevamped
public static OptionItem TabGroupSpeedrun;
public static OptionItem SpeedrunSettingsOverride;
public static OptionItem GameAutoEndsAfter;
public static OptionItem EngineerMode;
// Roles
// Abilities
public static OptionItem TabGroupCrewmate;
public static OptionItem MayorPerc;
public static OptionItem TabGroupNeutral;
public static OptionItem JesterPerc;
public static OptionItem OverrideCrewmate;
public static OptionItem CrewmateAbility;
public static OptionItem OverrideScientist;
public static OptionItem ScientistAbility;
public static OptionItem OverrideEngineer;
public static OptionItem EngineerAbility;
public static OptionItem OverrideNoisemaker;
public static OptionItem NoisemakerAbility;
public static OptionItem OverrideTracker;
public static OptionItem TrackerAbility;
public static OptionItem OverrideDetective;
public static OptionItem DetectiveAbility;
public static OptionItem TabGroupCrewmateAbilities;
public static OptionItem ExtraVotesCrewmate;
public static OptionItem ExtraVotesPerTask;
public static OptionItem SpeedrunnerShortTasks;
public static OptionItem SpeedrunnerLongTasks;
public static OptionItem TabGroupImpostor;
public static OptionItem OverrideImpostor;
public static OptionItem ImpostorAbility;
public static OptionItem OverrideShapeshifter;
public static OptionItem ShapeshifterAbility;
public static OptionItem OverridePhantom;
public static OptionItem PhantomAbility;
public static OptionItem OverrideViper;
public static OptionItem ViperAbility;
public static OptionItem TabGroupImpostorAbilities;
public static OptionItem ExtraVotesImpostor;
public static OptionItem ExtraVotesPerKill;
public static OptionItem KillsNeededForJuggernaut;
public static bool IsLoaded = false;
@@ -301,20 +351,20 @@ namespace AmongUsRevamped
TabGroupMain = TextOptionItem.Create(60000, Translator.Get("tabGroupMain"), TabGroup.SystemSettings)
.SetColor(Color.blue);
DeniedWordsToKick = IntegerOptionItem.Create(60049, Translator.Get("deniedWordsToKick"), new(1, 5, 1), 1, TabGroup.SystemSettings, false)
.SetValueFormat(OptionFormat.Level);
KickLowLevelPlayer = IntegerOptionItem.Create(60050, Translator.Get("kickLowLevelPlayer"), new(0, 100, 1), 0, TabGroup.SystemSettings, false)
.SetValueFormat(OptionFormat.Level);
TempBanLowLevelPlayer = BooleanOptionItem.Create(60051, Translator.Get("tempBanLowLevelPlayer"), false, TabGroup.SystemSettings, false)
.SetParent(KickLowLevelPlayer);
DontKickLevelOnes = BooleanOptionItem.Create(60052, Translator.Get("dontKickLevelOnes"), false, TabGroup.SystemSettings, false)
.SetParent(KickLowLevelPlayer);
KickInvalidFriendCodes = BooleanOptionItem.Create(60080, Translator.Get("kickInvalidFriendCodes"), true, TabGroup.SystemSettings, false);
TempBanInvalidFriendCodes = BooleanOptionItem.Create(60081, Translator.Get("tempBanInvalidFriendCodes"), false, TabGroup.SystemSettings, false)
.SetParent(KickInvalidFriendCodes);
ApplyBanList = BooleanOptionItem.Create(60110, Translator.Get("applyBanList"), true, TabGroup.SystemSettings, true);
ApplyDenyNameList = BooleanOptionItem.Create(60120, Translator.Get("applyDenyNameList"), true, TabGroup.SystemSettings, false);
ApplyModeratorList = BooleanOptionItem.Create(60121, Translator.Get("applyModeratorList"), true, TabGroup.SystemSettings, false);
ModeratorCanUseCommand = BooleanOptionItem.Create(60122, Translator.Get("moderatorCanUseCommand"), true, TabGroup.SystemSettings, false);
AutoKickStart = BooleanOptionItem.Create(60123, Translator.Get("autoKickStart"), false, TabGroup.SystemSettings, false);
AutoKickStartAsBan = BooleanOptionItem.Create(60124, Translator.Get("autoKickStartAsBan"), false, TabGroup.SystemSettings, false)
.SetParent(AutoKickStart);
@@ -329,42 +379,94 @@ namespace AmongUsRevamped
AutoSendGameInfo = BooleanOptionItem.Create(60150, Translator.Get("autoSendGameInfo"), true, TabGroup.SystemSettings, false);
AutoRejoinLobby = BooleanOptionItem.Create(60210, Translator.Get("autoRejoinLobby"), false, TabGroup.SystemSettings, false);
AutoStartTimer = IntegerOptionItem.Create(64420, Translator.Get("autoStartTimer"), new(1, 600, 1), 5, TabGroup.SystemSettings, false)
AutoStartTimer = IntegerOptionItem.Create(64420, Translator.Get("autoStartTimer"), new(1, 5, 1), 5, TabGroup.SystemSettings, false)
.SetValueFormat(OptionFormat.Seconds);
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);
StartCountdown = IntegerOptionItem.Create(60380, Translator.Get("startCountdown"), new(1, 600, 1), 5, TabGroup.SystemSettings, false)
StartCountdown = IntegerOptionItem.Create(60380, Translator.Get("startCountdown"), new(1, 5, 1), 5, TabGroup.SystemSettings, false)
.SetValueFormat(OptionFormat.Seconds);
ColorCommandLevel = StringOptionItem.Create(60381, Translator.Get("colorCommandLevel"), colorLevels, 0, TabGroup.SystemSettings, false);
AllowFortegreen = BooleanOptionItem.Create(60382, Translator.Get("allowFortegreen"), false, TabGroup.SystemSettings, false);
NoGameEnd = BooleanOptionItem.Create(60383, Translator.Get("noGameEnd"), false, TabGroup.SystemSettings, false)
.SetColor(Color.red);
TabGroupAccess = TextOptionItem.Create(60400, Translator.Get("tabGroupAccess"), TabGroup.SystemSettings)
.SetColor(Color.red);
SlashColorCmd = StringOptionItem.Create(60401, Translator.Get("slashColorCmd"), accessLevels, 1, TabGroup.SystemSettings, false);
SlashRolesAndGamemodeCmd = StringOptionItem.Create(60402, Translator.Get("slashRolesAndGamemodeCmd"), accessLevels, 1, TabGroup.SystemSettings, false);
SlashLastGameCmd = StringOptionItem.Create(60403, Translator.Get("slashLastGameCmd"), accessLevels, 1, TabGroup.SystemSettings, false);
SlashKickCmd = StringOptionItem.Create(60405, Translator.Get("slashKickCmd"), accessLevels, 2, TabGroup.SystemSettings, false);
SlashBanCmd = StringOptionItem.Create(60406, Translator.Get("slashBanCmd"), accessLevels, 2, TabGroup.SystemSettings, false);
SlashEndMeetingCmd = StringOptionItem.Create(60407, Translator.Get("slashEndMeetingCmd"), accessLevels, 3, TabGroup.SystemSettings, false);
SlashStartAndEndGameCmd = StringOptionItem.Create(60408, Translator.Get("slashStartAndEndGameCmd"), accessLevels, 3, TabGroup.SystemSettings, false);
// Custom role settings
TabGroupCrewmate = TextOptionItem.Create(100000, Translator.Get("tabGroupCrewmate"), TabGroup.CustomRoleSettings)
// Ability settings
TabGroupCrewmate = TextOptionItem.Create(100000, Translator.Get("tabGroupCrewmate"), TabGroup.AbilitySettings)
.SetColor(CL.Hex("#8cffff"));
MayorPerc = IntegerOptionItem.Create(100001, Translator.Get("mayorPerc"), new(0, 100, 5), 0, TabGroup.CustomRoleSettings, false)
.SetValueFormat(OptionFormat.Percent)
.SetColor(CL.Hex("#204d42"));
TabGroupNeutral = TextOptionItem.Create(101000, Translator.Get("tabGroupNeutral"), TabGroup.CustomRoleSettings)
.SetColor(CL.Hex("#FFFF99"));
JesterPerc = IntegerOptionItem.Create(101001, Translator.Get("jesterPerc"), new(0, 100, 5), 0, TabGroup.CustomRoleSettings, false)
.SetValueFormat(OptionFormat.Percent)
.SetColor(CL.Hex("#ec62a5"));
CrewmateAbility = StringOptionItem.Create(100001, Translator.Get("crewmateAbility"), crewmateAbilities, 4, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#8cffff"));
TabGroupImpostor = TextOptionItem.Create(102000, Translator.Get("tabGroupImpostor"), TabGroup.CustomRoleSettings)
ScientistAbility = StringOptionItem.Create(100101, Translator.Get("scientistAbility"), crewmateAbilities, 4, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#8cffff"));
EngineerAbility = StringOptionItem.Create(100201, Translator.Get("engineerAbility"), crewmateAbilities, 4, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#8cffff"));
NoisemakerAbility = StringOptionItem.Create(100301, Translator.Get("noisemakerAbility"), crewmateAbilities, 4, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#8cffff"));
TrackerAbility = StringOptionItem.Create(100401, Translator.Get("trackerAbility"), crewmateAbilities, 4, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#8cffff"));
DetectiveAbility = StringOptionItem.Create(100501, Translator.Get("detectiveAbility"), crewmateAbilities, 4, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#8cffff"));
TabGroupCrewmateAbilities = TextOptionItem.Create(101000, Translator.Get("tabGroupCrewmateAbilities"), TabGroup.AbilitySettings)
.SetColor(CL.Hex("#8cffff"));
ExtraVotesCrewmate = IntegerOptionItem.Create(101001, Translator.Get("extraVotesCrewmate"), new(1, 15, 1), 1, TabGroup.AbilitySettings, false)
.SetValueFormat(OptionFormat.Level);
ExtraVotesPerTask = FloatOptionItem.Create(101002, Translator.Get("extraVotesPerTask"), new(0.25f, 3f, 0.25f), 0.5f, TabGroup.AbilitySettings, false)
.SetValueFormat(OptionFormat.Level);
SpeedrunnerShortTasks = IntegerOptionItem.Create(101003, Translator.Get("speedrunnerShortTasks"), new(0, 15, 1), 4, TabGroup.AbilitySettings, false)
.SetValueFormat(OptionFormat.Level);
SpeedrunnerLongTasks = IntegerOptionItem.Create(101004, Translator.Get("speedrunnerLongTasks"), new(0, 15, 1), 3, TabGroup.AbilitySettings, false)
.SetValueFormat(OptionFormat.Level);
TabGroupImpostor = TextOptionItem.Create(102000, Translator.Get("tabGroupImpostor"), TabGroup.AbilitySettings)
.SetColor(CL.Hex("#ff1919"));
ImpostorAbility = StringOptionItem.Create(100002, Translator.Get("impostorAbility"), impostorAbilities, 3, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#ff1919"));
ShapeshifterAbility = StringOptionItem.Create(102101, Translator.Get("shapeshifterAbility"), impostorAbilities, 3, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#ff1919"));
PhantomAbility = StringOptionItem.Create(102201, Translator.Get("phantomAbility"), impostorAbilities, 3, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#ff1919"));
ViperAbility = StringOptionItem.Create(102301, Translator.Get("viperAbility"), impostorAbilities, 3, TabGroup.AbilitySettings, false)
.SetColor(CL.Hex("#ff1919"));
TabGroupImpostorAbilities = TextOptionItem.Create(103000, Translator.Get("tabGroupImpostorAbilities"), TabGroup.AbilitySettings)
.SetColor(CL.Hex("#ff1919"));
ExtraVotesImpostor = IntegerOptionItem.Create(103001, Translator.Get("extraVotesImpostor"), new(1, 15, 1), 1, TabGroup.AbilitySettings, false)
.SetValueFormat(OptionFormat.Level);
ExtraVotesPerKill = FloatOptionItem.Create(103002, Translator.Get("extraVotesPerKill"), new(0.25f, 3f, 0.25f), 0.5f, TabGroup.AbilitySettings, false)
.SetValueFormat(OptionFormat.Level);
KillsNeededForJuggernaut = IntegerOptionItem.Create(103003, Translator.Get("killsNeededForJuggernaut"), new(3, 15, 1), 7, TabGroup.AbilitySettings, false)
.SetValueFormat(OptionFormat.Level);
// Gamemode Settings
TabGroupHNS = TextOptionItem.Create(70000, Translator.Get("tabGroupHNS"), TabGroup.GamemodeSettings)
.SetColor(Color.green);
NumSeekers = IntegerOptionItem.Create(70001, Translator.Get("numSeekers"), new(1, 15, 1), 1, TabGroup.GamemodeSettings, false)
@@ -377,6 +479,7 @@ namespace AmongUsRevamped
TabGroupSNS = TextOptionItem.Create(70050, Translator.Get("tabGroupSNS"), TabGroup.GamemodeSettings)
.SetColor(Color.yellow);
SNSSettingsOverride = BooleanOptionItem.Create(70051, Translator.Get("snsSettingsOverride"), true, TabGroup.GamemodeSettings, false);
SNSChatInGame = BooleanOptionItem.Create(70063, Translator.Get("snsChatInGame"), false, TabGroup.GamemodeSettings, false);
CantKillTime = IntegerOptionItem.Create(70053, Translator.Get("cantKillTime"), new(0, 60, 5), 20, TabGroup.GamemodeSettings, false)
.SetValueFormat(OptionFormat.Seconds);
MisfiresToSuicide = IntegerOptionItem.Create(70052, Translator.Get("misfiresToSuicide"), new(1, 10, 1), 2, TabGroup.GamemodeSettings, false);
@@ -410,6 +513,7 @@ namespace AmongUsRevamped
SpeedrunSettingsOverride = BooleanOptionItem.Create(70076, Translator.Get("speedrunSettingsOverride"), true, TabGroup.GamemodeSettings, false);
GameAutoEndsAfter = IntegerOptionItem.Create(70077, Translator.Get("gameAutoEndsAfter"), new(0, 600, 10), 300, TabGroup.GamemodeSettings, false)
.SetValueFormat(OptionFormat.Seconds);
EngineerMode = BooleanOptionItem.Create(70078, Translator.Get("engineerMode"), false, TabGroup.GamemodeSettings, false);
// Gameplay Settings
TabGroupSabotages = TextOptionItem.Create(60450, Translator.Get("tabGroupSabotages"), TabGroup.ModSettings)
@@ -443,8 +547,6 @@ namespace AmongUsRevamped
.SetColor(Color.blue);
DisableAnnoyingMeetingCalls = BooleanOptionItem.Create(60565, Translator.Get("disableAnnoyingMeetingCalls"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(19, 188, 233, byte.MaxValue));
DisableReport = BooleanOptionItem.Create(60520, Translator.Get("disableReport"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(19, 188, 233, byte.MaxValue));
ChangeDecontaminationTime = BooleanOptionItem.Create(60550, Translator.Get("changeDecontaminationTime"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(19, 188, 233, byte.MaxValue));
@@ -465,6 +567,9 @@ namespace AmongUsRevamped
.SetValueFormat(OptionFormat.Seconds)
.SetColor(new Color32(19, 188, 233, byte.MaxValue));
DisableSporeTrigger = BooleanOptionItem.Create(60558, Translator.Get("disableSporeTrigger"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(19, 188, 233, byte.MaxValue));
DisableDevices = BooleanOptionItem.Create(22900, Translator.Get("disableDevices"), false, TabGroup.ModSettings, false)
.SetColor(Color.red);
@@ -517,99 +622,97 @@ namespace AmongUsRevamped
.SetParent(DisableAirshipDevices)
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
DisableFungleDevices = BooleanOptionItem.Create(22925, "Disable Fungle Devices", false, TabGroup.ModSettings, false)
DisableFungleDevices = BooleanOptionItem.Create(22925, Translator.Get("disableFungleDevices"), false, TabGroup.ModSettings, false)
.SetParent(DisableDevices)
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
DisableFungleCamera = BooleanOptionItem.Create(22926, "Disable Fungle Camera", false, TabGroup.ModSettings, false)
DisableFungleCamera = BooleanOptionItem.Create(22926, Translator.Get("disableFungleCamera"), false, TabGroup.ModSettings, false)
.SetParent(DisableFungleDevices)
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
DisableFungleVital = BooleanOptionItem.Create(22927, "Disable Fungle Vitals", false, TabGroup.ModSettings, false)
DisableFungleVital = BooleanOptionItem.Create(22927, Translator.Get("disableFungleVital"), false, TabGroup.ModSettings, false)
.SetParent(DisableFungleDevices)
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
TabGroupTasks = TextOptionItem.Create(22997, "Tasks", TabGroup.ModSettings)
TabGroupTasks = TextOptionItem.Create(22995, Translator.Get("tabGroupTasks"), TabGroup.ModSettings)
.SetColor(Color.yellow);
AllPlayersSameTasks = BooleanOptionItem.Create(22998, "Everyone has same tasks", false, TabGroup.ModSettings, false)
TaskPercentNeededToWin = IntegerOptionItem.Create(22996, Translator.Get("taskPercentNeededToWin"), new(30, 100, 5), 100, TabGroup.ModSettings, false)
.SetColor(new Color32(255, 255, 153, byte.MaxValue))
.SetValueFormat(OptionFormat.Percent);
AllPlayersSameTasks = BooleanOptionItem.Create(22998, Translator.Get("allPlayersSameTasks"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(255, 255, 153, byte.MaxValue));
OverrideTaskSettings = BooleanOptionItem.Create(22999, Translator.Get("overrideTaskSettings"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(255, 255, 153, byte.MaxValue));
OverrideTaskSettings = BooleanOptionItem.Create(22999, "<#ffd>Di<#ffb>sa<#ff9>bl<#ffb>e T<#ffd>as<#ffb>ks", false, TabGroup.ModSettings, false)
.SetColor(new Color32(239, 89, 175, byte.MaxValue));
DisableMiraTasks = BooleanOptionItem.Create(23000, "Disable Mira HQ Tasks", false, TabGroup.ModSettings, false)
DisableMiraTasks = BooleanOptionItem.Create(23000, Translator.Get("disableMiraTasks"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(173, 216, 230, byte.MaxValue))
.SetParent(OverrideTaskSettings);
DisableBuyBeverage = BooleanOptionItem.Create(23001, "Disable Buy Beverage", false, TabGroup.ModSettings, false)
DisableBuyBeverage = BooleanOptionItem.Create(23001, Translator.Get("disableBuyBeverage"), false, TabGroup.ModSettings, false)
.SetParent(DisableMiraTasks);
DisableMeasureWeather = BooleanOptionItem.Create(23002, "Disable Measure Weather", false, TabGroup.ModSettings, false)
DisableMeasureWeather = BooleanOptionItem.Create(23002, Translator.Get("disableMeasureWeather"), false, TabGroup.ModSettings, false)
.SetParent(DisableMiraTasks);
DisableProcessData = BooleanOptionItem.Create(23003, "Disable Process Data", false, TabGroup.ModSettings, false)
DisableProcessData = BooleanOptionItem.Create(23003, Translator.Get("disableProcessData"), false, TabGroup.ModSettings, false)
.SetParent(DisableMiraTasks);
DisableRunDiagnostics = BooleanOptionItem.Create(23004, "Disable Run Diagnostics", false, TabGroup.ModSettings, false)
DisableRunDiagnostics = BooleanOptionItem.Create(23004, Translator.Get("disableRunDiagnostics"), false, TabGroup.ModSettings, false)
.SetParent(DisableMiraTasks);
DisableSortSamples = BooleanOptionItem.Create(23005, "Disable Sort Samples", false, TabGroup.ModSettings, false)
DisableSortSamples = BooleanOptionItem.Create(23005, Translator.Get("disableSortSamples"), false, TabGroup.ModSettings, false)
.SetParent(DisableMiraTasks);
DisablePolusTasks = BooleanOptionItem.Create(23100, "Disable Polus Tasks", false, TabGroup.ModSettings, false)
DisablePolusTasks = BooleanOptionItem.Create(23100, Translator.Get("disablePolusTasks"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(173, 216, 230, byte.MaxValue))
.SetParent(OverrideTaskSettings);
DisableActivateWeatherNodes = BooleanOptionItem.Create(23101, "Disable Activate Weather Nodes", false, TabGroup.ModSettings, false)
DisableActivateWeatherNodes = BooleanOptionItem.Create(23101, Translator.Get("disableActivateWeatherNodes"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableAlignTelescope = BooleanOptionItem.Create(23102, "Disable Align Telescope", false, TabGroup.ModSettings, false)
DisableAlignTelescope = BooleanOptionItem.Create(23102, Translator.Get("disableAlignTelescope"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableFillCanisters = BooleanOptionItem.Create(23103, "Disable Fill Canisters", false, TabGroup.ModSettings, false)
DisableFillCanisters = BooleanOptionItem.Create(23103, Translator.Get("disableFillCanisters"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableInsertKeys = BooleanOptionItem.Create(23104, "Disable Insert Keys", false, TabGroup.ModSettings, false)
DisableInsertKeys = BooleanOptionItem.Create(23104, Translator.Get("disableInsertKeys"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableOpenWaterways = BooleanOptionItem.Create(23105, "Disable Open Waterways", false, TabGroup.ModSettings, false)
DisableOpenWaterways = BooleanOptionItem.Create(23105, Translator.Get("disableOpenWaterways"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableRebootWifi = BooleanOptionItem.Create(23106, "Disable Reboot Wifi", false, TabGroup.ModSettings, false)
DisableRebootWifi = BooleanOptionItem.Create(23106, Translator.Get("disableRebootWifi"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableRepairDrill = BooleanOptionItem.Create(23107, "Disable Repair Drill", false, TabGroup.ModSettings, false)
DisableRepairDrill = BooleanOptionItem.Create(23107, Translator.Get("disableRepairDrill"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableScanBoardingPass = BooleanOptionItem.Create(23108, "Disable Scan Boarding Pass", false, TabGroup.ModSettings, false)
DisableScanBoardingPass = BooleanOptionItem.Create(23108, Translator.Get("disableScanBoardingPass"), false, TabGroup.ModSettings, false)
.SetParent(DisablePolusTasks);
DisableAirshipTasks = BooleanOptionItem.Create(23200, "Disable Airship Tasks", false, TabGroup.ModSettings, false)
DisableAirshipTasks = BooleanOptionItem.Create(23200, Translator.Get("disableAirshipTasks"), false, TabGroup.ModSettings, false)
.SetColor(new Color32(173, 216, 230, byte.MaxValue))
.SetParent(OverrideTaskSettings);
DisableCleanToilet = BooleanOptionItem.Create(23201, "Disable Clean Toilet", false, TabGroup.ModSettings, false)
DisableCleanToilet = BooleanOptionItem.Create(23201, Translator.Get("disableCleanToilet"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableDecontaminate = BooleanOptionItem.Create(23202, "Disable Decontaminate", false, TabGroup.ModSettings, false)
DisableDecontaminate = BooleanOptionItem.Create(23202, Translator.Get("disableDecontaminate"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableDevelopPhotos = BooleanOptionItem.Create(23203, "Disable Develop Photos", false, TabGroup.ModSettings, false)
DisableDevelopPhotos = BooleanOptionItem.Create(23203, Translator.Get("disableDevelopPhotos"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableDressMannequin = BooleanOptionItem.Create(23204, "Disable Dress Mannequin", false, TabGroup.ModSettings, false)
DisableDressMannequin = BooleanOptionItem.Create(23204, Translator.Get("disableDressMannequin"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableFixShower = BooleanOptionItem.Create(23205, "Disable Fix Shower", false, TabGroup.ModSettings, false)
DisableFixShower = BooleanOptionItem.Create(23205, Translator.Get("disableFixShower"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableMakeBurger = BooleanOptionItem.Create(23206, "Disable Make Burger", false, TabGroup.ModSettings, false)
DisableMakeBurger = BooleanOptionItem.Create(23206, Translator.Get("disableMakeBurger"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisablePickUpTowels = BooleanOptionItem.Create(23207, "Disable Pick Up Towels", false, TabGroup.ModSettings, false)
DisablePickUpTowels = BooleanOptionItem.Create(23207, Translator.Get("disablePickUpTowels"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisablePolishRuby = BooleanOptionItem.Create(23208, "Disable Polish Ruby", false, TabGroup.ModSettings, false)
DisablePolishRuby = BooleanOptionItem.Create(23208, Translator.Get("disablePolishRuby"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisablePutAwayPistols = BooleanOptionItem.Create(23209, "Disable Put Away Pistols", false, TabGroup.ModSettings, false)
DisablePutAwayPistols = BooleanOptionItem.Create(23209, Translator.Get("disablePutAwayPistols"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisablePutAwayRifles = BooleanOptionItem.Create(23210, "Disable Put Away Rifles", false, TabGroup.ModSettings, false)
DisablePutAwayRifles = BooleanOptionItem.Create(23210, Translator.Get("disablePutAwayRifles"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableRewindTapes = BooleanOptionItem.Create(23211, "Disable Rewind Tapes", false, TabGroup.ModSettings, false)
DisableRewindTapes = BooleanOptionItem.Create(23211, Translator.Get("disableRewindTapes"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableResetBreaker = BooleanOptionItem.Create(23212, "Disable Reset Breaker Task", false, TabGroup.ModSettings, false)
DisableResetBreaker = BooleanOptionItem.Create(23212, Translator.Get("disableResetBreaker"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableSortRecords = BooleanOptionItem.Create(23213, "Disable Sort Records", false, TabGroup.ModSettings, false)
DisableSortRecords = BooleanOptionItem.Create(23213, Translator.Get("disableSortRecords"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableStartFans = BooleanOptionItem.Create(23214, "Disable Start Fans", false, TabGroup.ModSettings, false)
DisableStartFans = BooleanOptionItem.Create(23214, Translator.Get("disableStartFans"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
DisableUnlockSafe = BooleanOptionItem.Create(23215, "Disable Unlock Safe Task", false, TabGroup.ModSettings, false)
DisableUnlockSafe = BooleanOptionItem.Create(23215, Translator.Get("disableUnlockSafe"), false, TabGroup.ModSettings, false)
.SetParent(DisableAirshipTasks);
+251 -8
View File
@@ -1,17 +1,238 @@
using AmongUs.GameOptions;
using Hazel;
using System;
using InnerNet;
using UnityEngine;
namespace AmongUsRevamped;
// It was a fun ride, but this won't last.
// Edit: WE ARE SO BACK
public static class AbilityManagement
{
public static bool IsMayor(PlayerControl player)
{
if (player.Data.RoleType == RoleTypes.Crewmate && Options.CrewmateAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Scientist && Options.ScientistAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Engineer && Options.EngineerAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Noisemaker && Options.NoisemakerAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Tracker && Options.TrackerAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Detective && Options.DetectiveAbility.GetValue() == 0)
{
return true;
}
else return false;
}
public static bool IsWorkhorse(PlayerControl player)
{
if (player.Data.RoleType == RoleTypes.Crewmate && Options.CrewmateAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Scientist && Options.ScientistAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Engineer && Options.EngineerAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Noisemaker && Options.NoisemakerAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Tracker && Options.TrackerAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Detective && Options.DetectiveAbility.GetValue() == 1)
{
return true;
}
else return false;
}
public static bool IsJester(PlayerControl player)
{
if (player.Data.RoleType == RoleTypes.Crewmate && Options.CrewmateAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Scientist && Options.ScientistAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Engineer && Options.EngineerAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Noisemaker && Options.NoisemakerAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Tracker && Options.TrackerAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Detective && Options.DetectiveAbility.GetValue() == 2)
{
return true;
}
else return false;
}
public static bool IsSpeedrunner(PlayerControl player)
{
if (player.Data.RoleType == RoleTypes.Crewmate && Options.CrewmateAbility.GetValue() == 3 ||
player.Data.RoleType == RoleTypes.Scientist && Options.ScientistAbility.GetValue() == 3 ||
player.Data.RoleType == RoleTypes.Engineer && Options.EngineerAbility.GetValue() == 3 ||
player.Data.RoleType == RoleTypes.Noisemaker && Options.NoisemakerAbility.GetValue() == 3 ||
player.Data.RoleType == RoleTypes.Tracker && Options.TrackerAbility.GetValue() == 3 ||
player.Data.RoleType == RoleTypes.Detective && Options.DetectiveAbility.GetValue() == 3)
{
return true;
}
else return false;
}
public static bool IsTyrant(PlayerControl player)
{
if (player.Data.RoleType == RoleTypes.Impostor && Options.ImpostorAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Shapeshifter && Options.ShapeshifterAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Phantom && Options.PhantomAbility.GetValue() == 0 ||
player.Data.RoleType == RoleTypes.Viper && Options.ViperAbility.GetValue() == 0)
{
return true;
}
else return false;
}
public static bool IsStealer(PlayerControl player)
{
if (player.Data.RoleType == RoleTypes.Impostor && Options.ImpostorAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Shapeshifter && Options.ShapeshifterAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Phantom && Options.PhantomAbility.GetValue() == 1 ||
player.Data.RoleType == RoleTypes.Viper && Options.ViperAbility.GetValue() == 1)
{
return true;
}
else return false;
}
public static bool IsJuggernaut(PlayerControl player)
{
if (player.Data.RoleType == RoleTypes.Impostor && Options.ImpostorAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Shapeshifter && Options.ShapeshifterAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Phantom && Options.PhantomAbility.GetValue() == 2 ||
player.Data.RoleType == RoleTypes.Viper && Options.ViperAbility.GetValue() == 2)
{
return true;
}
else return false;
}
public static string RoleList()
{
if (!AmongUsClient.Instance.AmHost) return "";
var lines = new List<string>();
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.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()}");
if (lines.Count == 0) return "";
return "ABILITIES:\n\n" + string.Join("\n", lines);
}
public static void SendRoleList(ChatController c, string text, bool moderator)
{
if (!AmongUsClient.Instance.AmHost) return;
if (string.IsNullOrEmpty(RoleList()) || Utils.isHideNSeek) return;
if (text.Length <= 120)
{
if (moderator) Utils.ModeratorChatCommand(text, "", false);
else Utils.ChatCommand(c, text, "", false);
return;
}
int splitIndex = text.LastIndexOf('\n', 120);
if (splitIndex <= 0) splitIndex = 120;
string first = text[..splitIndex];
string second = text[(splitIndex + 1)..];
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<HudManager>.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
{
public static Dictionary<byte, string> PlayerRoles = new Dictionary<byte, string>();
private static readonly System.Random random = new System.Random();
public static string GetRole(byte playerId)
{
PlayerRoles.TryGetValue(playerId, out string role);
return role ?? "None";
}
public static void AssignRoles()
{
if (Options.Gamemode.GetValue() > 1) return;
// crewmateRoles = assigned with crewmate role base
// impostorRoles = assigned with impostor role base
List<(string roleName, int percentage)> crewmateRoles = new()
@@ -40,14 +261,14 @@ public static class CustomRoleManagement
foreach (var (roleName, percentage) in rolesToAssign)
{
if (attemptedRoles.Contains(roleName)) continue;
if (attemptedRoles.Contains(roleName) || percentage == 0) continue;
attemptedRoles.Add(roleName);
int randomValue = random.Next(0, 101);
Logger.Info($"{roleName}, Value: {randomValue}, Percentage: {percentage}", "StartGameCustomRole1");
if (randomValue >= percentage) continue;
if (randomValue > percentage) continue;
if (PlayerRoles.ContainsKey(player.PlayerId)) continue;
PlayerRoles[player.PlayerId] = roleName;
@@ -73,7 +294,7 @@ public static class CustomRoleManagement
sb.Append(c);
}
return sb.ToString();
}
}
public static string GetActiveRoles()
{
@@ -107,29 +328,50 @@ public static class CustomRoleManagement
private static int PendingRoleMessages = 0;
public static void SendRoleMessages(Dictionary<string, string> roleMessages)
{
if (PlayerRoles.Count == 0 || PlayerControl.LocalPlayer.Data.IsDead)
{
HandlingRoleMessages = false;
PendingRoleMessages = 0;
return;
}
HashSet<string> sentRoles = new HashSet<string>();
var players = PlayerControl.AllPlayerControls.ToArray().ToList();
float delay = 0f;
float delay = 2.2f;
PendingRoleMessages = 0;
HandlingRoleMessages = false;
HandlingRoleMessages = true;
PlayerControl.LocalPlayer.RpcSendChat($"{Translator.Get("customRoleAnnouncement")}");
foreach (var player in players)
{
if (!PlayerRoles.TryGetValue(player.PlayerId, out string role)) continue;
PlayerRoles.TryGetValue(player.PlayerId, out string role);
if (string.IsNullOrEmpty(role)) continue;
if (!roleMessages.ContainsKey(role)) continue;
if (sentRoles.Contains(role)) continue;
PendingRoleMessages++;
new LateTask(() =>
{
Utils.SendPrivateMessage(player, roleMessages[role]);
if (Utils.InGame)
{
Utils.SendPrivateMessage(player, roleMessages[role]);
}
else
{
Logger.Info("Role sending was forcefully canceled. This should not happen.", "SendRoleMessages");
}
PendingRoleMessages--;
if (PendingRoleMessages <= 0)
{
PendingRoleMessages = 0;
HandlingRoleMessages = false;
sentRoles.Clear();
}
}, delay, "SendRoleMessage");
@@ -176,4 +418,5 @@ public static class CustomRoleManagement
}
return string.Join("\n", lines);
}
}
}
*/
+47 -57
View File
@@ -36,78 +36,68 @@ public static class FixedUpdate
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))]
class FixedUpdateInGamePatch
{
public static readonly HashSet<byte> ProcessedModerators = new HashSet<byte>();
private static Dictionary<byte, string> LastColors = new();
private static float t;
private static GameObject settingsLabel;
public static void Postfix(PlayerControl __instance)
{
if (__instance == null || __instance.PlayerId == 255 || !AmongUsClient.Instance.AmHost) return;
if (Utils.IsPlayerModerator(__instance.Data.FriendCode) && !ProcessedModerators.Contains(__instance.PlayerId))
t += Time.deltaTime;
if (t < 0.2f) return;
t = 0f;
if (Utils.IsLobby)
{
__instance.SetName($"★{__instance.Data.PlayerName}★");
ProcessedModerators.Add(__instance.PlayerId);
}
GameObject g = GameObject.Find("GameSettingsLabel");
// 0Kc
if (Options.Gamemode.GetValue() == 1 && !Utils.isHideNSeek && Main.NormalOptions.KillCooldown != 0.01f)
{
Main.NormalOptions.KillCooldown = 0.01f;
if (Options.NoKcdSettingsOverride.GetBool() && g == null)
int access = Utils.CheckAccessLevel(__instance.Data.FriendCode);
string color = access switch
{
Main.NormalOptions.EmergencyCooldown = 0;
1 => "yellow",
2 => "purple",
3 => "red",
_ => "white"
};
Main.NormalOptions.TaskBarMode = 0;
if (!LastColors.TryGetValue(__instance.PlayerId, out var lastColor) || lastColor != color || !__instance.cosmetics.nameText.text.Contains($"<color={color}>"))
{
__instance.cosmetics.nameText.text = $"<color={color}>{__instance.Data.PlayerName}</color>";
LastColors[__instance.PlayerId] = color;
}
}
// SnS
if (Options.Gamemode.GetValue() == 2 && !Utils.isHideNSeek && Main.NormalOptions.KillCooldown != 2.5f)
if (settingsLabel == null) settingsLabel = GameObject.Find("GameSettingsLabel");
int gamemode = Options.Gamemode.GetValue();
switch (gamemode)
{
Main.NormalOptions.KillCooldown = 2.5f;
case 1: // 0Kc
if (Main.NormalOptions.KillCooldown != 0.01f)
Main.NormalOptions.KillCooldown = 0.01f;
if (Options.SNSSettingsOverride.GetBool() && g == null)
{
Main.NormalOptions.TaskBarMode = 0;
}
}
if (Options.NoKcdSettingsOverride.GetBool() && settingsLabel == null)
{
Main.NormalOptions.EmergencyCooldown = 0;
Main.NormalOptions.TaskBarMode = 0;
}
break;
// Speedrun
if (Options.Gamemode.GetValue() == 3 && !Utils.isHideNSeek && g == null)
{
Main.NormalOptions.TaskBarMode = 0;
case 2: // SnS
if (Main.NormalOptions.KillCooldown != 2.5f)
Main.NormalOptions.KillCooldown = 2.5f;
if (__instance.AllTasksCompleted() && Utils.InGame && Utils.GamePastRoleSelection && !Utils.HandlingGameEnd)
{
if (__instance == PlayerControl.LocalPlayer && Main.GM.Value) return;
if (Options.SNSSettingsOverride.GetBool() && settingsLabel == null)
Main.NormalOptions.TaskBarMode = 0;
break;
Utils.CustomWinnerEndGame(__instance, 1);
NormalGameEndChecker.LastWinReason = $"★ {__instance.Data.PlayerName} Wins! (Completed tasks first)";
case 3: // Speedrun
break;
}
}
if (Options.Gamemode.GetValue() == 0 && Main.NormalOptions.KillCooldown <= 0.01f)
{
Main.NormalOptions.KillCooldown = 25f;
}
if (__instance.Data.PlayerLevel != 0 && __instance.Data.PlayerLevel < Options.KickLowLevelPlayer.GetInt() && __instance.Data.ClientId != AmongUsClient.Instance.HostId)
{
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()}");
}
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()}");
}
case 0: // Reset
if (Main.NormalOptions.KillCooldown <= 0.01f)
Main.NormalOptions.KillCooldown = 25f;
break;
}
if (Utils.InGame && !Utils.IsMeeting && !ExileController.Instance)
@@ -121,7 +111,7 @@ class FixedUpdateInGamePatch
Utils.ContinueEndGame((byte)GameOverReason.CrewmatesByVote);
Logger.Info($" Crewmates won because the game took longer than {Options.CrewAutoWinsGameAfter.GetInt()}s", "SNSManager");
NormalGameEndChecker.LastWinReason = $"★ Crewmates win! (Timer)\n\nImpostors:\n" + string.Join("\n", NormalGameEndChecker.imps.Select(p => p.Data.PlayerName));
NormalGameEndChecker.CheckWinnerText("SnSTimer");
}
}
// 3 = Speedrun
@@ -133,7 +123,7 @@ class FixedUpdateInGamePatch
Utils.CustomWinnerEndGame(PlayerControl.LocalPlayer, 0);
Logger.Info($" No one won because the game took longer than {Options.GameAutoEndsAfter.GetInt()}s", "SpeedrunManager");
NormalGameEndChecker.LastWinReason = $"★ No one wins! (Timer)";
NormalGameEndChecker.CheckWinnerText("NoOneWin");
}
}
}
+2
View File
@@ -12,6 +12,8 @@ internal class Hotkeys
public static int IncrementMultiplier;
public static void Postfix()
{
if (AmongUsClient.Instance == null || PlayerControl.LocalPlayer == null) return;
bool Shift = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
bool Ctrl = Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
bool Enter = Input.GetKeyDown(KeyCode.Return);
+2 -1
View File
@@ -214,7 +214,8 @@ namespace AmongUsRevamped
public enum TabGroup
{
SystemSettings,
CustomRoleSettings,
//CustomRoleSettings,
AbilitySettings,
ModSettings,
GamemodeSettings,
+18 -1
View File
@@ -77,7 +77,7 @@ public static class Translator
}
}
private static void LoadLanguage(SupportedLangs lang)
private static void LoadLanguage(SupportedLangs lang, bool reset = false)
{
string path = GetLanguagePath(lang);
@@ -121,6 +121,23 @@ public static class Translator
public static void Reload()
{
string path = GetLanguagePath(_currentLang);
var assembly = Assembly.GetExecutingAssembly();
string targetFile = $"{_currentLang}.json";
foreach (var name in assembly.GetManifestResourceNames())
{
if (name.EndsWith(targetFile, StringComparison.OrdinalIgnoreCase))
{
using var stream = assembly.GetManifestResourceStream(name);
using var reader = new StreamReader(stream);
string json = reader.ReadToEnd();
File.WriteAllText(path, json);
break;
}
}
LoadLanguage(_currentLang);
}
}
+85 -8
View File
@@ -47,13 +47,24 @@ public static class Utils
public static string ColorToHex(Color32 color) => $"#{color.r:x2}{color.g:x2}{color.b:x2}{color.a:x2}";
public static byte GetActiveMapId() => GameOptionsManager.Instance.CurrentGameOptions.MapId;
public static bool IsPlayerModerator(string friendCode)
public static int CheckAccessLevel(string friendCode)
{
if (friendCode == "") return false;
if (friendCode == "") return 0;
var friendCodesFilePath = @$"{BanManager.DataPath}/AUR-DATA/ModeratorList.txt";
var friendCodes = File.ReadAllLines(friendCodesFilePath);
return friendCodes.Any(code => code.Contains(friendCode));
var vipFilePath = @$"{BanManager.DataPath}/AUR-DATA/VIP.txt";
var vipFriendCodes = File.ReadAllLines(vipFilePath);
var moderatorFilePath = @$"{BanManager.DataPath}/AUR-DATA/Moderator.txt";
var moderatorFriendCodes = File.ReadAllLines(moderatorFilePath);
var adminFilePath = @$"{BanManager.DataPath}/AUR-DATA/Admin.txt";
var adminFriendCodes = File.ReadAllLines(adminFilePath);
if (adminFriendCodes.Any(code => code.Contains(friendCode))) return 3;
if (moderatorFriendCodes.Any(code => code.Contains(friendCode))) return 2;
if (vipFriendCodes.Any(code => code.Contains(friendCode))) return 1;
return 0;
}
public static string GetTabName(TabGroup tab)
@@ -62,8 +73,12 @@ public static class Utils
{
case TabGroup.SystemSettings:
return "System Settings";
/*
case TabGroup.CustomRoleSettings:
return "Custom Roles";
*/
case TabGroup.AbilitySettings:
return "Ability Settings";
case TabGroup.ModSettings:
return "Gameplay Settings";
case TabGroup.GamemodeSettings:
@@ -193,12 +208,32 @@ public static class Utils
HandlingGameEnd = false;
OnGameJoinedPatch.AutoStartCheck = false;
Main.GameTimer = 0f;
NormalGameEndChecker.canUpdateWinnerText = true;
MurderPlayerPatch.misfireCount.Clear();
LateTask.Tasks.Clear();
FixedUpdateInGamePatch.ProcessedModerators.Clear();
MurderPlayerPatch.killCount.Clear();
LateTask.Tasks.Clear();
NormalGameEndChecker.ImpCheckComplete = false;
CreateOptionsPickerPatch.SetDleks2 = false;
CanCallMeetings = true;
AbilityManagement.HandlingRoleMessages = false;
PlayerControlSetRolePatch.FirstAssign = true;
PlayerControlSetRolePatch.Jesters.Clear();
PlayerControlCompleteTaskPatch.playerTasksCompleted.Clear();
PlayerControlCompleteTaskPatch.tasksPerPlayer.Clear();
PlayerControlCompleteTaskPatch.tasksInitiated = false;
PlayerControlCompleteTaskPatch.ignoredCompletedTasks = 0;
PlayerControlCompleteTaskPatch.ignoredTasks = 0;
OnPlayerJoinedPatch.JoinNum = 0;
PlayerControlSetRolePatch.Seekers.Clear();
PlayerControlSetRolePatch.Jesters.Clear();
PlayerControlSetRolePatch.FirstAssign = true;
CoShowIntroPatch.ScheduleExile = false;
CoShowIntroPatch.IntroInitiated = false;
}
public static PlayerControl[] AllAlivePlayerControls
@@ -349,6 +384,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();
@@ -379,6 +416,8 @@ public static class Utils
public static void ModeratorChatCommand(string msg, string msg2, bool multi)
{
if (OnGameJoinedPatch.WaitingForChat) return;
OnGameJoinedPatch.WaitingForChat = true;
new LateTask(() =>
@@ -452,7 +491,6 @@ public static class Utils
AmongUsClient.Instance.FinishEndGame(writer);
HandlingGameEnd = false;
Logger.Info($"{gameOverReason}", "ContinueEndGame");
Logger.Info(" -------- GAME ENDED --------", "ContinueEndGame");
}
public static void DumpLog()
@@ -515,4 +553,43 @@ public static class Utils
}
return null;
}
public static void SetChatVisible()
{
PlayerControl.LocalPlayer.CmdReportDeadBody(null);
MeetingHud.Instance.RpcClose();
}
public static MethodBase GetStateMachineMoveNext<T>(string methodName)
{
var typeName = typeof(T).FullName;
var stateMachine = typeof(T).GetNestedTypes().FirstOrDefault(x => x.Name.Contains(methodName));
if (stateMachine == null)
{
Logger.Error($"Failed to find {methodName} state machine for {typeName}", "GetStateMachineMoveNext");
return null;
}
var moveNext = AccessTools.Method(stateMachine, "MoveNext");
if (moveNext == null)
{
Logger.Error($"Failed to find MoveNext method for {typeName}.{methodName}", "GetStateMachineMoveNext");
return null;
}
Logger.Info($"Found {methodName}.MoveNext", "GetStateMachineMoveNext");
return moveNext;
}
public static string GetRoleText(PlayerControl p)
{
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 || p.Data.RoleType == RoleTypes.ImpostorGhost)
{
return $"<color=#ff1919>{p.Data.RoleType}</color>";
}
else return $"<color=#8cffff>{p.Data.RoleType}</color>";
}
}
+376 -57
View File
@@ -1,6 +1,7 @@
using Hazel;
using InnerNet;
using System;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
@@ -91,8 +92,9 @@ internal static class SendChatPatch
if (!AmongUsClient.Instance.AmHost) return true;
if (text == "/reload" || text == "/translatereload" || text == "/reset" || text == "/translatereset")
if (text == "/reload")
{
HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, $"{Translator.Get("translationReloaded")}");
Translator.Reload();
__instance.freeChatField.textArea.Clear();
__instance.freeChatField.textArea.SetText(string.Empty);
@@ -106,8 +108,7 @@ internal static class SendChatPatch
__instance.freeChatField.textArea.SetText(string.Empty);
return false;
}
if (text == "/h" || text == "/help" || text == "/cmd" || text == "/commands")
if (text == "/help")
{
HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, $"{Translator.Get("allCommandsFull")}");
__instance.freeChatField.textArea.Clear();
@@ -115,6 +116,14 @@ internal static class SendChatPatch
return false;
}
if (text == "/s" || text == "/start")
{
GameStartManager.Instance.BeginGame();
__instance.freeChatField.textArea.Clear();
__instance.freeChatField.textArea.SetText(string.Empty);
return false;
}
if (text == "/eg" || text == "/endgame")
{
__instance.freeChatField.textArea.Clear();
@@ -137,45 +146,256 @@ 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);
return false;
}
}
if (text == "/r jester"){
Utils.ChatCommand(__instance, Translator.Get("jesterPublic"), "", false);
return false;}
if (text == "/aur" || text == "/amongusrevamped" || text == "/socials" || text == "/github" || text == "/discord")
if (text == "/r mayor"){
Utils.ChatCommand(__instance, Translator.Get("mayorPublic", Options.ExtraVotesCrewmate.GetInt()), "", false);
return false;}
if (text == "/r tyrant"){
Utils.ChatCommand(__instance, Translator.Get("tyrantPublic", Options.ExtraVotesImpostor.GetInt()), "", false);
return false;}
if (text == "/r workhorse"){
Utils.ChatCommand(__instance, Translator.Get("workhorsePublic", Options.ExtraVotesPerTask.GetFloat()), "", false);
return false;}
if (text == "/r stealer"){
Utils.ChatCommand(__instance, Translator.Get("stealerPublic", Options.ExtraVotesPerKill.GetFloat()), "", false);
return false;}
if (text == "/r juggernaut"){
Utils.ChatCommand(__instance, Translator.Get("juggernautPublic", Options.KillsNeededForJuggernaut.GetInt()), "", false);
return false;}
if (text == "/r tasker"){
Utils.ChatCommand(__instance, Translator.Get("speedrunnerPublic"), "", false);
return false;}
if (text == "/aur" || text == "/socials")
{
Utils.ChatCommand(__instance, Translator.Get("socialsAll"), "", false);
return false;
}
if (text == "/0kc" || text == "/0kcd" || text == "/0killcooldown")
if (text == "/0kc" || text == "/0killcooldown")
{
Utils.ChatCommand(__instance, Translator.Get("noKcdMode"), "", false);
return false;
}
if (text == "/sns" || text == "/shiftandseek" || text == "/shift&seek")
if (text == "/sns" || text == "/shiftandseek")
{
Utils.ChatCommand(__instance, Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
if (Options.MisfiresToSuicide.GetInt() == 1 || Options.CantKillTime.GetInt() == 0)
{
Utils.ChatCommand(__instance, Translator.Get("SnSModeOne"), Translator.Get("SnSModeThree", Options.CrewAutoWinsGameAfter.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
else
{
Utils.ChatCommand(__instance, Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
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())
{
case 0:
Utils.ChatCommand(__instance, $"Enabled Custom Roles:\n\n{CustomRoleManagement.GetActiveRoles()}", "", false);
AbilityManagement.SendRoleList(__instance, AbilityManagement.RoleList(), false);
break;
case 1:
@@ -183,7 +403,14 @@ internal static class SendChatPatch
break;
case 2:
Utils.ChatCommand(__instance, Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
if (Options.MisfiresToSuicide.GetInt() == 1 || Options.CantKillTime.GetInt() == 0)
{
Utils.ChatCommand(__instance, Translator.Get("SnSModeOne"), Translator.Get("SnSModeThree", Options.CrewAutoWinsGameAfter.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
else
{
Utils.ChatCommand(__instance, Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
break;
case 3:
@@ -196,8 +423,33 @@ internal static class SendChatPatch
__instance.freeChatField.textArea.SetText(string.Empty);
return false;
}
if (text.StartsWith("/t "))
{
string templateName = text[3..].Trim().ToLower();
if (BanManager.Templates.TryGetValue(templateName, out string templateMessage))
{
if (templateMessage.Length < 121)
{
Utils.ChatCommand(__instance, BanManager.CheckTemplate(templateMessage), "", false);
}
else
{
HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("tooLongTemplate"));
}
}
else
{
Logger.Info($"Could not find template '{templateName}'", "TemplateManager");
HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, $"Template '{templateName}' not found.");
}
__instance.freeChatField.textArea.Clear();
__instance.freeChatField.textArea.SetText(string.Empty);
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 ");
@@ -229,10 +481,10 @@ internal static class SendChatPatch
if (!isKick && !isBan && !isColorKick && !isColorBan)
{
__instance.freeChatField.textArea.SetText(converted);
Utils.ChatCommand(__instance, $"{converted}", "", false);
//__instance.freeChatField.textArea.SetText(converted);
//Utils.ChatCommand(__instance, $"{converted}", "", false);
Logger.Info($" {PlayerControl.LocalPlayer.Data.PlayerName}: {msgtext}", "SendChat");
return false;
return true;
}
string arg = text.Substring(isKick ? 6 : isBan ? 5 : isColorKick ? 7 : isColorBan ? 6 : 0).Trim();
@@ -303,7 +555,7 @@ public static class RPCHandlerPatch
c = keywords.Any(k => text == k);
}
if (c && !Utils.IsPlayerModerator(__instance.Data.FriendCode) && Options.AutoKickStart.GetBool() && !Utils.InGame)
if (c && Utils.CheckAccessLevel(__instance.Data.FriendCode) < 1 && Options.AutoKickStart.GetBool() && !Utils.InGame)
{
int clientId = __instance.Data.ClientId;
@@ -320,7 +572,9 @@ public static class RPCHandlerPatch
}
}
bool col1 = text.StartsWith("/col ") || text.StartsWith("/cor ");
BanManager.IsWordBanned(__instance, text);
bool col1 = text.StartsWith("/col ");
bool col2 = text.StartsWith("/color ");
bool col3 = text.StartsWith("/colour ");
@@ -330,7 +584,7 @@ public static class RPCHandlerPatch
if (Utils.TryGetColorId(argCol, out byte colId))
{
if (Options.ColorCommandLevel.GetValue() == 0 && Utils.IsPlayerModerator(__instance.Data.FriendCode) || Options.ColorCommandLevel.GetValue() == 1)
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) >= Options.SlashColorCmd.GetValue())
{
if (colId > 17 && !Options.AllowFortegreen.GetBool()) return;
__instance.RpcSetColor(colId);
@@ -349,7 +603,7 @@ public static class RPCHandlerPatch
if (isKick || isBan || isColorKick || isColorBan)
{
if (Utils.IsPlayerModerator(__instance.Data.FriendCode))
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) >= Options.SlashKickCmd.GetValue())
{
string arg = text.Substring(isKick ? 6 : isBan ? 5 : isColorKick ? 7 : isColorBan ? 6 : 0).Trim();
@@ -357,7 +611,7 @@ public static class RPCHandlerPatch
foreach (PlayerControl p in PlayerControl.AllPlayerControls)
{
if (p.Data == null || p == PlayerControl.LocalPlayer || Utils.IsPlayerModerator(p.Data.FriendCode)) continue;
if (p.Data == null || p == PlayerControl.LocalPlayer || Utils.CheckAccessLevel(p.Data.FriendCode) >= 1) continue;
if ((isKick || isBan) && p.Data.PlayerName.Equals(arg, StringComparison.OrdinalIgnoreCase))
{
@@ -374,6 +628,7 @@ public static class RPCHandlerPatch
}
}
}
if (banLog && Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashBanCmd.GetValue()) return;
if (target != null)
{
@@ -383,59 +638,76 @@ public static class RPCHandlerPatch
}
}
if (CustomRoleManagement.HandlingRoleMessages || OnGameJoinedPatch.WaitingForChat) return;
if (AbilityManagement.HandlingRoleMessages || OnGameJoinedPatch.WaitingForChat || GameStartManagerUpdatePatch.CountingDown) return;
if (text == "/h" || text == "/help" || text == "/cmd" || text == "/commands")
if (text == "/eg" || text == "/endgame")
{
if (!Utils.IsPlayerModerator(__instance.Data.FriendCode) || !Options.ModeratorCanUseCommand.GetBool()) 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 (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashStartAndEndGameCmd.GetValue()) return;
MessageWriter writer = AmongUsClient.Instance.StartEndGame();
writer.Write((byte)GameOverReason.ImpostorDisconnect);
AmongUsClient.Instance.FinishEndGame(writer);
}
if (text == "/l" || text == "/lastgame" || text == "/win" || text == "/winner")
if (text == "/em" || text == "/endmeeting")
{
if (!Utils.IsPlayerModerator(__instance.Data.FriendCode) || !Options.ModeratorCanUseCommand.GetBool()) return;
if (Utils.IsMeeting)
{
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashEndMeetingCmd.GetValue()) return;
MeetingHud.Instance.RpcClose();
}
}
if (text == "/s" || text == "/start")
{
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashStartAndEndGameCmd.GetValue()) return;
GameStartManager.Instance.BeginGame();
}
if (text == "/l" || text == "/lastgame")
{
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashLastGameCmd.GetValue()) return;
if (string.IsNullOrEmpty(NormalGameEndChecker.LastWinReason) || Utils.InGame) return;
Utils.ModeratorChatCommand($"{NormalGameEndChecker.LastWinReason}", "", false);
}
if (text == "/0kc" || text == "/0kcd" || text == "/0killcooldown")
if (text == "/aur" || text == "/socials")
{
if (!Utils.IsPlayerModerator(__instance.Data.FriendCode) || !Options.ModeratorCanUseCommand.GetBool()) return;
Utils.ModeratorChatCommand(Translator.Get("noKcdMode"), "", false);
}
if (text == "/sns" || text == "/shiftandseek" || text == "/shift&seek")
{
if (!Utils.IsPlayerModerator(__instance.Data.FriendCode) || !Options.ModeratorCanUseCommand.GetBool()) return;
Utils.ModeratorChatCommand(Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashLastGameCmd.GetValue()) return;
Utils.ModeratorChatCommand(Translator.Get("socialsAll"), "", false);
}
if (text == "/sp" || text == "/sr" || text == "/speedrun")
if (text == "/0kc" || text == "/0killcooldown")
{
if (!Utils.IsPlayerModerator(__instance.Data.FriendCode) || !Options.ModeratorCanUseCommand.GetBool()) return;
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashRolesAndGamemodeCmd.GetValue()) return;
Utils.ModeratorChatCommand(Translator.Get("noKcdMode"), "", false);
}
if (text == "/sns" || text == "/shiftandseek")
{
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashRolesAndGamemodeCmd.GetValue()) return;
if (Options.MisfiresToSuicide.GetInt() == 1 || Options.CantKillTime.GetInt() == 0)
{
Utils.ModeratorChatCommand(Translator.Get("SnSModeOne"), Translator.Get("SnSModeThree", Options.CrewAutoWinsGameAfter.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
else
{
Utils.ModeratorChatCommand(Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
}
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.IsPlayerModerator(__instance.Data.FriendCode) || !Options.ModeratorCanUseCommand.GetBool()) return;
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashRolesAndGamemodeCmd.GetValue()) return;
switch (Options.Gamemode.GetValue())
{
case 0:
AbilityManagement.SendRoleList(DestroyableSingleton<HudManager>.Instance.Chat, AbilityManagement.RoleList(), true);
break;
case 1:
@@ -443,7 +715,14 @@ public static class RPCHandlerPatch
break;
case 2:
Utils.ModeratorChatCommand(Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
if (Options.MisfiresToSuicide.GetInt() == 1 || Options.CantKillTime.GetInt() == 0)
{
Utils.ModeratorChatCommand(Translator.Get("SnSModeOne"), Translator.Get("SnSModeThree", Options.CrewAutoWinsGameAfter.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
else
{
Utils.ModeratorChatCommand(Translator.Get("SnSModeOne"), Translator.Get("SnSModeTwo", Options.CrewAutoWinsGameAfter.GetInt(), Options.CantKillTime.GetInt(), Options.MisfiresToSuicide.GetInt()), true);
}
break;
case 3:
@@ -452,6 +731,46 @@ public static class RPCHandlerPatch
}
}
if (Utils.CheckAccessLevel(__instance.Data.FriendCode) < Options.SlashRolesAndGamemodeCmd.GetValue()) return;
if (text == "/r jester"){
Utils.ModeratorChatCommand(Translator.Get("jesterPublic"), "", false);}
if (text == "/r mayor"){
Utils.ModeratorChatCommand(Translator.Get("mayorPublic", Options.ExtraVotesCrewmate.GetInt()), "", false);}
if (text == "/r tyrant"){
Utils.ModeratorChatCommand(Translator.Get("tyrantPublic", Options.ExtraVotesImpostor.GetInt()), "", false);}
if (text == "/r workhorse"){
Utils.ModeratorChatCommand(Translator.Get("workhorsePublic", Options.ExtraVotesPerTask.GetFloat()), "", false);}
if (text == "/r stealer"){
Utils.ModeratorChatCommand(Translator.Get("stealerPublic", Options.ExtraVotesPerKill.GetFloat()), "", false);}
if (text == "/r juggernaut"){
Utils.ModeratorChatCommand(Translator.Get("juggernautPublic", Options.KillsNeededForJuggernaut.GetInt()), "", false);}
if (text == "/r tasker"){
Utils.ModeratorChatCommand(Translator.Get("speedrunnerPublic"), "", false);}
if (text.StartsWith("/t "))
{
string templateName = text[3..].Trim().ToLower();
if (BanManager.Templates.TryGetValue(templateName, out string templateMessage))
{
if (templateMessage.Length < 121)
{
Utils.ModeratorChatCommand(BanManager.CheckTemplate(templateMessage), "", false);
}
else
{
HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, Translator.Get("tooLongTemplate"));
}
}
}
break;
}
}
+16 -20
View File
@@ -10,11 +10,12 @@ namespace AmongUsRevamped
public static class OptionsMenuBehaviourStartPatch
{
private static ClientOptionItem GM;
private static ClientOptionItem UnlockFPS;
private static ClientOptionItem ShowFPS;
private static ClientOptionItem AutoStart;
private static ClientOptionItem DarkTheme;
private static ClientOptionItem LobbyMusic;
private static ClientOptionItem DisableInfoWhenDead;
private static ClientOptionItem DisableCommandHelper;
public static void Postfix(OptionsMenuBehaviour __instance)
{
@@ -22,32 +23,24 @@ namespace AmongUsRevamped
if (GM == null || GM.ToggleButton == null)
{
GM = ClientOptionItem.Create("Game Master", Main.GM, __instance, GMButtonToggle);
GM = ClientOptionItem.Create(Translator.Get("gameMaster"), Main.GM, __instance, GMButtonToggle);
static void GMButtonToggle()
{
if (Main.GM.Value)
HudManager.Instance.ShowPopUp("You will now spectate games until GM is turned off.");
}
}
if (UnlockFPS == null || UnlockFPS.ToggleButton == null)
{
UnlockFPS = ClientOptionItem.Create("Unlock FPS", Main.UnlockFps, __instance, UnlockFPSButtonToggle);
static void UnlockFPSButtonToggle()
{
Application.targetFrameRate = Main.UnlockFps.Value ? 120 : 60;
Logger.SendInGame($"FPS Set To {Application.targetFrameRate}");
HudManager.Instance.ShowPopUp(Translator.Get("gameMasterWarning"));
}
}
if (ShowFPS == null || ShowFPS.ToggleButton == null)
ShowFPS = ClientOptionItem.Create("Show FPS", Main.ShowFps, __instance);
ShowFPS = ClientOptionItem.Create(Translator.Get("showFPS"), Main.ShowFps, __instance);
if (DisableInfoWhenDead == null || DisableInfoWhenDead.ToggleButton == null)
DisableInfoWhenDead = ClientOptionItem.Create(Translator.Get("disableInfoWhenDead"), Main.DisableInfoWhenDead, __instance);
if (AutoStart == null || AutoStart.ToggleButton == null)
{
AutoStart = ClientOptionItem.Create("Auto Start", Main.AutoStart, __instance, AutoStartButtonToggle);
AutoStart = ClientOptionItem.Create(Translator.Get("autoStart"), Main.AutoStart, __instance, AutoStartButtonToggle);
static void AutoStartButtonToggle()
{
@@ -55,16 +48,19 @@ namespace AmongUsRevamped
GameStartManager.Instance.startState == GameStartManager.StartingStates.Countdown)
{
GameStartManager.Instance.ResetStartState();
Logger.SendInGame("CancelStartCountDown");
Logger.SendInGame(Translator.Get("CancelStartCountDown"));
}
}
}
if (DarkTheme == null || DarkTheme.ToggleButton == null)
DarkTheme = ClientOptionItem.Create("Enable Dark Theme", Main.DarkTheme, __instance);
DarkTheme = ClientOptionItem.Create(Translator.Get("enableDarkTheme"), Main.DarkTheme, __instance);
if (LobbyMusic == null || LobbyMusic.ToggleButton == null)
LobbyMusic = ClientOptionItem.Create("Lobby Music", Main.LobbyMusic, __instance);
LobbyMusic = ClientOptionItem.Create(Translator.Get("enableLobbyMusic"), Main.LobbyMusic, __instance);
if (DisableCommandHelper == null || DisableCommandHelper.ToggleButton == null)
DisableCommandHelper = ClientOptionItem.Create(Translator.Get("disableCommandHelper"), Main.DisableCommandHelper, __instance);
}
}
@@ -92,7 +88,7 @@ namespace AmongUsRevamped
{
public static void Postfix(HudManager __instance)
{
if (Main.GM.Value)
if (Main.GM.Value && AmongUsClient.Instance.AmHost)
{
__instance.Chat.gameObject.SetActive(true);
__instance.MapButton.gameObject.SetActive(true);
+2 -2
View File
@@ -58,7 +58,7 @@ internal static class DisableDevice
foreach (PlayerControl pc in Main.AllPlayerControls)
{
if (pc.Data.IsDead || Main.GM.Value && pc == PlayerControl.LocalPlayer) return;
if (pc.Data.IsDead || (Main.GM.Value && pc == PlayerControl.LocalPlayer)) continue;
try
{
@@ -148,7 +148,7 @@ public class RemoveDisableDevicesPatch
{
public static void Postfix()
{
if (!Options.DisableDevices.GetBool()) return;
if (!Options.DisableDevices.GetBool() || !AmongUsClient.Instance.AmHost) return;
UpdateDisableDevices();
}
+33 -15
View File
@@ -1,27 +1,31 @@
using System;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.SceneManagement;
namespace AmongUsRevamped;
[HarmonyPatch(typeof(AmongUsDateTime), nameof(AmongUsDateTime.UtcNow), MethodType.Getter)]
public static class AmongUsDateTime_UtcNow
{
public static bool Prefix(ref Il2CppSystem.DateTime __result)
{
if (!CreateOptionsPickerPatch.SetDleks) return true;
var managedDate = new DateTime(DateTime.UtcNow.Year, 4, 2, 7, 1, 0, DateTimeKind.Utc);
__result = new Il2CppSystem.DateTime(managedDate.Ticks);
return false;
}
}
class CreateOptionsPickerPatch
{
public static bool SetDleks = false;
public static bool SetDleks2;
private static bool InitiatedDleks;
private static bool isSkeldFlipped = false;
public static bool FlippedSkeld
{
get => isSkeldFlipped;
set
{
if (AmongUsClient.Instance == null || isSkeldFlipped == value) return;
AssetReference temp = AmongUsClient.Instance.ShipPrefabs[3];
AmongUsClient.Instance.ShipPrefabs[3] = AmongUsClient.Instance.ShipPrefabs[0];
AmongUsClient.Instance.ShipPrefabs[0] = temp;
isSkeldFlipped = value;
}
}
private static MapSelectButton DleksButton;
[HarmonyPatch]
public static class GameOptionsMapPickerPatch
@@ -30,7 +34,17 @@ class CreateOptionsPickerPatch
[HarmonyPostfix]
public static void Postfix_Initialize(CreateGameMapPicker __instance)
{
float delay = SceneManager.GetActiveScene().name == "MainMenu" ? 0.2f : 0f;
float delay;
if (SceneManager.GetActiveScene().name == "MainMenu" && InitiatedDleks)
{
delay = 0.2f;
}
else
{
delay = 0f;
InitiatedDleks = true;
}
if (SceneManager.GetActiveScene().name == "FindAGame") return;
new LateTask(() =>
@@ -69,6 +83,8 @@ class CreateOptionsPickerPatch
dlekS_ehT_MapButton.Button.OnClick.RemoveAllListeners();
dlekS_ehT_MapButton.Button.OnClick.AddListener((UnityEngine.Events.UnityAction)(() =>
{
FlippedSkeld = true;
__instance.SelectMap(__instance.AllMapIcons[0]);
if (__instance.selectedButton)
@@ -125,6 +141,8 @@ class CreateOptionsPickerPatch
if (__instance.MapName == null) return false;
FlippedSkeld = (__instance.selectedMapId == 3);
if (DleksButton != null) SetDleks = __instance.selectedMapId == 3;
if (__instance.selectedMapId == 3)
+64 -18
View File
@@ -39,27 +39,73 @@ class NormalGameEndChecker
ImpCheckComplete = true;
}
var customRoles = CustomRoleManagement.PlayerToCustomRole();
var impostorList = string.Join(", ", imps.Select(p => p.Data.PlayerName));
CheckWinnerText("");
if (Utils.AliveImpostors == 0)
{
LastWinReason = $"Crewmates win!\n\nImpostors: {impostorList}" + (string.IsNullOrEmpty(customRoles) ? "" : "\n\n" + customRoles);
}
else if (Utils.AliveImpostors >= Utils.AliveCrewmates)
{
LastWinReason = $"Impostors win!\n\nImpostor: {impostorList}" + (string.IsNullOrEmpty(customRoles) ? "" : "\n\n" + customRoles);
}
else if (GameData.Instance != null && GameData.Instance.TotalTasks > 0 && GameData.Instance.CompletedTasks >= GameData.Instance.TotalTasks)
{
LastWinReason = $"Crewmates win! (Tasks)\n\nImpostors: {impostorList}" + (string.IsNullOrEmpty(customRoles) ? "" : "\n\n" + customRoles);
}
else if (Options.Gamemode.GetValue() < 2)
{
LastWinReason = $"Impostors win! (Sabotage)\n\nImpostors: {impostorList}" + (string.IsNullOrEmpty(customRoles) ? "" : "\n\n" + customRoles);
}
return true;
}
public static bool canUpdateWinnerText;
public static string customRoles { get; set; }
public static void CheckWinnerText(string Winner)
{
var impostorList = string.Join(", ", imps.Select(p => p.Data.PlayerName));
if (!canUpdateWinnerText) return;
if (Winner == "Jester")
{
LastWinReason = Translator.Get("jesterWin") + impostorList;
canUpdateWinnerText = false;
return;
}
if (Winner == "Juggernaut")
{
LastWinReason = Translator.Get("juggernautWin", Options.KillsNeededForJuggernaut.GetInt()) + impostorList;
canUpdateWinnerText = false;
return;
}
if (Winner == "Speedrunner")
{
LastWinReason = Translator.Get("speedrunnerWin") + impostorList;
canUpdateWinnerText = false;
return;
}
if (Winner == "SnSTimer")
{
LastWinReason = Translator.Get("crewmateWinTimer", Options.CrewAutoWinsGameAfter.GetInt()) + impostorList;
canUpdateWinnerText = false;
return;
}
if (Winner == "NoOneWinsSpeedrun")
{
LastWinReason = Translator.Get("noOneWin", Options.GameAutoEndsAfter.GetInt());
canUpdateWinnerText = false;
return;
}
if (Utils.AliveImpostors == 0 || Winner == "Crewmate")
{
LastWinReason = Translator.Get("crewmateWin") + impostorList;
canUpdateWinnerText = false;
}
else if (Utils.AliveImpostors >= Utils.AliveCrewmates || Winner == "Impostor")
{
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 = Translator.Get("crewmateWinTasks", Options.TaskPercentNeededToWin.GetInt()) + impostorList;
canUpdateWinnerText = false;
}
else if (Options.Gamemode.GetValue() < 2 || Winner == "ImpostorSabotage")
{
LastWinReason = Translator.Get("impostorWinMisc") + impostorList;
}
}
}
[HarmonyPatch(typeof(LogicGameFlowHnS), nameof(LogicGameFlowHnS.CheckEndCriteria))]
+58 -19
View File
@@ -1,35 +1,74 @@
using System.Reflection;
using Il2CppInterop.Runtime.InteropTypes;
namespace AmongUsRevamped;
[HarmonyPatch]
class ExileControllerWrapUpPatch
{
[HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))]
class ExileControllerPatch
public static MethodBase TargetMethod()
{
public static void Postfix(ExileController __instance)
return AccessTools.Method(typeof(ExileController), nameof(ExileController.WrapUp));
}
public static void Postfix(ExileController __instance)
{
AfterExile(__instance.initData.networkedPlayer);
}
public static void AfterExile(NetworkedPlayerInfo ejectedPlayer)
{
if (!AmongUsClient.Instance.AmHost) return;
if (ejectedPlayer == null) return;
PlayerControl pc = null;
PlayerControl exiledPlayer = ejectedPlayer.Object;
foreach (var p in PlayerControl.AllPlayerControls)
{
if (!AmongUsClient.Instance.AmHost) return;
var ejectedPlayer = __instance.initData?.networkedPlayer;
if (ejectedPlayer == null) return;
PlayerControl pc = null;
foreach (var p in PlayerControl.AllPlayerControls)
if (p.PlayerId == ejectedPlayer.PlayerId)
{
if (p.PlayerId == ejectedPlayer.PlayerId)
pc = p;
}
if (ejectedPlayer == PlayerControl.LocalPlayer.Data && !Main.DisableInfoWhenDead.Value)
{
if (p.Data.Role.IsImpostor)
{
pc = p;
break;
p.cosmetics.nameText.text = $"{p.Data.PlayerName}<color=red><size=90%>({MurderPlayerPatch.killCount[p.Data.PlayerId]}†)";
}
else
{
if (!PlayerControlCompleteTaskPatch.playerTasksCompleted.ContainsKey(p.PlayerId))
{
PlayerControlCompleteTaskPatch.playerTasksCompleted[p.PlayerId] = 0;
}
p.cosmetics.nameText.text = $"{p.Data.PlayerName}<color=green><size=90%>({PlayerControlCompleteTaskPatch.playerTasksCompleted[p.PlayerId]}/{PlayerControlCompleteTaskPatch.tasksPerPlayer[p.PlayerId]})";
}
}
}
Logger.Info($" {ejectedPlayer.PlayerName} was ejected", "ExileController");
Logger.Info($" {ejectedPlayer.PlayerName} was ejected", "ExileController");
if (!CustomRoleManagement.PlayerRoles.TryGetValue(ejectedPlayer.PlayerId, out var role)) return;
if (PlayerControlSetRolePatch.Jesters.Contains(exiledPlayer))
{
Logger.Info($"Jester {ejectedPlayer.PlayerName} wins", "ExilePatch");
Utils.CustomWinnerEndGame(exiledPlayer, 1);
NormalGameEndChecker.CheckWinnerText("Jester");
return;
}
}
if (role == "Jester")
{
Utils.CustomWinnerEndGame(pc, 1);
}
[HarmonyPatch]
class AirshipExileControllerPatch
{
public static MethodBase TargetMethod()
{
return Utils.GetStateMachineMoveNext<AirshipExileController>(nameof(AirshipExileController.WrapUpAndSpawn));
}
public static void Postfix(AirshipExileController._WrapUpAndSpawn_d__11 __instance)
{
ExileControllerWrapUpPatch.AfterExile(__instance.__4__this.initData.networkedPlayer);
}
}
}
+6 -1
View File
@@ -115,11 +115,16 @@ namespace AmongUsRevamped
case TabGroup.SystemSettings:
__instance.MenuDescriptionText.text = "Quality settings to improve comfort and testing.";
break;
/*
case TabGroup.CustomRoleSettings:
__instance.MenuDescriptionText.text = "Custom Role enabling and settings.";
break;
*/
case TabGroup.AbilitySettings:
__instance.MenuDescriptionText.text = "Ability settings to enhance vanilla roles.";
break;
case TabGroup.ModSettings:
__instance.MenuDescriptionText.text = "Gameplay Settings to improve the in-game experience.";
__instance.MenuDescriptionText.text = "Gameplay settings to improve the in-game experience.";
break;
case TabGroup.GamemodeSettings:
__instance.MenuDescriptionText.text = "Situational settings to apply for specific gamemodes.";
+18 -3
View File
@@ -9,6 +9,7 @@ public static class GameStartManagerUpdatePatch
{
public static bool CustomTimerApplied;
public static bool Autostarting;
public static bool CountingDown;
public static void Prefix(GameStartManager __instance)
{
@@ -27,11 +28,16 @@ public static class GameStartManagerUpdatePatch
Autostarting = true;
}
if (__instance.startState == GameStartManager.StartingStates.Countdown && !CustomTimerApplied && !Autostarting)
if (__instance.startState == GameStartManager.StartingStates.Countdown)
{
__instance.countDownTimer = Options.StartCountdown.GetInt();
CustomTimerApplied = true;
CountingDown = true;
if (!CustomTimerApplied && !Autostarting)
{
__instance.countDownTimer = Options.StartCountdown.GetInt();
CustomTimerApplied = true;
}
}
else CountingDown = false;
if (__instance.startState != GameStartManager.StartingStates.Countdown)
{
@@ -106,4 +112,13 @@ public class GameStartManagerStartPatch
}));
}
}
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.BeginGame))]
public class GameStartManagerBeginGamePatch
{
public static void Prefix(GameStartManager __instance)
{
if (Options.NoGameEnd.GetBool()) Logger.SendInGame(Translator.Get("noGameEndWarning"));
}
}
+31 -22
View File
@@ -9,30 +9,39 @@ namespace AmongUsRevamped;
[HarmonyPatch(typeof(HudManager), nameof(HudManager.CoShowIntro))]
internal static class CoShowIntroPatch
{
public static bool IntroInitiated;
public static bool ScheduleExile;
public static void Postfix(IntroCutscene __instance)
{
Logger.Info("Intro initiated", "CoShowIntro");
Logger.Info(" Intro initiated", "CoShowIntro");
if (!AmongUsClient.Instance.AmHost) return;
if ((Options.Gamemode.GetValue() == 0 || Options.Gamemode.GetValue() == 1) && !Utils.isHideNSeek)
IntroInitiated = true;
AbilityManagement.SendRoleMessages();
foreach (var p in PlayerControl.AllPlayerControls)
{
CustomRoleManagement.AssignRoles();
p.cosmetics.nameText.text = p.Data.PlayerName;
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");
}
if (ScheduleExile)
{
PlayerControl.LocalPlayer.Exiled();
ScheduleExile = false;
}
CustomRoleManagement.SendRoleMessages(new Dictionary<string, string>
{
{ "Jester", Translator.Get("JesterPriv")},
{ "Mayor", Translator.Get("MayorPriv")}
});
Logger.Info($" {AbilityManagement.RoleList()}", "AbilityInfo");
if (Main.GM.Value)
{
PlayerControl.LocalPlayer.RpcSetRole(AmongUs.GameOptions.RoleTypes.CrewmateGhost, false);
PlayerControl.LocalPlayer.myTasks.Clear();
}
if (Options.DisableAnnoyingMeetingCalls.GetBool())
if (Options.DisableAnnoyingMeetingCalls.GetBool() && !Utils.isHideNSeek)
{
Utils.CanCallMeetings = false;
_ = new LateTask(() =>
@@ -41,14 +50,14 @@ internal static class CoShowIntroPatch
}, 33f, "MeetingEnabled");
}
if (!Utils.isHideNSeek) return;
foreach (var p in PlayerControl.AllPlayerControls)
if (Options.Gamemode.GetValue() == 2 && Options.SNSChatInGame.GetBool())
{
if (p.Data.Role.TeamType == RoleTeamTypes.Impostor)
{
p.RpcSetRole(AmongUs.GameOptions.RoleTypes.Impostor, false);
}
_ = new LateTask(() =>
{
PlayerControl.LocalPlayer.CmdReportDeadBody(null);
if (MeetingHud.Instance != null) MeetingHud.Instance.RpcClose();
}, 9f, "SetChatVisible");
}
}
}
+59 -9
View File
@@ -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))
@@ -79,13 +80,8 @@ class OnPlayerJoinedPatch
if (AmongUsClient.Instance.AmHost)
{
BanManager.CheckBanPlayer(Client);
BanManager.IsPlayerInDenyName(Client, Client.PlayerName);
if (Utils.IsPlayerModerator(Client.FriendCode) && Options.ApplyModeratorList.GetBool())
{
Logger.Info($" {Client.PlayerName} is moderator", "ModeratorCheck");
}
Logger.Info($" {Client.PlayerName} has access level {Utils.CheckAccessLevel(Client.FriendCode)}", "AccessCheck");
if (HasInvalidFriendCode(Client.FriendCode) && Options.KickInvalidFriendCodes.GetBool())
{
@@ -102,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(BanManager.CheckTemplate(msg), "", false);
}
}
}
}
}
@@ -109,9 +117,51 @@ class OnPlayerJoinedPatch
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnPlayerLeft))]
class OnPlayerLeftPatch
{
static void Prefix([HarmonyArgument(0)] ClientData client)
static void Postfix([HarmonyArgument(0)] ClientData client)
{
if (client?.Character == null) return;
FixedUpdateInGamePatch.ProcessedModerators.Remove(client.Character.PlayerId);
if (!AmongUsClient.Instance.AmHost) return;
Logger.Info($" {client.PlayerName} left the game", "OnPlayerLeft");
if (!Utils.InGame) return;
PlayerControlCompleteTaskPatch.CalculateTaskWin();
}
}
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetLevel))]
public static class SetLevelPatch
{
public static List<PlayerControl> HandledLevelKicks = [];
public static void Prefix(PlayerControl __instance, uint level)
{
if (AmongUsClient.Instance.AmHost && level < Options.KickLowLevelPlayer.GetInt() - 1 && __instance.Data.ClientId != AmongUsClient.Instance.HostId)
{
if (level == 0 && Options.DontKickLevelOnes.GetBool()) return;
if (HandledLevelKicks.Contains(__instance)) return;
if (!Options.TempBanLowLevelPlayer.GetBool())
{
AmongUsClient.Instance.KickPlayer(__instance.Data.ClientId, false);
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} (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);
}
}
}
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Start))]
public static class ShowLobbyTimer_GameStartManager_Start_Postfix
{
public static void Postfix(GameStartManager __instance)
{
if (__instance == null || !GameData.Instance || !AmongUsClient.Instance || AmongUsClient.Instance.NetworkMode == NetworkModes.LocalGame || !AmongUsClient.Instance.AmHost) return;
HudManager.Instance.ShowLobbyTimer(600);
}
}
+117
View File
@@ -0,0 +1,117 @@
using UnityEngine;
namespace AmongUsRevamped;
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CheckForEndVoting))]
public static class CheckForEndVotingPatch
{
public static bool Prefix(MeetingHud __instance)
{
if (!AmongUsClient.Instance.AmHost) return true;
if (!__instance.playerStates.All(ps => ps.AmDead || ps.DidVote)) return true;
var votes = __instance.CalculateVotes();
var visualVotes = new List<MeetingHud.VoterState>();
foreach (var ps in __instance.playerStates)
{
if (ps == null) continue;
byte voterId = ps.TargetPlayerId;
byte votedFor = ps.VotedFor;
PlayerControl pc = GameData.Instance.GetPlayerById(voterId)?.Object;
if (pc == null) continue;
if (votedFor == byte.MaxValue) continue;
if (!votes.ContainsKey(votedFor)) votes[votedFor] = 0;
visualVotes.Add(new MeetingHud.VoterState { VoterId = voterId, VotedForId = votedFor });
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[voterId]+0.1f);
int extraVotesPerKill = (int)(Options.ExtraVotesPerKill.GetFloat()*MurderPlayerPatch.killCount[voterId]+0.1f);
if (!votes.TryGetValue(votedFor, out int currentVotes)) currentVotes = 0;
if (AbilityManagement.IsMayor(pc)) extraVotes += extraVotesCrewmate;
if (AbilityManagement.IsTyrant(pc)) extraVotes += extraVotesImpostor;
if (AbilityManagement.IsWorkhorse(pc)) extraVotes += extraVotesPerTask;
if (AbilityManagement.IsStealer(pc)) extraVotes += extraVotesPerKill;
for (int i = 0; i < extraVotes; i++)
{
visualVotes.Add(new MeetingHud.VoterState { VoterId = voterId, VotedForId = votedFor });
votes[votedFor]++;
}
}
var max = votes.MaxPair(out var tie);
var exiled = GameData.Instance.AllPlayers.ToArray().FirstOrDefault(p => !tie && p.PlayerId == max.Key);
var statesArray = visualVotes.ToArray();
__instance.RpcVotingComplete(statesArray, exiled, tie);
return false;
}
}
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Start))]
class MeetingHudStartPatch
{
public static void Postfix(MeetingHud __instance)
{
if (!AmongUsClient.Instance.AmHost) return;
foreach (var playerState in __instance.playerStates)
{
PlayerControl player = null;
foreach (var pc in PlayerControl.AllPlayerControls)
{
if (pc.PlayerId == playerState.TargetPlayerId)
{
player = pc;
break;
}
}
if (player == null || !PlayerControl.LocalPlayer.Data.IsDead || Main.DisableInfoWhenDead.Value) continue;
var textTemplate = playerState.NameText;
var taskText = GetProgressText(player);
var taskTextMeeting = UnityEngine.Object.Instantiate(textTemplate);
taskTextMeeting.transform.SetParent(textTemplate.transform);
taskTextMeeting.transform.localPosition = new Vector3(0f, 0.18f, 0f);
taskTextMeeting.fontSize = 1.6f;
taskTextMeeting.text = taskText;
taskTextMeeting.gameObject.name = "TaskTextMeeting";
taskTextMeeting.enableWordWrapping = false;
taskTextMeeting.enabled = player.AmOwner || player.PlayerId == playerState.TargetPlayerId;
}
}
public static string GetProgressText(PlayerControl player)
{
int totalTasks = 0;
int tasksCompleted = 0;
if (player.Data.Tasks != null && !player.Data.Role.IsImpostor)
{
foreach (var task in player.Data.Tasks)
{
totalTasks++;
if (task.Complete) tasksCompleted++;
}
return $"<color=green>({tasksCompleted}/{totalTasks})</color> - {Utils.GetRoleText(player)}";
}
else
{
return $"<color=red>({MurderPlayerPatch.killCount[player.Data.PlayerId]}†)</color> - {Utils.GetRoleText(player)}";
}
}
}
+2 -2
View File
@@ -15,7 +15,7 @@ public static class NumberOption_Increase
float increment = Hotkeys.IncrementMultiplier * __instance.Increment;
#endif
if (Utils.isHideNSeek || Utils.IsLobby && !Utils.isHideNSeek && __instance.Title != StringNames.GameNumImpostors && __instance.Title != StringNames.GamePlayerSpeed)
if (Utils.IsLobby)
{
if (__instance.Value <= __instance.ValidRange.min)
{
@@ -53,7 +53,7 @@ public static class NumberOption_Decrease
float increment = Hotkeys.IncrementMultiplier * __instance.Increment;
#endif
if (Utils.isHideNSeek || Utils.IsLobby && !Utils.isHideNSeek && __instance.Title != StringNames.GameNumImpostors && __instance.Title != StringNames.GamePlayerSpeed)
if (Utils.IsLobby)
{
if (__instance.Value >= __instance.ValidRange.max)
{
+82 -36
View File
@@ -1,4 +1,5 @@
using System;
using AmongUs.GameOptions;
using System;
using InnerNet;
using UnityEngine;
@@ -12,53 +13,98 @@ internal class CoStartGamePatch
if (!AmongUsClient.Instance.AmHost) return;
Logger.Info(" -------- GAME STARTED --------", "StartGame");
Logger.Info($" Gamemode: {Options.Gamemode.GetValue()}", "StartGame");
Logger.Info($" Players: {PlayerControl.AllPlayerControls.Count}", "StartGame");
NormalGameEndChecker.imps.Clear();
NormalGameEndChecker.LastWinReason = "";
if (Options.Gamemode.GetValue() == 3 && !Utils.isHideNSeek)
}
}
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RpcSetRole))]
class PlayerControlSetRolePatch
{
public static bool FirstAssign;
private static readonly HashSet<byte> ProcessedPlayers = new();
public static HashSet<byte> Seekers = new();
public static HashSet<PlayerControl> Jesters = new();
private static readonly System.Random rand = new System.Random();
public static bool Prefix(PlayerControl __instance, ref RoleTypes roleType, ref bool canOverrideRole)
{
if (!FirstAssign || !AmongUsClient.Instance.AmHost) return true;
if (!ProcessedPlayers.Add(__instance.PlayerId)) return true;
canOverrideRole = false;
if (Main.GM.Value && __instance == PlayerControl.LocalPlayer)
{
roleType = RoleTypes.Crewmate;
CoShowIntroPatch.ScheduleExile = true;
}
if (Utils.isHideNSeek && Seekers.Count() == 0)
{
int seekersCount = Options.NumSeekers.GetInt();
var candidates = new List<PlayerControl>();
foreach (var p in PlayerControl.AllPlayerControls)
{
if (p != PlayerControl.LocalPlayer)
{
p.RpcSetRole(AmongUs.GameOptions.RoleTypes.Crewmate, false);
}
if (p == PlayerControl.LocalPlayer)
{
p.CoSetRole(AmongUs.GameOptions.RoleTypes.Crewmate, false);
}
if (!Main.GM.Value || p != PlayerControl.LocalPlayer) candidates.Add(p);
}
seekersCount = Math.Min(seekersCount, candidates.Count);
for (int j = candidates.Count - 1; j > 0; j--)
{
int k = rand.Next(j + 1);
(candidates[j], candidates[k]) = (candidates[k], candidates[j]);
}
for (int j = 0; j < seekersCount; j++)
{
Seekers.Add(candidates[j].PlayerId);
}
}
if (Utils.isHideNSeek)
{
int seekersCount = Options.NumSeekers.GetInt();
int toAdd = Math.Max(0, seekersCount - 1);
var candidates = new List<PlayerControl>();
foreach (var p in PlayerControl.AllPlayerControls)
{
if (p.Data.Role.TeamType != RoleTeamTypes.Impostor && !p.Data.IsDead)
candidates.Add(p);
}
toAdd = Math.Min(toAdd, candidates.Count);
System.Random rand = new System.Random();
for (int i = candidates.Count - 1; i > 0; i--)
{
int j = rand.Next(i + 1);
(candidates[i], candidates[j]) = (candidates[j], candidates[i]);
}
for (int i = 0; i < toAdd; i++)
{
var player = candidates[i];
player.RpcSetRole(AmongUs.GameOptions.RoleTypes.Impostor, false);
}
if (Seekers.Contains(__instance.PlayerId)) roleType = RoleTypes.Impostor;
else roleType = RoleTypes.Engineer;
}
if (Options.Gamemode.GetValue() == 3 && !Utils.isHideNSeek)
{
if (Options.EngineerMode.GetBool()) roleType = RoleTypes.Engineer;
else roleType = RoleTypes.Crewmate;
}
if (Options.Gamemode.GetValue() == 2 && !Utils.isHideNSeek)
{
if (roleType == RoleTypes.Impostor || roleType == RoleTypes.Phantom || roleType == RoleTypes.Viper) roleType = RoleTypes.Shapeshifter;
}
if (ProcessedPlayers.Count >= PlayerControl.AllPlayerControls.Count)
{
Seekers.Clear();
ProcessedPlayers.Clear();
FirstAssign = false;
Logger.Info("PCSRP successful", "RoleManaging");
}
if (roleType == RoleTypes.Crewmate && Options.CrewmateAbility.GetValue() == 2 ||
roleType == RoleTypes.Scientist && Options.ScientistAbility.GetValue() == 2 ||
roleType == RoleTypes.Engineer && Options.EngineerAbility.GetValue() == 2 ||
roleType == RoleTypes.Noisemaker && Options.NoisemakerAbility.GetValue() == 2 ||
roleType == RoleTypes.Tracker && Options.TrackerAbility.GetValue() == 2 ||
roleType == RoleTypes.Detective && Options.DetectiveAbility.GetValue() == 2)
{
Jesters.Add(__instance);
}
return true;
}
}
+148 -10
View File
@@ -3,7 +3,9 @@ using AmongUs.GameOptions;
using Hazel;
using InnerNet;
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace AmongUsRevamped;
@@ -13,20 +15,29 @@ class ReportDeadBodyPatch
public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] NetworkedPlayerInfo target)
{
if (!AmongUsClient.Instance.AmHost || __instance == null) return true;
if (Utils.isHideNSeek) return false;
if (Options.DisableAnnoyingMeetingCalls.GetBool() && !Utils.CanCallMeetings && target == null)
if (Options.DisableAnnoyingMeetingCalls.GetBool() && !Utils.CanCallMeetings && target == null && Options.Gamemode.GetValue() < 2)
{
Logger.Info($" {__instance.Data.PlayerName} is calling a meeting too fast, attempt blocked", "ReportDeadBodyPatch");
return false;
}
// target == null means meeting
if (target == null) return true;
if (Options.DisableReport.GetBool() || Options.Gamemode.GetValue() == 2 || Options.Gamemode.GetValue() == 3)
if (Options.Gamemode.GetValue() == 2 || Options.Gamemode.GetValue() == 3)
{
Logger.Info($" Stopped {__instance.Data.PlayerName} reporting the body of {target.PlayerName}", "ReportDeadBodyPatch");
return false;
if (target != null)
{
Logger.Info($" Stopped {__instance.Data.PlayerName} reporting the body of {target.PlayerName}", "ReportDeadBodyPatch");
return false;
}
if (__instance != PlayerControl.LocalPlayer)
{
Logger.Info($" Stopped {__instance.Data.PlayerName} trying to call a meeting", "ReportDeadBodyPatch");
return false;
}
return true;
}
else return true;
}
@@ -36,10 +47,46 @@ class ReportDeadBodyPatch
internal static class MurderPlayerPatch
{
public static readonly Dictionary<byte, int> misfireCount = new();
public static readonly Dictionary<byte, int> killCount = new();
public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] PlayerControl target, [HarmonyArgument(1)] MurderResultFlags resultFlags, ref bool __state)
{
if (!AmongUsClient.Instance.AmHost) return;
if (!AmongUsClient.Instance.AmHost || !resultFlags.HasFlag(MurderResultFlags.Succeeded)) return;
byte playerId = __instance.Data.PlayerId;
if (!killCount.ContainsKey(playerId))
{
killCount[playerId] = 0;
}
if (!__instance.isNew)
{
killCount[playerId]++;
Logger.Info($" {__instance.Data.PlayerName} killed {target.Data.PlayerName}", "MurderPlayer");
if ((target == PlayerControl.LocalPlayer || PlayerControl.LocalPlayer.Data.IsDead) && !Main.DisableInfoWhenDead.Value)
{
foreach (var p in PlayerControl.AllPlayerControls)
{
if (p.Data.Role.IsImpostor)
{
p.cosmetics.nameText.text = $"{p.Data.PlayerName}<color=red><size=90%>({killCount[p.Data.PlayerId]}†)</color> - {Utils.GetRoleText(p)}";
}
else
{
p.cosmetics.nameText.text = $"{p.Data.PlayerName}<color=green><size=90%>({PlayerControlCompleteTaskPatch.playerTasksCompleted[p.PlayerId]}/{PlayerControlCompleteTaskPatch.tasksPerPlayer[p.PlayerId]})</color> - {Utils.GetRoleText(p)}";
}
}
}
}
if (Options.Gamemode.GetValue() < 2 && AbilityManagement.IsJuggernaut(__instance) && killCount[__instance.PlayerId] >= Options.KillsNeededForJuggernaut.GetInt())
{
Logger.Info("Juggernaut win", "MurderPlayer");
Utils.ContinueEndGame((byte)GameOverReason.ImpostorsByVote);
NormalGameEndChecker.CheckWinnerText("Juggernaut");
}
//2 = Shift and Seek
if (Options.Gamemode.GetValue() == 2 && !Utils.isHideNSeek)
@@ -47,8 +94,6 @@ internal static class MurderPlayerPatch
if (!resultFlags.HasFlag(MurderResultFlags.Succeeded))
return;
byte playerId = __instance.Data.PlayerId;
if (target.Data.PlayerId == __instance.shapeshiftTargetPlayerId)
{
Logger.Info($" {__instance.Data.PlayerName} correctly killed {target.Data.PlayerName} ", "SNSKillManager");
@@ -77,8 +122,8 @@ internal static class MurderPlayerPatch
if (misfireCount[__instance.Data.PlayerId] >= Options.MisfiresToSuicide.GetFloat())
{
__instance.RpcSetRole(RoleTypes.ImpostorGhost);
Logger.Info($" {__instance.Data.PlayerName} misfired {misfireCount[playerId]} times and suicided", "SNSKillManager");
Logger.SendInGame($" {__instance.Data.PlayerName} misfired {misfireCount[playerId]} times and suicided");
Logger.Info($" {__instance.Data.PlayerName} misfired {misfireCount[playerId]} time(s) and suicided", "SNSKillManager");
Logger.SendInGame($" {__instance.Data.PlayerName} misfired {misfireCount[playerId]} time(s) and suicided");
}
}
@@ -104,3 +149,96 @@ internal static class CheckShapeshiftPatch
else return true;
}
}
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CompleteTask))]
class PlayerControlCompleteTaskPatch
{
public static Dictionary<byte, int> playerTasksCompleted = new Dictionary<byte, int>();
public static Dictionary<byte, int> tasksPerPlayer = new Dictionary<byte, int>();
public static List<string> ignoredRoles = new List<string> {"Jester"};
public static int ignoredTasks;
public static int ignoredCompletedTasks;
public static bool tasksInitiated;
public static void Postfix(PlayerControl __instance, uint idx)
{
if (!AmongUsClient.Instance.AmHost) return;
foreach (var p in PlayerControl.AllPlayerControls)
{
if (AbilityManagement.IsJester(p) && !tasksInitiated)
{
ignoredTasks += p.Data.Tasks.Count;
tasksInitiated = true;
}
if (!playerTasksCompleted.ContainsKey(p.PlayerId))
{
playerTasksCompleted[p.PlayerId] = 0;
}
tasksPerPlayer[p.PlayerId] = p.Data.Tasks.Count;
}
playerTasksCompleted[__instance.PlayerId]++;
if (AbilityManagement.IsJester(__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.PlayerId] >= __instance.Data.Tasks.Count)
{
Logger.Info($"Speedrunner {__instance.Data.PlayerName} won", "TaskPatch");
Utils.ContinueEndGame((byte)GameOverReason.CrewmatesByVote);
NormalGameEndChecker.CheckWinnerText("Speedrunner");
}
}
if (Options.Gamemode.GetValue() != 3) CalculateTaskWin();
if (Options.Gamemode.GetValue() == 3)
{
if (!__instance.Data.IsDead && playerTasksCompleted[__instance.PlayerId] >= __instance.Data.Tasks.Count)
{
Utils.CustomWinnerEndGame(__instance, 1);
NormalGameEndChecker.LastWinReason = $"{__instance.Data.PlayerName} wins! (Completed tasks)";
NormalGameEndChecker.canUpdateWinnerText = false;
}
}
if (PlayerControl.LocalPlayer.Data.IsDead && !Main.DisableInfoWhenDead.Value)
{
TMP_Text nameText = __instance.cosmetics.nameText;
nameText.text = $"{__instance.Data.PlayerName}<color=green><size=90%>({playerTasksCompleted[__instance.PlayerId]}/{tasksPerPlayer[__instance.PlayerId]})</color> - {Utils.GetRoleText(__instance)}";
}
}
public static void CalculateTaskWin()
{
if (!Utils.GamePastRoleSelection || Utils.isHideNSeek || Options.NoGameEnd.GetBool() || !CoShowIntroPatch.IntroInitiated) return;
//Logger.Info($" Checking if {GameData.Instance.CompletedTasks} - {ignoredCompletedTasks} >= ({GameData.Instance.TotalTasks} - {ignoredTasks}) * 0.01 * {Options.TaskPercentNeededToWin.GetInt()}", "TaskPatch");
if ((GameData.Instance.CompletedTasks - ignoredCompletedTasks) >= (GameData.Instance.TotalTasks - ignoredTasks)*0.01*Options.TaskPercentNeededToWin.GetInt())
{
Utils.ContinueEndGame((byte)GameOverReason.CrewmatesByVote);
NormalGameEndChecker.CheckWinnerText("CrewmateTasks");
}
}
}
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CheckSporeTrigger))]
public static class PlayerControlCheckSporeTriggerPatch
{
public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] Mushroom mushroom)
{
if (!AmongUsClient.Instance.AmHost) return true;
if (Options.DisableSporeTrigger.GetBool()) return false;
else return true;
}
}
+19 -11
View File
@@ -136,7 +136,7 @@ internal static class RpcSetTasksPatch
if (!Options.AllPlayersSameTasks.GetBool())
{
RerollTasks(ref taskTypeIds);
RerollTasks(pc, ref taskTypeIds);
return;
}
@@ -155,23 +155,26 @@ internal static class RpcSetTasksPatch
}
private static void RerollTasks(ref Il2CppStructArray<byte> taskTypeIds)
private static void RerollTasks(PlayerControl pc, ref Il2CppStructArray<byte> taskTypeIds)
{
// Default number of tasks
bool hasCommonTasks = true;
int numCommonTasks = Main.NormalOptions.NumCommonTasks;
int numLongTasks = Main.NormalOptions.NumLongTasks;
int numShortTasks = Main.NormalOptions.NumShortTasks;
if (AbilityManagement.IsSpeedrunner(pc))
{
numLongTasks = Options.SpeedrunnerLongTasks.GetInt();
numShortTasks = Options.SpeedrunnerShortTasks.GetInt();
}
if (taskTypeIds.Length == 0) hasCommonTasks = false;
switch (hasCommonTasks)
{
case false when numLongTasks == 0 && numShortTasks == 0:
numShortTasks = 1;
break;
case true when numLongTasks == Main.NormalOptions.NumLongTasks && numShortTasks == Main.NormalOptions.NumShortTasks:
return;
case false when numLongTasks == 0 && numShortTasks == 0: numShortTasks = 1; break;
case true when numLongTasks == Main.NormalOptions.NumLongTasks && numShortTasks == Main.NormalOptions.NumShortTasks: return;
}
Il2CppSystem.Collections.Generic.List<byte> TasksList = new();
@@ -180,24 +183,28 @@ internal static class RpcSetTasksPatch
Il2CppSystem.Collections.Generic.HashSet<TaskTypes> UsedTaskTypes = new();
var start0 = 0;
var start1 = 0;
var start2 = 0;
// Long tasks
Il2CppSystem.Collections.Generic.List<NormalPlayerTask> CommonTasks = new();
foreach (var task in ShipStatus.Instance.CommonTasks) CommonTasks.Add(task);
Shuffle(CommonTasks);
ShipStatus.Instance.AddTasksFromList(ref start0, numCommonTasks, TasksList, UsedTaskTypes, CommonTasks);
Il2CppSystem.Collections.Generic.List<NormalPlayerTask> LongTasks = new();
foreach (var task in ShipStatus.Instance.LongTasks) LongTasks.Add(task);
Shuffle(LongTasks);
ShipStatus.Instance.AddTasksFromList(ref start1, numLongTasks, TasksList, UsedTaskTypes, LongTasks);
// Short tasks
Il2CppSystem.Collections.Generic.List<NormalPlayerTask> ShortTasks = new();
foreach (var task in ShipStatus.Instance.ShortTasks) ShortTasks.Add(task);
Shuffle(ShortTasks);
ShipStatus.Instance.AddTasksFromList(ref start2, numShortTasks, TasksList, UsedTaskTypes, ShortTasks);
// Apply result
taskTypeIds = new Il2CppStructArray<byte>(TasksList.Count);
for (int i = 0; i < TasksList.Count; i++) taskTypeIds[i] = TasksList[i];
}
@@ -212,4 +219,5 @@ internal static class RpcSetTasksPatch
list[r] = tmp;
}
}
}
+20
View File
@@ -0,0 +1,20 @@
namespace AmongUsRevamped;
//Old Patch for Mayor
/*
[HarmonyPatch(typeof(Vent), nameof(Vent.EnterVent))]
class EnterVentPatch
{
public static void Postfix(Vent __instance, [HarmonyArgument(0)] PlayerControl pc)
{
if (!AmongUsClient.Instance.AmHost) return;
if (CustomRoleManagement.PlayerRoles.TryGetValue(pc.PlayerId, out var role) && role == "Mayor")
{
pc.CmdReportDeadBody(null);
Logger.Info($" The Mayor, {pc.Data.PlayerName}, called a meeting by venting", "EnterVent");
}
}
}
*/
+10 -2
View File
@@ -17,8 +17,6 @@ internal static class AddVotePatch
if (AmongUsClient.Instance.ClientId == srcClient)
{
AmongUsClient.Instance.KickPlayer(target.Data.ClientId, false);
Logger.Info($" Kicked {target.Data.PlayerName}, {target.Data.FriendCode}", "KickPatch");
}
return true;
@@ -48,6 +46,16 @@ internal static class BanMenuSetVisiblePatch
__instance.KickButton.gameObject.SetActive(true);
__instance.MenuButton.gameObject.SetActive(show);
return false;
}
}
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.CanBan))]
internal class InnerNetClientCanBanPatch
{
public static bool Prefix(InnerNetClient __instance, ref bool __result)
{
__result = __instance.AmHost;
return false;
}
}
+57 -28
View File
@@ -1,4 +1,4 @@
# Welcome to AmongUsRevamped!
# Welcome to Among Us Revamped!
<br>
</p>
@@ -29,52 +29,76 @@
<img src="https://github.com/astra1dev/AUnlocker/assets/90265231/14226f03-a003-4efc-b27b-6df53fb394d6" width=410 height=240>****
‎
# 🎮 Features (v1.5.3):
# 🎮 Features (v1.8.0):
## <b> 🌟 Custom Abilities:</b>
- Mayor (Crewmate)
- The Mayor has a configurable amount of extra votes
- Jester (Crewmate)
- The Jester wins alone by getting ejected, can win with Crewmates
- 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)
- The Tyrant has a configurable amount of extra votes
- Stealer (Impostor)
- The Stealer gains additional votes per kill
- Juggernaut (Impostor)
- The Impostors win if the Juggernaut gains a set amount of kills
- For the enabled ability list, type /r
- To check ability descriptions, type /r {ability}
## <b>♠️ Client Side settings:</b>
- Game Master
- Unlock FPS
- Game Master (Spectator)
- Show FPS
- Dark Theme
- Toggle Lobby Music
- Customizable strings
- Show/Hide Info When Dead
## <b>⚙️ Technical settings:</b>
- Kick/Ban players under a certain level
- Kick/Ban invalid FriendCodes
- Kick/Ban players who say "start" and conitions
- DenyName system
- Moderator system
- Kick/Ban players who say "start"
- Denyword system
- Banlist system
- Denyname system
- Multi layer moderator system
- To add Admins, Moderators and VIP's, type the user's Friendcode in the designated files located in AUR-DATA
- Enable No Game End
- Custom starting countdown
## <b>♻️ Automation settings:</b>
- Automatically start game and conditions for it
- Automatically start game
- Automatically rejoin lobby
- Automatically send winner info
- Enable (configurable) Welcome Messages
- The Welcome Template is in Templates.txt
## <b>🔧 Gameplay Settings:</b>
- 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
## <b>🏆 Custom Gamemodes:</b>
- 0 Kill Cooldown
- Shift and Seek
- Speedrun
## <b>❓ Other Improvements:</b>
- ehT dlekS map (reverse Skeld)
- Command Helper
- Creatable and customizable Templates
- Eht Dleks (Reverse Skeld) Map
- Ability to cancel starting countdown
- Improved main menu
- Faster startup time
- Custom anticheat system
- Zoom out in lobby or when dead
- Near unlimited default Option ranges
- More accurate Option incrementing
- Logging for useful information
- See player kill/task count and Role when dead
- Higher and more accurate Option ranges
- Always visible lobby timer
- <b>🎉 And this all works in public lobbies!</b>
### Hotkeys
@@ -91,25 +115,30 @@
### Chat Commands
| Command | Function |
| ------------------------------------------- | ------------------------------------------------- |
| /h<br>/help | Show command help |
| /l<br>/win | Show winner |
| /r | Show current gamemode/roles description |
| /0kc<br>/sns</br>/sp | Show respective gamemode description |
| /ban <name> | Ban a player by name |
| /kick <name> | Kick a player by name |
| /cban <color> | Ban a player by color |
| /ckick <color> | Kick a player by color |
| /help | Show command help |
| /l<br>/lastgame | Send last game info |
| /r | Send current gamemode/roles description |
| /r {ability} | Send specific Ability info |
| /0kc<br>/sns</br>/sp | Send respective gamemode description |
| /ban {name} | Ban a player by name |
| /kick {name} | Kick a player by name |
| /cban {color} | Ban a player by color |
| /ckick {color} | 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 |
| /eg<br>/endgame | Instantly end an ongoing game |
| /em<br>/endmeeting | Instantly end an ongoing meeting |
| /aur<br>/socials | Send AUR socials (GitHub, Discord) |
| /col<br>/color | Set color. Can be used to bypass color limit |
| /reload | Reset the *Language*.JSON file to default |
| /s<br>/start | Start game countdown |
| /vip<br>/moderator<br>/admin | Add a user to respective list by name |
| /t {template} | Send a Template from Templates.txt |
‎
**Credit to these mods and their developers for their code:**
### :star: [AUnlocker](https://github.com/astra1dev/AUnlocker)
> - Original NumberOptionsPatch
> - Always Show Lobby Timer
### :star: [EHR (Formerly TOHE+)](https://github.com/Gurge44/EndlessHostRoles)
> - Task Patching
### :star: [TOH](https://github.com/tukasa0001/TownOfHost) :
+145 -14
View File
@@ -1,12 +1,27 @@
{
"LanguageID": "0",
"gameMaster": "Game Master",
"unlockFPS": "Unlock FPS",
"showFPS": "Show FPS",
"autoStart": "Auto Start",
"enableDarkTheme": "Enable Dark Theme",
"enableLobbyMusic": "Lobby Music",
"disableInfoWhenDead": "Hide Info When Dead",
"disableCommandHelper": "Disable Command Helper",
"gameMasterWarning":"You will now spectate games until Game Master is turned off. WARNING: Ability messages will not be sent if this setting is enabled.",
"cancelStartCountdown": "Start countdown canceled",
"gamemode": "Gamemode",
"tabGroupMain": "Moderation",
"kickLowLevelPlayer": "Kick Players Under Level",
"tempBanLowLevelPlayer": "Ban Instead Of Kick",
"dontKickLevelOnes": "Don't Kick Lv.1 Players For Glitched Lobbies",
"kickInvalidFriendCodes": "Kick Invalid FriendCodes",
"tempBanInvalidFriendCodes": "Ban Instead Of Kick",
"deniedWordsToKick": "Sent Denied Words To Kick Player",
"applyBanList": "Apply BanList",
"applyDenyNameList": "Apply DenyName List",
"applyModeratorList": "Apply Moderator List",
@@ -21,23 +36,36 @@
"autoStartTimer": "Countdown For Auto Start",
"waitAutoStart": "Auto Start After",
"playerAutoStart": "Players Needed To Auto Start",
"enableJoinMessages": "Enable Welcome Messages",
"messagePerPlayerNum": "Message Per Amount Of Joins",
"tabGroupMisc": "Miscelleneous",
"startCountdown": "Default Starting Countdown",
"colorCommandLevel": "Who Can use Color Commands",
"allowFortegreen": "Allow Fortegreen Color",
"noGameEnd": "No Game End",
"tabGroupAccess": "Access Levels",
"slashColorCmd": "Who Can Use /color",
"slashRolesAndGamemodeCmd": "Who Can Use /r & Templates",
"slashLastGameCmd": "Who Can Use /l & /aur",
"slashKickCmd": "Who Can Use /kick & /ckick",
"slashBanCmd": "Who Can Use /ban & /cban",
"slashEndMeetingCmd": "Who Can Use /endmeeting",
"slashStartAndEndGameCmd": "Who Can Use /startgame & /endgame",
"tabGroupCrewmate": "Crewmate Roles",
"mayorPerc": "PLACEHOLDER",
"tabGroupNeutral": "Neutral Roles",
"jesterPerc": "PLACEHOLDER",
"tabGroupImpostor": "Impostor Roles",
"tabGroupStandard": "Standard",
"chatBeforeFirstMeeting": "Force chat 1st round to see roles (experimental)",
"tabGroupHNS": "Hide and Seek",
"numSeekers": "# Seekers",
"tabGroup0Kcd": "0 Kill Cooldown",
"noKcdSettingsOverride": "Auto Update Settings",
"tabGroupSNS": "Shift and Seek",
"snsChatInGame": "Chat during gameplay (experimental)",
"snsSettingsOverride": "Auto Update Settings",
"cantKillTime": "After Misfiring, Can't kill for",
"misfiresToSuicide": "Suicide After Amount Of Misfires",
@@ -53,6 +81,7 @@
"tabGroupSpeedrun": "Speedrun",
"speedrunSettingsOverride": "Auto Update Settings",
"gameAutoEndsAfter": "Game automatically ends after",
"engineerMode": "Everyone Is Engineer",
"tabGroupSabotages": "Sabotages",
"deadImpostorsCanSabotage": "Dead Impostors Can Sabotage",
@@ -68,11 +97,12 @@
"tabGroupGameplayGeneral": "General",
"disableAnnoyingMeetingCalls": "Disable Meeting Calls First 30s",
"disableReport": "Disable Body Reports",
"changeDecontaminationTime": "Override Decontamination Time",
"changeDecontaminationTime": "Override Decontamination Time (Standard Only)",
"decontaminationTimeOnMiraHQ": "Mira HQ Decon Duration",
"decontaminationDoorOpenTimeOnMiraHQ": "Mira HQ Door Open Duration",
"decontaminationTimeOnPolus": "Polus Decon Duration",
"decontaminationDoorOpenTimeOnPolus": "Polus Door Open Duration",
"disableSporeTrigger": "Disable Spores On The Fungle",
"disableDevices": "Disable Devices",
"disableSkeldDevices": "Disable Skeld Devices",
@@ -96,7 +126,8 @@
"tabGroupTasks": "Tasks",
"allPlayersSameTasks": "Everyone has same tasks",
"overrideTaskSettings": "<#ffd>Di<#ffb>sa<#ff9>bl<#ffb>e T<#ffd>as<#ffb>ks",
"overrideTaskSettings": "Disable Tasks",
"taskPercentNeededToWin": "% Tasks completed for crewmates to win",
"disableMiraTasks": "Disable Mira HQ Tasks",
"disableBuyBeverage": "Disable Buy Beverage",
@@ -127,10 +158,10 @@
"disablePutAwayPistols": "Disable Put Away Pistols",
"disablePutAwayRifles": "Disable Put Away Rifles",
"disableRewindTapes": "Disable Rewind Tapes",
"disableResetBreaker": "Disable Reset Breaker Task",
"disableResetBreaker": "Disable Reset Breakers",
"disableSortRecords": "Disable Sort Records",
"disableStartFans": "Disable Start Fans",
"disableUnlockSafe": "Disable Unlock Safe Task",
"disableUnlockSafe": "Disable Unlock Safe",
"disableFungleTasks": "Disable Fungle Tasks",
"disableBuildSandcastle": "Disable Build Sandcastle",
@@ -190,15 +221,115 @@
"noKcdMode": "0 Kill Cooldown:\n\nImpostors have no kill cooldown, Crewmates have low tasks\nThink fast and pay attention!",
"SnSModeOne": "Shift and Seek:\n\nImpostors can only kill someone while shapeshifted as them\nEmergency Meetings = Off",
"SnSModeTwo": "Crew wins by tasks/surviving {0}s\nImp wins by killing\nOne wrong kill = Can't kill for {1}s\n{2} wrong kills = suicide",
"SnSModeThree": "Crewmates win by doing tasks or surviving {0}s\nImpostors win by killing everyone\n{1} wrong kill(s) = suicide",
"speedrunMode": "Speedrun:\n\nEveryone is a crewmate. The 1st player to finish tasks wins the game. Game auto ends after {0}s",
"allCommandsFull": "Commands:\n/r - Current mode description\n/0kc, /sns, /sp - Specific mode description\n/l - Shows last winner info\n/kick, /ban - Bans or kicks a player by name\n/ckick, /cban - Bans or kicks a player by color",
"allCommandsOne": "Commands:\n/r - Current mode description\n/0kc, /sns, /sp - Specific mode description\n/l - Shows last winner info",
"allCommandsTwo": "/kick, /ban - Bans or kicks a player by name\n/ckick, /cban - Bans or kicks a player by color",
"SocialsAll": "AUR socials:\n\ng i t h u b . c o m /\nApeMV/AmongUsRevamped\n\nd i s c o r d . g g /\n83Zhzhyhya",
"Mayor": "Mayor",
"MayorPriv": "PRIVATE:\n\nYour role is Mayor!\n\nYou are a crewmate with i total votes. Use your voting power to eject Impostors.",
"allCommandsFull": "<b>ALL COMMANDS:</b>\n\n<b>/help</b>\nShow this message.\n<b>/aur, /socials</b>\nSend Among Us Revamped social links.\n\n<b>/r, /gm</b>\nSend current mode description or ability list.\n<b>/r {ability}</b>\nSend specific ability info.\n<b>/l, /lastgame</b>\nSend last winner info.\n\n<b>/0kc, /0killcooldown</b>\nSend 0 Kill Cooldown mode description.\n<b>/sns, /shiftandseek</b>\nSend Shift and Seek mode description.\n<b>/sp, /speedrun</b>\nSend Speedrun mode description.\n\n/<b>kick, /ban</b>\nKick or ban a player by name.\n<b>/ckick, /cban</b>\nKick or ban a player by color.\n\n<b>/vip /moderator /admin</b>\nAdd a player as VIP, Moderator, or Admin.\n<b>/removevip, /removemoderator, /removeadmin</b>\nRemove VIP, Moderator, or Admin from a player.\n\n<b>/eg, /endgame</b>\nEnd the current game.\n<b>/em, /endmeeting</b>\nEnd the current meeting.\n<b>/s, /start</b>\nBegin the game starting countdown.\n\n<b>/t {template}</b>\nSend a template from AUR-DATA/templates.txt.\n\n<b>/col, /color, /colour</b>\nSet your color, can be used to bypass limits.",
"Jester": "Jester",
"JesterPriv": "PRIVATE:\n\nYour role is Jester!\nYou are NOT a crewmate!\n\nYou win by getting voted. Act as suspicious as possible."
"socialsAll": "AUR socials:\n\ng i t h u b . c o m /\nApeMV/AmongUsRevamped\n\nd i s c o r d . g g /\n83Zhzhyhya",
"translationReloaded": "Your file has successfully been reset.\nTo apply the changes, restart your game.",
"mayorPublic": "Mayor:\n\nThe Mayor is a Crewmate with {0} additional vote(s). Use them wisely.",
"tyrantPublic": "Tyrant:\n\nThe Tyrant is an Impostor with {0} additional vote(s). Use them wisely.",
"juggernautPublic": "Juggernaut:\n\nThe Impostors instantly win if the Juggernaut gains {0} kills.",
"speedrunnerPublic": "Tasker:\n\nThe Crewmates win if the Tasker completes tasks and is alive. The Tasker has more tasks.",
"stealerPublic": "Stealer:\n\nThe Stealer gains {0} additional vote(s) per killed player. Votes are rounded down.",
"workhorsePublic": "Workhorse:\n\nThe Workhorse gains {0} additional vote(s) per completed task. Votes are rounded down.",
"jesterPublic": "Jester:\n\nThe Jester is a Crewmate who can also win alone by getting voted.",
"customRoleAnnouncement": "Custom Roles are enabled!\n\nIf you have a Custom Role, it will show in a message below this one.",
"tabGroupCrewmateAbilities": "Crewmate Ability Settings",
"crewmateAbility": "Crewmate (Role) Ability",
"scientistAbility": "Scientist Ability",
"engineerAbility": "Engineer Ability",
"noisemakerAbility": "Noisemaker Ability",
"trackerAbility": "Tracker Ability",
"detectiveAbility": "Detective Ability",
"extraVotesCrewmate": "Extra Votes For Mayor",
"extraVotesPerTask": "Extra Votes Per Task For Workhorse",
"speedrunnerShortTasks": "Short Tasks For Tasker",
"speedrunnerLongTasks": "Long Tasks For Tasker",
"tabGroupImpostorAbilities": "Impostor Ability Settings",
"impostorAbility": "Impostor (Role) Ability",
"shapeshifterAbility": "Shapeshifter Ability",
"phantomAbility": "Phantom Ability",
"viperAbility": "Viper Ability",
"extraVotesImpostor": "Extra Votes For Tyrant",
"extraVotesPerKill": "Extra Votes Per Kill For Stealer",
"killsNeededForJuggernaut": "Kills Needed For Juggernaut",
"youAreMayor": "Your Ability: Mayor\n\nYou are a Crewmate with {0} additional vote(s). Use them wisely.",
"youAreJester": "Your Ability: Jester\n\nYou can optionally win alone by getting voted, you are still a Crewmate.",
"youAreSpeedrunner": "Your Ability: Tasker\n\nThe Crewmates win if you complete tasks while being alive. You have more tasks.",
"youAreTyrant": "Your Ability: Tyrant\n\nYou are an Impostor with {0} additional vote(s). Use them wisely.",
"youAreStealer": "Your Ability: Stealer\n\nYou gain {0} additional vote(s) per killed player. Votes are rounded down.",
"youAreWorkhorse": "Your Ability: Workhorse\n\nYou gain {0} additional vote(s) per completed task. Votes are rounded down.",
"youAreJuggernaut": "Your Ability: Juggernaut\n\nThe Impostor team instantly wins if you gain {0} kills.",
"jesterWin": "Jester wins! (voted)\n\nImpostors: ",
"speedrunnerWin": "Crewmates win! (Tasker finished tasks)\n\nImpostors: ",
"juggernautWin": "Impostors win! (Juggernaut killed {0} players)\n\nImpostors: ",
"crewmateWin": "Crewmates Win!\n\nImpostors: ",
"impostorWin": "Impostors Win!\n\nImpostors: ",
"crewmateWinTasks": "Crewmates Win! ({0}% tasks completed)\n\nImpostors: ",
"impostorWinMisc": "Impostors Win! (Sabotage)\n\n Impostors: ",
"crewmateWinTimer": "Crewmates Win! (Survived {0}s)\n\n Impostors: ",
"noOneWin": "No one wins. ({0}s Timer)",
"ability": "Ability",
"templateWelcome": "# In this file you can add Templates, which serve as easy copy-paste alternatives.\n# To create a template, write a new line with the same formatting as the test Template below.\n# Note that Templates can't be longer than 120 characters and can't contain special characters. Having so will kick you.\n\ntest: this is an example template. Type '/t test' to see it.\n\nwelcome: Welcome! This lobby uses Among Us Revamped {ModVersion} by MV. Enjoy!",
"moderatorWelcome": "# In this file you can add Moderators by Friendcode.\n# If you add someone, they will gain a purple name in-game.\n# Go to 'System Settings' in-game to customize Moderator permissions. Below is a Friendcode example.\n\nfriendcode#0000",
"vipWelcome": "# In this file you can add VIP's by Friendcode.\n# If you add someone, they will gain a yellow name in-game.\n# Go to 'System Settings' in-game to customize VIP permissions. Below is a Friendcode example.\n\nfriendcode#0000\n",
"adminWelcome": "# In this file you can add Admins by Friendcode.\n# If you add someone, they will gain a red name in-game.\n# Go to 'System Settings' in-game to customize Admin permissions. Below is a Friendcode example.\n\nfriendcode#0000\n",
"banlistWelcome": "# In this file you can ban players from your lobby by Friendcode.\n# Banning someone in-game will automatically add them here as well. Below is a Friendcode example.\n\nfriendcode#0000\n",
"banwordWelcome": "# In this file you can set denied words, automatically kicking anyone in-game who sends words listed here.\n# Make sure to separate words by using new lines.",
"bannameWelcome": "# In this file you can set denied names, automatically kicking anyone in-game who uses names listed here.\n# Make sure to separate names by using new lines.",
"noGameEndWarning": "WARNING: No Game End is enabled",
"tooLongTemplate": "Your Template is longer than 120 characters and would kick you upon sending. Please reduce the length.",
"vipAdd": "Successfully added {0} as VIP.",
"moderatorAdd": "Successfully added {0} as Moderator.",
"adminAdd": "Successfully added {0} as Admin.",
"vipRemove": "Successfully removed VIP from {0}.",
"moderatorRemove": "Successfully removed Moderator from {0}.",
"adminRemove": "Successfully removed Admin from {0}.",
"permFail": "Could not find user '{0}'. Did you write it correctly?",
"helpDesc": "Show all commands and what they do.",
"snsDesc": "Send Shift and Seek gamemode Description.",
"0kcDesc": "Send 0 Kill Cooldown gamemode Description.",
"SrDesc": "Send Speedrun gamemode Description.",
"egDesc": "End the current game.",
"emDesc": "End the current meeting.",
"aurDesc": "Send Among Us Revamped social links.",
"sDesc": "Start the game countdown.",
"rDesc": "/r sends active abilities or current gamemode. /r {ability} sends specific ability info",
"rolesDesc": "Send all abilities/gamemode overview.",
"kickDesc": "Kick a player by name.",
"ckickDesc": "Kick a player by color.",
"banDesc": "Ban a player by name.",
"cbanDesc": "Ban a player by color.",
"dumpDesc": "Copy LogOutput into a seperate file.",
"colDesc": "Set your color.",
"reloadDesc": "Reload language file.",
"vipDesc": "Add user as VIP.",
"moderatorDesc": "Add user as Moderator.",
"adminDesc": "Add user as admin.",
"cremoveVipDesc": "Remove VIP from user.",
"removeModeratorDesc": "Remove Moderator from user.",
"removeAdminDesc": "Remove Admin from user.",
"lastgameDesc": "Send last game info.",
"templateDesc": "Send a specified template from AUR-DATA/templates.txt.",
"banWordKick": "{0} was kicked because they sent a banned word {1} time(s)"
}