diff --git a/CTA/CustomTeamAssigner/CustomRoles.cs b/CTA/CustomTeamAssigner/CustomRoles.cs index d85a22d65..c7f029308 100644 --- a/CTA/CustomTeamAssigner/CustomRoles.cs +++ b/CTA/CustomTeamAssigner/CustomRoles.cs @@ -94,6 +94,7 @@ public enum CustomRoles Overheat, Parasite, Penguin, + Perplexer, Postponer, Psychopath, Puppeteer, diff --git a/CustomRoles.cs b/CustomRoles.cs index d85a22d65..c7f029308 100644 --- a/CustomRoles.cs +++ b/CustomRoles.cs @@ -94,6 +94,7 @@ public enum CustomRoles Overheat, Parasite, Penguin, + Perplexer, Postponer, Psychopath, Puppeteer, diff --git a/Gamemodes/StopAndGo.cs b/Gamemodes/StopAndGo.cs index 65d921d7a..a84683085 100644 --- a/Gamemodes/StopAndGo.cs +++ b/Gamemodes/StopAndGo.cs @@ -82,7 +82,7 @@ internal class StopAndGoPlayerData(Counter[] counters, float positionX, float po public int Lives { get; private set; } = lives; - private Stopwatch LostLifeCooldownTimer { get; set; } + private Stopwatch LostLifeCooldownTimer { get; set; } = Stopwatch.StartNew(); public override string ToString() { diff --git a/Main.cs b/Main.cs index ebdde035d..b1ee3f93a 100644 --- a/Main.cs +++ b/Main.cs @@ -30,7 +30,8 @@ namespace EHR; [BepInPlugin(PluginGuid, "EHR", PluginVersion)] [BepInIncompatibility("jp.ykundesu.supernewroles")] [BepInIncompatibility("MalumMenu")] -[BepInIncompatibility("com.ten.thebetterroles")] +[BepInIncompatibility("com.crewmod.oficial")] +[BepInIncompatibility("com.crewmod.showcase")] [BepInIncompatibility("xyz.crowdedmods.crowdedmod")] [BepInDependency(SubmergedCompatibility.SubmergedGuid, BepInDependency.DependencyFlags.SoftDependency)] [BepInProcess("Among Us.exe")] diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 688ba9e48..63c7af094 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -368,6 +368,7 @@ internal static class CustomRolesHelper CustomRoles.Unshifter => CustomRoles.Impostor, CustomRoles.Scanner => CustomRoles.Phantom, CustomRoles.Fakeshifter => CustomRoles.Shapeshifter, + CustomRoles.Perplexer => CustomRoles.Shapeshifter, CustomRoles.Silencer => Silencer.SilenceMode.GetValue() switch { 0 => CustomRoles.Impostor, @@ -831,7 +832,8 @@ internal static class CustomRolesHelper CustomRoles.Camouflager or CustomRoles.Twister or CustomRoles.Lurker or - CustomRoles.Fakeshifter; + CustomRoles.Fakeshifter or + CustomRoles.Perplexer; } public static bool IsNeutral(this CustomRoles role, bool check = false) @@ -1128,7 +1130,7 @@ internal static class CustomRolesHelper public static bool CheckAddonConflict(CustomRoles role, PlayerControl pc) { - return role.IsAdditionRole() && !(role.IsGhostRole() && pc.IsAlive()) && (!Main.NeverSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out Dictionary> neverList) || !neverList.TryGetValue(pc.GetCustomRole(), out List bannedAddonList) || !bannedAddonList.Contains(role)) && pc.GetCustomRole() is not CustomRoles.GuardianAngelEHR and not CustomRoles.God && !pc.Is(CustomRoles.Madmate) && !pc.Is(CustomRoles.GM) && role is not CustomRoles.Lovers && !pc.Is(CustomRoles.LazyGuy) && (!pc.HasSubRole() || pc.GetCustomSubRoles().Count < Options.NoLimitAddonsNumMax.GetInt()) && (!Options.AddonCanBeSettings.TryGetValue(role, out (OptionItem Imp, OptionItem Neutral, OptionItem Crew, OptionItem Coven) o) || ((o.Imp.GetBool() || !pc.GetCustomRole().IsImpostor()) && (o.Neutral.GetBool() || !pc.GetCustomRole().IsNeutral()) && (o.Crew.GetBool() || !pc.IsCrewmate()) && (o.Coven.GetBool() || !pc.Is(Team.Coven)))) && (!role.IsImpOnlyAddon() || (pc.IsImpostor() && !pc.Is(CustomRoles.DoubleAgent)) || (pc.Is(CustomRoles.Traitor) && Traitor.CanGetImpostorOnlyAddons.GetBool())) && role switch + return role.IsAdditionRole() && !(role.IsGhostRole() && pc.IsAlive()) && (!Main.NeverSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out Dictionary> neverList) || !neverList.TryGetValue(pc.GetCustomRole(), out List bannedAddonList) || !bannedAddonList.Contains(role)) && pc.GetCustomRole() is not CustomRoles.GuardianAngelEHR and not CustomRoles.God && !pc.Is(CustomRoles.Madmate) && !pc.Is(CustomRoles.GM) && role is not CustomRoles.Lovers && !pc.Is(CustomRoles.LazyGuy) && (Options.AddonAssigningRolesIgnoreMaxAddonsLimit.GetBool() || !pc.HasSubRole() || pc.GetCustomSubRoles().Count < Options.NoLimitAddonsNumMax.GetInt()) && (!Options.AddonCanBeSettings.TryGetValue(role, out (OptionItem Imp, OptionItem Neutral, OptionItem Crew, OptionItem Coven) o) || ((o.Imp.GetBool() || !pc.GetCustomRole().IsImpostor()) && (o.Neutral.GetBool() || !pc.GetCustomRole().IsNeutral()) && (o.Crew.GetBool() || !pc.IsCrewmate()) && (o.Coven.GetBool() || !pc.Is(Team.Coven)))) && (!role.IsImpOnlyAddon() || (pc.IsImpostor() && !pc.Is(CustomRoles.DoubleAgent)) || (pc.Is(CustomRoles.Traitor) && Traitor.CanGetImpostorOnlyAddons.GetBool())) && role switch { CustomRoles.Blind when pc.Is(CustomRoles.Sensor) => false, CustomRoles.Composter when float.IsNaN(pc.GetAbilityUseLimit()) => false, @@ -1694,6 +1696,7 @@ internal static class CustomRolesHelper CustomRoles.Librarian => RoleOptionType.Impostor_Support, CustomRoles.Nullifier => RoleOptionType.Impostor_Support, CustomRoles.Occultist => RoleOptionType.Impostor_Support, + CustomRoles.Perplexer => RoleOptionType.Impostor_Support, CustomRoles.Silencer => RoleOptionType.Impostor_Support, CustomRoles.Swapster => RoleOptionType.Impostor_Support, CustomRoles.TimeThief => RoleOptionType.Impostor_Support, diff --git a/Modules/CustomRpcSender.cs b/Modules/CustomRpcSender.cs index 1baa80a93..377923ffc 100644 --- a/Modules/CustomRpcSender.cs +++ b/Modules/CustomRpcSender.cs @@ -709,6 +709,15 @@ public static class CustomRpcSenderExtensions return hasValue; } + public static bool RpcExileV2(this CustomRpcSender sender, PlayerControl player) + { + player.Exiled(); + sender.AutoStartRpc(player.NetId, RpcCalls.Exiled) + .EndRpc(); + FixedUpdatePatch.LoversSuicide(player.PlayerId); + return true; + } + public static bool SyncSettings(this CustomRpcSender sender, PlayerControl player) { if (GameStates.CurrentServerType == GameStates.ServerType.Vanilla) diff --git a/Modules/OptionHolder.cs b/Modules/OptionHolder.cs index b5147a417..c3c28c1e9 100644 --- a/Modules/OptionHolder.cs +++ b/Modules/OptionHolder.cs @@ -812,6 +812,7 @@ public static class Options public static OptionItem NameDisplayAddonsOnlyInMeetings; public static OptionItem AddBracketsToAddons; public static OptionItem NoLimitAddonsNumMax; + public static OptionItem AddonAssigningRolesIgnoreMaxAddonsLimit; public static OptionItem CharmedCanBeGuessed; public static OptionItem ContagiousCanBeGuessed; @@ -1455,6 +1456,9 @@ public static class Options NoLimitAddonsNumMax = new IntegerOptionItem(211, "NoLimitAddonsNumMax", new(1, 90, 1), 1, TabGroup.Addons) .SetGameMode(CustomGameMode.Standard); + + AddonAssigningRolesIgnoreMaxAddonsLimit = new BooleanOptionItem(214, "AddonAssigningRolesIgnoreMaxAddonsLimit", false, TabGroup.Addons) + .SetGameMode(CustomGameMode.Standard); CharmedCanBeGuessed = new StringOptionItem(213, "ConvertedAddonCanBeGuessed", AddonGuessOptions, 2, TabGroup.Addons) .SetHeader(true) diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index 6169d1811..5f360aa2e 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -2476,7 +2476,7 @@ internal static class ChatCommands private static void RCommand(PlayerControl player, string text, string[] args) { string subArgs = text.Remove(0, 2); - byte to = player.AmOwner && Input.GetKey(KeyCode.LeftShift) ? byte.MaxValue : player.PlayerId; + byte to = player.AmOwner && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) ? byte.MaxValue : player.PlayerId; SendRolesInfo(subArgs, to); } @@ -3296,7 +3296,8 @@ internal static class ChatUpdatePatch chatBubble.Background.color = new(0.1f, 0.1f, 0.1f, 1f); } - LastMessages.RemoveAll(x => Utils.TimeStamp - x.SendTimeStamp > 10); + long now = Utils.TimeStamp; + LastMessages.RemoveAll(x => now - x.SendTimeStamp > 10); } internal static bool SendLastMessages(ref CustomRpcSender sender) diff --git a/Patches/ChatControlPatch.cs b/Patches/ChatControlPatch.cs index fdaa82be8..14565cbc8 100644 --- a/Patches/ChatControlPatch.cs +++ b/Patches/ChatControlPatch.cs @@ -41,17 +41,17 @@ internal static class ChatControllerUpdatePatch __instance.quickChatField.background.color = new Color32(40, 40, 40, byte.MaxValue); __instance.quickChatField.text.color = Color.white; - if (QuickChatIcon == null) + if (!QuickChatIcon) QuickChatIcon = GameObject.Find("QuickChatIcon")?.transform.GetComponent(); else QuickChatIcon.sprite = Utils.LoadSprite("EHR.Resources.Images.DarkQuickChat.png", 100f); - if (OpenBanMenuIcon == null) + if (!OpenBanMenuIcon) OpenBanMenuIcon = GameObject.Find("OpenBanMenuIcon")?.transform.GetComponent(); else OpenBanMenuIcon.sprite = Utils.LoadSprite("EHR.Resources.Images.DarkReport.png", 100f); - if (OpenKeyboardIcon == null) + if (!OpenKeyboardIcon) OpenKeyboardIcon = GameObject.Find("OpenKeyboardIcon")?.transform.GetComponent(); else OpenKeyboardIcon.sprite = Utils.LoadSprite("EHR.Resources.Images.DarkKeyboard.png", 100f); @@ -256,7 +256,7 @@ public static class ChatManager for (var j = 2; j < entryParts.Length; j++) senderMessage += ':' + entryParts[j].Trim(); PlayerControl senderPlayer = Utils.GetPlayerById(Convert.ToByte(senderId)); - if (senderPlayer == null) continue; + if (!senderPlayer) continue; chat.AddChat(senderPlayer, senderMessage); SendRPC(writer, senderPlayer, senderMessage); @@ -289,14 +289,14 @@ public static class ChatManager { if (!AmongUsClient.Instance.AmHost) return; PlayerControl player = GameStates.CurrentServerType == GameStates.ServerType.Vanilla ? PlayerControl.LocalPlayer : Main.EnumerateAlivePlayerControls().MinBy(x => x.PlayerId) ?? Main.EnumeratePlayerControls().MinBy(x => x.PlayerId) ?? PlayerControl.LocalPlayer; - if (player == null) return; + if (!player) return; if (targets.Count == 0 || targets.Count >= Main.AllAlivePlayerControls.Count) SendEmptyMessage(null); else targets.Do(SendEmptyMessage); return; void SendEmptyMessage(PlayerControl receiver) { - bool toEveryone = receiver == null; + bool toEveryone = !receiver; bool toLocalPlayer = !toEveryone && receiver.AmOwner; if (HudManager.InstanceExists && (toLocalPlayer || toEveryone)) HudManager.Instance.Chat.AddChat(player, "."); if (toLocalPlayer) return; diff --git a/Patches/ControlPatch.cs b/Patches/ControlPatch.cs index b4d91fd88..50ed770c6 100644 --- a/Patches/ControlPatch.cs +++ b/Patches/ControlPatch.cs @@ -31,7 +31,7 @@ internal static class ControllerManagerUpdatePatch { if (HudManager.InstanceExists) { - if (PlayerControl.LocalPlayer != null) + if (PlayerControl.LocalPlayer) { if (Input.GetKeyDown(KeyCode.LeftControl)) { @@ -46,7 +46,7 @@ internal static class ControllerManagerUpdatePatch } } - if (GameStates.IsLobby && (HudManager.Instance.Chat == null || !HudManager.Instance.Chat.IsOpenOrOpening)) + if (GameStates.IsLobby && (!HudManager.Instance.Chat || !HudManager.Instance.Chat.IsOpenOrOpening)) { if (Input.GetKeyDown(KeyCode.Tab)) OptionShower.Next(); @@ -56,7 +56,7 @@ internal static class ControllerManagerUpdatePatch OptionShower.CurrentPage = i; } - if (KeysDown(KeyCode.Return) && GameSettingMenu.Instance != null && GameSettingMenu.Instance.isActiveAndEnabled) + if (KeysDown(KeyCode.Return) && GameSettingMenu.Instance && GameSettingMenu.Instance.isActiveAndEnabled) GameSettingMenuPatch.SearchForOptionsAction?.Invoke(); } } @@ -149,7 +149,7 @@ internal static class ControllerManagerUpdatePatch Logger.SendInGame(GetString("CancelStartCountDown")); } - if (Input.GetKeyDown(KeyCode.Return) && GameStates.IsLobby && GameStartManager.InstanceExists && Options.EnterKeyToStartGame.GetBool() && GameStartManager.Instance.startState == GameStartManager.StartingStates.NotStarting && !HudManager.Instance.Chat.IsOpenOrOpening && !OnGameJoinedPatch.JoiningGame && GameSettingMenu.Instance == null) + if (Input.GetKeyDown(KeyCode.Return) && GameStates.IsLobby && GameStartManager.InstanceExists && Options.EnterKeyToStartGame.GetBool() && GameStartManager.Instance.startState == GameStartManager.StartingStates.NotStarting && !HudManager.Instance.Chat.IsOpenOrOpening && !OnGameJoinedPatch.JoiningGame && !GameSettingMenu.Instance) { Logger.Info("ENTER pressed: Starting game by host", "KeyCommand"); GameStartManager.Instance.BeginGame(); @@ -377,7 +377,7 @@ public static class InGameRoleInfoMenu private static GameObject MainInfo; private static GameObject AddonsInfo; - public static bool Showing => Fill != null && Fill.active && Menu != null && Menu.active; + public static bool Showing => Fill && Fill.active && Menu && Menu.active; private static SpriteRenderer FillSp => Fill.GetComponent(); private static TextMeshPro MainInfoTMP => MainInfo.GetComponent(); private static TextMeshPro AddonsInfoTMP => AddonsInfo.GetComponent(); @@ -418,7 +418,7 @@ public static class InGameRoleInfoMenu public static void SetRoleInfoRef(PlayerControl player) { - if (player == null) return; + if (!player) return; if (!Fill || !Menu) Init(); diff --git a/Patches/CredentialsPatch.cs b/Patches/CredentialsPatch.cs index 8db918230..eb5aadb9e 100644 --- a/Patches/CredentialsPatch.cs +++ b/Patches/CredentialsPatch.cs @@ -23,9 +23,9 @@ internal static class PingTrackerUpdatePatch { FpsSampler.TickFrame(); - PingTracker instance = Instance == null ? __instance : Instance; + PingTracker instance = !Instance ? __instance : Instance; - if (AmongUsClient.Instance == null) return false; + if (!AmongUsClient.Instance) return false; if (AmongUsClient.Instance.NetworkMode == NetworkModes.FreePlay) { @@ -40,7 +40,7 @@ internal static class PingTrackerUpdatePatch instance.text.text = Sb.ToString(); } - if (Instance == null) Instance = __instance; + if (!Instance) Instance = __instance; long now = Utils.TimeStamp; if (now == LastUpdate) return false; @@ -125,7 +125,7 @@ internal static class VersionShowerStartPatch ErrorText.Create(__instance.text); - if (Main.HasArgumentException && ErrorText.Instance != null) + if (Main.HasArgumentException && ErrorText.Instance) ErrorText.Instance.AddError(ErrorCode.Main_DictionaryError); VersionChecker.Check(); @@ -146,7 +146,7 @@ public static class UpdateFriendCodeUIPatch GameObject friendCode = GameObject.Find("FriendCode"); - if (friendCode != null && VersionShower == null) + if (friendCode && !VersionShower) { VersionShower = Object.Instantiate(friendCode, friendCode.transform.parent); VersionShower.name = "EHR Version Shower"; @@ -160,7 +160,7 @@ public static class UpdateFriendCodeUIPatch GameObject newRequest = GameObject.Find("NewRequest"); - if (newRequest != null) + if (newRequest) { newRequest.transform.localPosition -= new Vector3(0f, 0f, 10f); newRequest.transform.localScale = new(0f, 0f, 0f); @@ -168,7 +168,7 @@ public static class UpdateFriendCodeUIPatch GameObject friendsButton = GameObject.Find("FriendsButton"); - if (friendsButton != null) + if (friendsButton) { friendsButton.transform.FindChild("Highlight").GetComponent().color = new(0f, 0.647f, 1f, 1f); friendsButton.transform.FindChild("Inactive").GetComponent().color = new(0f, 0.847f, 1f, 1f); @@ -191,7 +191,7 @@ internal static class FriendsListUIOpenPatch for (var index = 0; index < componentsInChildren.Length; ++index) { - if (componentsInChildren[index] != null) + if (componentsInChildren[index]) Object.Destroy(componentsInChildren[index].gameObject); } @@ -199,7 +199,7 @@ internal static class FriendsListUIOpenPatch __instance.currentSceneName = activeScene.name; __instance.UpdateFriendCodeUI(); - if ((HudManager.InstanceExists && HudManager.Instance != null && HudManager.Instance.Chat != null && HudManager.Instance.Chat.IsOpenOrOpening) || ShipStatus.Instance != null) + if ((HudManager.InstanceExists && HudManager.InstanceExists && HudManager.Instance.Chat && HudManager.Instance.Chat.IsOpenOrOpening) || ShipStatus.Instance) return false; __instance.friendBars = new(); @@ -340,7 +340,7 @@ internal static class TitleLogoPatch bool newYear = now is { Month: 1, Day: <= 6 }; bool easter = IsEasterPeriod(); - if (SpecialMessage == null && (holidays || christmas || newYear || easter)) + if (!SpecialMessage && (holidays || christmas || newYear || easter)) { SpecialMessage = new GameObject("SpecialMessage"); SpecialMessage.transform.SetParent(__instance.transform); @@ -356,7 +356,7 @@ internal static class TitleLogoPatch text.text = $"{GetString(holidays ? "HolidayGreeting" : christmas ? "ChristmasGreeting" : newYear ? "NewYearGreeting" : "EasterGreeting")}"; } - if (CustomBG == null && (holidays || christmas || newYear || easter)) + if (!CustomBG && (holidays || christmas || newYear || easter)) { CustomBG = new GameObject("CustomBG"); CustomBG.transform.SetParent(__instance.transform); @@ -364,7 +364,7 @@ internal static class TitleLogoPatch var sr = CustomBG.AddComponent(); sr.sprite = Utils.LoadSprite(easter ? "EHR.Resources.Images.EasterBG.jpg" : "EHR.Resources.Images.WinterBG.jpg", 180f); PlayerParticles pp = Object.FindObjectOfType(); - if (pp != null) pp.gameObject.SetActive(false); + if (pp) pp.gameObject.SetActive(false); } if (!(ModStamp = GameObject.Find("ModStamp"))) return; @@ -373,7 +373,7 @@ internal static class TitleLogoPatch Ambience = GameObject.Find("Ambience"); - if (Ambience != null) + if (Ambience) { try { __instance.playButton.transform.gameObject.SetActive(true); } catch (Exception ex) { Logger.Warn(ex.ToString(), "MainMenuLoader"); } @@ -399,7 +399,7 @@ internal static class TitleLogoPatch foreach (KeyValuePair, (Sprite, Color, Color, Color, Color)> kvp in mainButtons) kvp.Key.Do(button => FormatButtonColor(button, kvp.Value.Item2, kvp.Value.Item3, kvp.Value.Item4, kvp.Value.Item5)); - try { mainButtons.Keys.Flatten().DoIf(x => x != null, x => x.buttonText.color = Color.white); } + try { mainButtons.Keys.Flatten().DoIf(x => x, x => x.buttonText.color = Color.white); } catch { } GameObject.Find("Divider")?.SetActive(false); @@ -518,7 +518,7 @@ internal static class OptionsMenuBehaviourOpenPatch } else { - if (Minigame.Instance != null) Minigame.Instance.Close(); + if (Minigame.Instance) Minigame.Instance.Close(); __instance.OpenTabGroup(0); __instance.UpdateButtons(); diff --git a/Patches/ExilePatch.cs b/Patches/ExilePatch.cs index 8076be736..2b0236844 100644 --- a/Patches/ExilePatch.cs +++ b/Patches/ExilePatch.cs @@ -5,6 +5,7 @@ using AmongUs.Data; using EHR.Modules; using EHR.Roles; using HarmonyLib; +using Hazel; namespace EHR.Patches; @@ -169,7 +170,10 @@ internal static class ExileControllerWrapUpPatch return; } - Main.AfterMeetingDeathPlayers.Keys.ToValidPlayers().Do(x => x.RpcExileV2()); + bool hasValue = false; + CustomRpcSender sender = CustomRpcSender.Create("Exile AfterMeetingDeathPlayers", SendOption.Reliable); + Main.AfterMeetingDeathPlayers.Keys.ToValidPlayers().Do(x => hasValue |= sender.RpcExileV2(x)); + sender.SendMessage(dispose: !hasValue); foreach ((byte id, PlayerState.DeathReason deathReason) in Main.AfterMeetingDeathPlayers) { @@ -181,7 +185,7 @@ internal static class ExileControllerWrapUpPatch state.deathReason = deathReason; state.SetDead(); - if (player == null) continue; + if (!player) continue; if (deathReason == PlayerState.DeathReason.Suicide) player.SetRealKiller(player, true); diff --git a/Patches/GameOptionsMenuPatch.cs b/Patches/GameOptionsMenuPatch.cs index eedb0faa8..e04568c08 100644 --- a/Patches/GameOptionsMenuPatch.cs +++ b/Patches/GameOptionsMenuPatch.cs @@ -51,21 +51,21 @@ public static class GameOptionsMenuPatch private static void InitializePostfix() { GameObject optionMenu = GameObject.Find("PlayerOptionsMenu(Clone)"); - if (optionMenu == null) return; + if (!optionMenu) return; optionMenu.transform.FindChild("Background")?.gameObject.SetActive(false); // By TommyXL LateTask.New(() => { - if (optionMenu == null) return; + if (!optionMenu) return; Transform menuDescription = optionMenu.transform.FindChild("What Is This?"); - if (menuDescription == null) return; + if (!menuDescription) return; Transform infoImage = menuDescription.transform.FindChild("InfoImage"); - if (infoImage != null) + if (infoImage) { infoImage.transform.localPosition = new(-4.65f, 0.16f, -1f); infoImage.transform.localScale = new(0.2202f, 0.2202f, 0.3202f); @@ -73,7 +73,7 @@ public static class GameOptionsMenuPatch Transform infoText = menuDescription.transform.FindChild("InfoText"); - if (infoText != null) + if (infoText) { infoText.transform.localPosition = new(-3.5f, 0.83f, -2f); infoText.transform.localScale = new(1f, 1f, 1f); @@ -81,13 +81,13 @@ public static class GameOptionsMenuPatch Transform cubeObject = menuDescription.transform.FindChild("Cube"); - if (cubeObject != null) + if (cubeObject) { cubeObject.transform.localPosition = new(-3.2f, 0.55f, -0.1f); cubeObject.transform.localScale = new(0.61f, 0.64f, 1f); } - if (GameSettingMenu.Instance != null && GameSettingMenu.Instance.MenuDescriptionText != null) + if (GameSettingMenu.Instance && GameSettingMenu.Instance.MenuDescriptionText) GameSettingMenu.Instance.MenuDescriptionText.m_marginWidth = 2.5f; }, 0.2f, log: false); } @@ -160,7 +160,7 @@ public static class GameOptionsMenuPatch num -= 0.18f; BaseGameSetting baseGameSetting = GetSetting(option); - if (baseGameSetting == null) continue; + if (!baseGameSetting) continue; OptionBehaviour optionBehaviour; @@ -429,7 +429,7 @@ public static class GameOptionsMenuPatch break; } - if (baseGameSetting != null) baseGameSetting.Title = StringNames.Accept; + if (baseGameSetting) baseGameSetting.Title = StringNames.Accept; return baseGameSetting; } @@ -438,7 +438,7 @@ public static class GameOptionsMenuPatch public static void ReloadUI() { int tab = ModGameOptionsMenu.TabIndex; - if (GameSettingMenu.Instance == null) return; + if (!GameSettingMenu.Instance) return; GameSettingMenu.Instance.Close(); OptionsConsole optionsConsole = null; @@ -789,10 +789,10 @@ public static class StringOptionPatch GameObject gameObject = GameObject.Find("PlayerOptionsMenu(Clone)"); - if (gameObject != null) + if (gameObject) { Transform findChild = gameObject.transform.FindChild("What Is This?"); - if (findChild != null) findChild.gameObject.SetActive(false); + if (findChild) findChild.gameObject.SetActive(false); } GameSettingMenuPatch.GMButtons.ForEach(x => x.gameObject.SetActive(true)); @@ -1104,7 +1104,7 @@ public static class GameSettingMenuPatch minus.OnClick.AddListener((Action)(() => { - if (PresetBehaviour == null) + if (!PresetBehaviour) __instance.ChangeTab(3, false); LastPresetChange = Utils.TimeStamp; @@ -1141,7 +1141,7 @@ public static class GameSettingMenuPatch plus.OnClick.AddListener((Action)(() => { - if (PresetBehaviour == null) + if (!PresetBehaviour) __instance.ChangeTab(3, false); LastPresetChange = Utils.TimeStamp; @@ -1279,7 +1279,7 @@ public static class GameSettingMenuPatch HiddenBySearch = result; System.Collections.Generic.List searchWinners = optionItems.Where(x => x.Parent == null && !x.IsCurrentlyHidden() && !result.Contains(x)).ToList(); - if (searchWinners.Count == 0 || !ModSettingsTabs.TryGetValue(modTab, out GameOptionsMenu gameSettings) || gameSettings == null) + if (searchWinners.Count == 0 || !ModSettingsTabs.TryGetValue(modTab, out GameOptionsMenu gameSettings) || !gameSettings) { HiddenBySearch.Clear(); Logger.SendInGame(Translator.GetString("SearchNoResult"), Palette.Orange); @@ -1329,7 +1329,7 @@ public static class GameSettingMenuPatch { HiddenBySearch.Do(x => x.SetHidden(false)); - if (ModSettingsTabs.TryGetValue((TabGroup)(ModGameOptionsMenu.TabIndex - 3), out GameOptionsMenu gameSettings) && gameSettings != null) + if (ModSettingsTabs.TryGetValue((TabGroup)(ModGameOptionsMenu.TabIndex - 3), out GameOptionsMenu gameSettings) && gameSettings) GameOptionsMenuPatch.ReCreateSettings(gameSettings); HiddenBySearch.Clear(); @@ -1346,13 +1346,13 @@ public static class GameSettingMenuPatch foreach (TabGroup tab in tabGroups) { - if (ModSettingsTabs.TryGetValue(tab, out settingsTab) && settingsTab != null) + if (ModSettingsTabs.TryGetValue(tab, out settingsTab) && settingsTab) settingsTab.gameObject.SetActive(false); } foreach (TabGroup tab in tabGroups) { - if (ModSettingsButtons.TryGetValue(tab, out button) && button != null) + if (ModSettingsButtons.TryGetValue(tab, out button) && button) button.SelectButton(false); } } @@ -1370,7 +1370,7 @@ public static class GameSettingMenuPatch __instance.GameSettingsButton.SelectButton(false); __instance.RoleSettingsButton.SelectButton(false); - if (ModSettingsTabs.TryGetValue(tabGroup, out settingsTab) && settingsTab != null) + if (ModSettingsTabs.TryGetValue(tabGroup, out settingsTab) && settingsTab) { settingsTab.gameObject.SetActive(true); __instance.MenuDescriptionText.DestroyTranslator(); @@ -1388,7 +1388,7 @@ public static class GameSettingMenuPatch __instance.ToggleLeftSideDarkener(true); __instance.ToggleRightSideDarkener(false); - if (ModSettingsButtons.TryGetValue(tabGroup, out button) && button != null) button.SelectButton(true); + if (ModSettingsButtons.TryGetValue(tabGroup, out button) && button) button.SelectButton(true); return false; } @@ -1397,13 +1397,13 @@ public static class GameSettingMenuPatch [HarmonyPrefix] private static bool OnEnablePrefix(GameSettingMenu __instance) { - if (TemplateGameOptionsMenu == null) + if (!TemplateGameOptionsMenu) { TemplateGameOptionsMenu = Object.Instantiate(__instance.GameSettingsTab, __instance.GameSettingsTab.transform.parent); TemplateGameOptionsMenu.gameObject.SetActive(false); } - if (TemplateGameSettingsButton == null) + if (!TemplateGameSettingsButton) { TemplateGameSettingsButton = Object.Instantiate(__instance.GameSettingsButton, __instance.GameSettingsButton.transform.parent); TemplateGameSettingsButton.gameObject.SetActive(false); @@ -1478,7 +1478,7 @@ public static class FixInputChatField { public static bool Prefix(FreeChatInputField __instance) { - if (GameSettingMenuPatch.InputField != null && __instance == GameSettingMenuPatch.InputField) + if (GameSettingMenuPatch.InputField && __instance == GameSettingMenuPatch.InputField) { Vector2 size = __instance.Background.size; size.y = Math.Max(0.62f, __instance.textArea.TextHeight + 0.2f); @@ -1499,7 +1499,7 @@ public static class FixDarkThemeForSearchBar FreeChatInputField field = GameSettingMenuPatch.InputField; - if (field != null) + if (field) { field.background.color = new Color32(40, 40, 40, byte.MaxValue); field.textArea.compoText.Color(Color.white); diff --git a/Patches/GameStartManagerPatch.cs b/Patches/GameStartManagerPatch.cs index 8b320d1e5..be5c1bbbe 100644 --- a/Patches/GameStartManagerPatch.cs +++ b/Patches/GameStartManagerPatch.cs @@ -44,7 +44,7 @@ public static class GameStartManagerPatch { try { - if (__instance == null) return; + if (!__instance) return; GameCountdown = Object.Instantiate(__instance.PlayerCounter, __instance.HostInfoPanel.transform); GameCountdown.text = string.Empty; @@ -82,7 +82,7 @@ public static class GameStartManagerPatch __instance.ClientViewButton.inactiveSprites.transform.Find("Shine").GetComponent().color = new(0f, 1f, 1f, 0.5f); } - if (AmongUsClient.Instance == null || AmongUsClient.Instance.IsGameStarted || GameStates.IsInGame || __instance.startState == GameStartManager.StartingStates.Starting) return; + if (!AmongUsClient.Instance || AmongUsClient.Instance.IsGameStarted || GameStates.IsInGame || __instance.startState == GameStartManager.StartingStates.Starting) return; __instance.GameRoomNameCode.text = GameCode.IntToGameName(AmongUsClient.Instance.GameId); // Reset lobby countdown timer @@ -135,28 +135,28 @@ public static class GameStartManagerPatch try { __instance.MinPlayers = 1; } catch (Exception ex) { Logger.Error(ex.ToString(), "Surely this can't be causing an issue, right?"); } - if (AmongUsClient.Instance == null) return false; + if (!AmongUsClient.Instance) return false; if (AmongUsClient.Instance.AmHost) VanillaUpdate(__instance); - if (AmongUsClient.Instance.IsGameStarted || GameStates.IsInGame || __instance == null || __instance.startState == GameStartManager.StartingStates.Starting) return false; + if (AmongUsClient.Instance.IsGameStarted || GameStates.IsInGame || !__instance || __instance.startState == GameStartManager.StartingStates.Starting) return false; // Lobby code if (DataManager.Settings != null && DataManager.Settings.Gameplay != null) { if (DataManager.Settings.Gameplay.StreamerMode) { - if (__instance.GameRoomNameCode != null) __instance.GameRoomNameCode.color = new(255, 255, 255, 0); - if (GameStartManagerStartPatch.HideName != null) GameStartManagerStartPatch.HideName.enabled = true; + if (__instance.GameRoomNameCode) __instance.GameRoomNameCode.color = new(255, 255, 255, 0); + if (GameStartManagerStartPatch.HideName) GameStartManagerStartPatch.HideName.enabled = true; } else { - if (__instance.GameRoomNameCode != null) __instance.GameRoomNameCode.color = new(255, 255, 255, 255); - if (GameStartManagerStartPatch.HideName != null) GameStartManagerStartPatch.HideName.enabled = false; + if (__instance.GameRoomNameCode) __instance.GameRoomNameCode.color = new(255, 255, 255, 255); + if (GameStartManagerStartPatch.HideName) GameStartManagerStartPatch.HideName.enabled = false; } } - if (AmongUsClient.Instance == null || GameData.Instance == null || !AmongUsClient.Instance.AmHost || !GameData.Instance) return true; + if (!AmongUsClient.Instance || !GameData.Instance || !AmongUsClient.Instance.AmHost) return true; CheckAutoStart(__instance); } @@ -180,7 +180,7 @@ public static class GameStartManagerPatch float timer = Timer; - if (timer > 60 && GameSettingMenu.Instance != null) return; + if (timer > 60 && GameSettingMenu.Instance) return; Main.UpdateTime++; if (Main.UpdateTime < 50) return; @@ -333,7 +333,7 @@ public static class GameStartManagerPatch { try { - if (AmongUsClient.Instance == null || AmongUsClient.Instance.IsGameStarted || GameStates.IsInGame || __instance == null || __instance.startState == GameStartManager.StartingStates.Starting) return; + if (!AmongUsClient.Instance || AmongUsClient.Instance.IsGameStarted || GameStates.IsInGame || !__instance || __instance.startState == GameStartManager.StartingStates.Starting) return; var canStartGame = true; var mismatchedClientName = string.Empty; @@ -350,10 +350,10 @@ public static class GameStartManagerPatch for (var index = 0; index < allClients.Length; index++) { ClientData client = allClients[index]; - if (client.Character == null) continue; + if (!client.Character) continue; var dummyComponent = client.Character.GetComponent(); - if (dummyComponent != null && dummyComponent.enabled) continue; + if (dummyComponent && dummyComponent.enabled) continue; if (!MatchVersions(client.Character.PlayerId, true)) { @@ -443,7 +443,7 @@ public static class GameStartManagerPatch { float timer = Timer; - if (LobbyTimerBg == null) LobbyTimerBg = HudManager.Instance.LobbyTimerExtensionUI.timerText.transform.parent.transform.Find("LabelBackground").GetComponent(); + if (!LobbyTimerBg) LobbyTimerBg = HudManager.Instance.LobbyTimerExtensionUI.timerText.transform.parent.transform.Find("LabelBackground").GetComponent(); LobbyTimerBg.sprite = Utils.LoadSprite("EHR.Resources.Images.LobbyTimerBG.png", 100f); LobbyTimerBg.color = GetTimerColor(timer); diff --git a/Patches/LightSourcePatch.cs b/Patches/LightSourcePatch.cs deleted file mode 100644 index 73c9c4207..000000000 --- a/Patches/LightSourcePatch.cs +++ /dev/null @@ -1,61 +0,0 @@ -using HarmonyLib; -using UnityEngine; - -namespace EHR.Patches; - -[HarmonyPatch(typeof(LightSource), nameof(LightSource.Update))] -internal static class LightSourceUpdatePatch -{ - private static readonly int PlayerRadius = Shader.PropertyToID("_PlayerRadius"); - private static readonly int LightRadius = Shader.PropertyToID("_LightRadius"); - private static readonly int LightOffset = Shader.PropertyToID("_LightOffset"); - private static readonly int FlashlightSize = Shader.PropertyToID("_FlashlightSize"); - private static readonly int FlashlightAngle = Shader.PropertyToID("_FlashlightAngle"); - - public static bool Prefix(LightSource __instance) - { - if (SubmergedCompatibility.IsSubmerged()) return true; - Vector3 position = __instance.transform.position; - position.z -= 7f; - __instance.UpdateFlashlightAngle(); - __instance.LightCutawayMaterial.SetFloat(PlayerRadius, __instance.PlayerRadius); - __instance.LightCutawayMaterial.SetFloat(LightRadius, __instance.ViewDistance); - __instance.LightCutawayMaterial.SetVector(LightOffset, __instance.LightOffset); - __instance.LightCutawayMaterial.SetFloat(FlashlightSize, __instance.FlashlightSize); - __instance.LightCutawayMaterial.SetFloat(FlashlightAngle, PlayerControl.LocalPlayer.FlashlightAngle); - __instance.lightChild.transform.position = position; - __instance.renderer.Render(position); - return false; - } -} - -[HarmonyPatch(typeof(LightSourceGpuRenderer), nameof(LightSourceGpuRenderer.DrawOcclusion))] -internal static class LightSourceGpuRendererPatch -{ - private static readonly int DepthCompressionValue = Shader.PropertyToID("_DepthCompressionValue"); - private static readonly int ShmapTexture = Shader.PropertyToID("_ShmapTexture"); - private static readonly int Radius = Shader.PropertyToID("_Radius"); - private static readonly int Column = Shader.PropertyToID("_Column"); - private static readonly int LightPosition = Shader.PropertyToID("_LightPosition"); - private static readonly int TexelSize = Shader.PropertyToID("_TexelSize"); - - public static bool Prefix(LightSourceGpuRenderer __instance, [HarmonyArgument(0)] float effectiveRadius) - { - if (SubmergedCompatibility.IsSubmerged()) return true; - if (!__instance.shadowTexture || !__instance.shadowCasterMaterial) return false; - float width = __instance.shadowTexture.width; - __instance.shadowCasterMaterial.SetFloat(DepthCompressionValue, effectiveRadius); - __instance.cb.Clear(); - __instance.cb.SetRenderTarget(__instance.shadowTexture); - __instance.cb.ClearRenderTarget(true, true, new Color(1f, 1f, 1f, 1f)); - __instance.cb.SetGlobalTexture(ShmapTexture, __instance.shadowTexture); - __instance.cb.SetGlobalFloat(Radius, __instance.lightSource.ViewDistance); - __instance.cb.SetGlobalFloat(Column, 0.0f); - __instance.cb.SetGlobalVector(LightPosition, __instance.lightSource.transform.position); - __instance.cb.SetGlobalVector(TexelSize, new Vector4(1f / width, 1f / width, width, width)); - __instance.cb.SetGlobalFloat(DepthCompressionValue, effectiveRadius); - __instance.cb.DrawMesh(__instance.occluderMesh, Matrix4x4.identity, __instance.shadowCasterMaterial); - Graphics.ExecuteCommandBuffer(__instance.cb); - return false; - } -} \ No newline at end of file diff --git a/Patches/LobbyPatch.cs b/Patches/LobbyPatch.cs index b13bab818..04678dc15 100644 --- a/Patches/LobbyPatch.cs +++ b/Patches/LobbyPatch.cs @@ -20,7 +20,7 @@ public static class LobbyFixedUpdatePatch { GameObject leftBox = GameObject.Find("Leftbox"); - if (leftBox != null) + if (leftBox) { Paint = Object.Instantiate(leftBox, leftBox.transform.parent.transform); Paint.name = "Lobby Paint"; @@ -33,10 +33,10 @@ public static class LobbyFixedUpdatePatch if (!LeftEngineSR || !RightEngineSR) { var leftEngine = GameObject.Find("LeftEngine"); - if (leftEngine != null) LeftEngineSR = leftEngine.GetComponent(); + if (leftEngine) LeftEngineSR = leftEngine.GetComponent(); var rightEngine = GameObject.Find("RightEngine"); - if (rightEngine != null) RightEngineSR = rightEngine.GetComponent(); + if (rightEngine) RightEngineSR = rightEngine.GetComponent(); } else { @@ -62,7 +62,7 @@ public static class HostInfoPanelSetUpPatch { try { - if (HostText == null) HostText = __instance.content.transform.FindChild("Name").GetComponent(); + if (!HostText) HostText = __instance.content.transform.FindChild("Name").GetComponent(); string name = AmongUsClient.Instance.GetHost().PlayerName.Split('\n')[^1]; if (name == string.Empty) return; diff --git a/Patches/MeetingHudPatch.cs b/Patches/MeetingHudPatch.cs index 36985f1d2..559804ea9 100644 --- a/Patches/MeetingHudPatch.cs +++ b/Patches/MeetingHudPatch.cs @@ -38,10 +38,10 @@ internal static class CheckForEndVotingPatch foreach (PlayerVoteArea pva in __instance.playerStates) { - if (pva == null) continue; + if (!pva) continue; PlayerControl pc = Utils.GetPlayerById(pva.TargetPlayerId); - if (pc == null) continue; + if (!pc) continue; // Dictators who are not dead have already voted. // Take the initiative to rebel @@ -93,20 +93,25 @@ internal static class CheckForEndVotingPatch { PlayerControl voteTarget = Utils.GetPlayerById(pva.VotedFor); - if (voteTarget == null || !voteTarget.IsAlive() || voteTarget.Data == null || voteTarget.Data.Disconnected) + if (!voteTarget || !voteTarget.IsAlive() || !voteTarget.Data || voteTarget.Data.Disconnected) { pva.UnsetVote(); __instance.RpcClearVote(pc.OwnerId); __instance.UpdateButtons(); pva.VotedFor = byte.MaxValue; } - else if (voteTarget != null && !pc.GetCustomRole().CancelsVote() && !pc.UsesMeetingShapeshift()) + else if (voteTarget && !pc.GetCustomRole().CancelsVote() && !pc.UsesMeetingShapeshift()) Main.PlayerStates[pc.PlayerId].Role.OnVote(pc, voteTarget); else if (pc.Is(CustomRoles.Godfather)) Godfather.GodfatherTarget = byte.MaxValue; } } - if (!shouldSkip && !__instance.playerStates.All(ps => ps == null || Silencer.ForSilencer.Contains(ps.TargetPlayerId) || !Main.PlayerStates.TryGetValue(ps.TargetPlayerId, out PlayerState st) || st.IsDead || ps.AmDead || ps.DidVote || Utils.GetPlayerById(ps.TargetPlayerId) == null || Utils.GetPlayerById(ps.TargetPlayerId).Data == null || Utils.GetPlayerById(ps.TargetPlayerId).Data.Disconnected)) return false; + if (!shouldSkip && !__instance.playerStates.All(ps => + { + if (!ps || Silencer.ForSilencer.Contains(ps.TargetPlayerId) || !Main.PlayerStates.TryGetValue(ps.TargetPlayerId, out PlayerState st) || st.IsDead || ps.AmDead || ps.DidVote) return true; + PlayerControl targetPlayer = Utils.GetPlayerById(ps.TargetPlayerId); + return !targetPlayer || !targetPlayer.Data || targetPlayer.Data.Disconnected; + })) return false; NetworkedPlayerInfo exiledPlayer = PlayerControl.LocalPlayer.Data; var tie = false; @@ -114,11 +119,11 @@ internal static class CheckForEndVotingPatch foreach (PlayerVoteArea ps in __instance.playerStates) { - if (ps == null) continue; + if (!ps) continue; voteLog.Info($"{ps.TargetPlayerId,-2}{$"({Utils.GetVoteName(ps.TargetPlayerId)})".PadRightV2(40)}:{ps.VotedFor,-3}({Utils.GetVoteName(ps.VotedFor)})"); PlayerControl voter = Utils.GetPlayerById(ps.TargetPlayerId); - if (voter == null || voter.Data == null || voter.Data.Disconnected) continue; + if (!voter || !voter.Data || voter.Data.Disconnected) continue; if (Options.VoteMode.GetBool()) { @@ -229,6 +234,7 @@ internal static class CheckForEndVotingPatch Commited.OnVotingResultsShown(statesList); Summoner.OnMeetingEnd(); + QuizMaster.OnMeetingEnd(); states = [.. statesList]; @@ -532,7 +538,7 @@ internal static class CheckForEndVotingPatch foreach ((byte id, Vector2 pos) in Lazy.BeforeMeetingPositions) { PlayerControl pc = id.GetPlayer(); - if (pc == null || !pc.IsAlive()) continue; + if (!pc || !pc.IsAlive()) continue; pc.TP(pos); } @@ -584,10 +590,10 @@ internal static class CheckForEndVotingPatch private static void RevengeOnExile(byte playerId /*, PlayerState.DeathReason deathReason*/) { PlayerControl player = Utils.GetPlayerById(playerId); - if (player == null) return; + if (!player) return; PlayerControl target = PickRevengeTarget(player /*, deathReason*/); - if (target == null) return; + if (!target) return; TryAddAfterMeetingDeathPlayers(PlayerState.DeathReason.Revenge, target.PlayerId); target.SetRealKiller(player); @@ -617,7 +623,7 @@ internal static class ExtendedMeetingHud foreach (PlayerVoteArea ps in __instance.playerStates) { - if (ps == null) continue; + if (!ps) continue; if (ps.VotedFor is not 252 and not byte.MaxValue and not 254) { @@ -625,7 +631,7 @@ internal static class ExtendedMeetingHud PlayerControl target = Utils.GetPlayerById(ps.VotedFor); - if (target != null) + if (target) { if (target.Is(CustomRoles.Zombie) || (target.Is(CustomRoles.Shifter) && !Shifter.CanBeVoted.GetBool())) voteNum = 0; @@ -1164,6 +1170,8 @@ internal static class MeetingHudStartPatch Ventriloquist.StartMeetingPatch.Postfix(__instance); ShowHostMeetingPatch.Setup_Postfix(__instance); Crowded.MeetingHudStartPatch.Postfix(__instance); + + TextBoxPatch.OnMeetingStart(); } } @@ -1247,7 +1255,7 @@ internal static class MeetingHudUpdatePatch case CustomRoles.NiceGuesser or CustomRoles.EvilGuesser or CustomRoles.Judge or CustomRoles.Swapper or CustomRoles.Councillor or CustomRoles.Guesser when !PlayerControl.LocalPlayer.IsAlive(): ClearShootButton(__instance, true); break; - case CustomRoles.Nemesis when !PlayerControl.LocalPlayer.IsAlive() && GameObject.Find("ShootButton") == null: + case CustomRoles.Nemesis when !PlayerControl.LocalPlayer.IsAlive() && !GameObject.Find("ShootButton"): Nemesis.CreateJudgeButton(__instance); break; } @@ -1368,13 +1376,13 @@ internal static class MeetingHudCastVotePatch if (t.TargetPlayerId == suspectPlayerId) pvaTarget = t; } - if (pvaSrc == null) + if (!pvaSrc) { Logger.Error("Src PlayerVoteArea not found", "MeetingHudCastVotePatch.Prefix"); return true; } - if (pvaTarget == null) + if (!pvaTarget) { //Logger.Warn("Target PlayerVoteArea not found ⇒ Vote treated as a Skip", "MeetingHudCastVotePatch.Prefix"); skip = true; @@ -1383,13 +1391,13 @@ internal static class MeetingHudCastVotePatch PlayerControl pcSrc = Utils.GetPlayerById(srcPlayerId); PlayerControl pcTarget = Utils.GetPlayerById(suspectPlayerId); - if (pcSrc == null) + if (!pcSrc) { Logger.Error("Src PlayerControl is null", "MeetingHudCastVotePatch.Prefix"); return true; } - if (pcTarget == null) + if (!pcTarget) { //Logger.Warn("Target PlayerControl is null ⇒ Vote treated as a Skip", "MeetingHudCastVotePatch.Prefix"); skip = true; diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index b7985ac68..f38b09a29 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -1215,7 +1215,7 @@ internal static class ReportDeadBodyPatch } catch (Exception e) { ThrowException(e); } } - }, 2f, "CNO OnMeeting"); + }, 5f, "CNO OnMeeting"); if (HudManager.InstanceExists) HudManager.Instance.SetRolePanelOpen(false); diff --git a/Patches/TaskAdderPatch.cs b/Patches/TaskAdderPatch.cs index 0d1c65bd8..2ff14702a 100644 --- a/Patches/TaskAdderPatch.cs +++ b/Patches/TaskAdderPatch.cs @@ -68,9 +68,9 @@ internal class TaskAddButtonUpdatePatch { if ((int)__instance.Role.Role >= 1000) { - CustomRoles PlayerCustomRole = PlayerControl.LocalPlayer.GetCustomRole(); - CustomRoles FileCustomRole = (CustomRoles)__instance.Role.Role - 1000; - __instance.Overlay.enabled = PlayerCustomRole == FileCustomRole; + CustomRoles playerCustomRole = PlayerControl.LocalPlayer.GetCustomRole(); + CustomRoles fileCustomRole = (CustomRoles)__instance.Role.Role - 1000; + __instance.Overlay.enabled = playerCustomRole == fileCustomRole; } } catch { } diff --git a/Patches/TextBoxPatch.cs b/Patches/TextBoxPatch.cs index 96c36d72f..3c667d288 100644 --- a/Patches/TextBoxPatch.cs +++ b/Patches/TextBoxPatch.cs @@ -95,7 +95,7 @@ public static class TextBoxPatch } } - if (flag) __instance.OnEnter.Invoke(); + if (flag && !Input.GetKey(KeyCode.LeftShift)) __instance.OnEnter.Invoke(); __instance.SetPipePosition(); return false; } @@ -282,6 +282,7 @@ public static class TextBoxPatch bool IsInvalidArg() => arg != argName && argName switch { + "{uuid}" => arg.Length > 16, "{id}" or "{id1}" or "{id2}" => !byte.TryParse(arg, out byte id) || Main.EnumeratePlayerControls().All(x => x.PlayerId != id), "{ids}" => arg.Split(',').Any(x => !byte.TryParse(x, out _)), "{number}" or "{level}" or "{duration}" or "{number1}" or "{number2}" => !int.TryParse(arg, out int num) || num < 0, @@ -342,10 +343,10 @@ public static class TextBoxPatch void Destroy() { - if (PlaceHolderText != null) PlaceHolderText.enabled = false; - if (CommandInfoText != null) CommandInfoText.enabled = false; + if (PlaceHolderText) PlaceHolderText.enabled = false; + if (CommandInfoText) CommandInfoText.enabled = false; - if (AdditionalInfoText != null) + if (AdditionalInfoText) { bool showLobbyCode = HudManager.Instance?.Chat?.IsOpenOrOpening == true && GameStates.IsLobby && Options.GetSuffixMode() == SuffixModes.Streaming && !Options.HideGameSettings.GetBool() && !DataManager.Settings.Gameplay.StreamerMode; AdditionalInfoText.enabled = showLobbyCode; @@ -356,12 +357,12 @@ public static class TextBoxPatch public static void OnTabPress(ChatController __instance) { - if (PlaceHolderText == null || PlaceHolderText.text == "") return; + if (!PlaceHolderText || PlaceHolderText.text == "") return; __instance.freeChatField.textArea.SetText(PlaceHolderText.text); __instance.freeChatField.textArea.compoText = ""; - if (AdditionalInfoText != null && AdditionalInfoText.text != "") + if (AdditionalInfoText && AdditionalInfoText.text != "") OptionShower.CurrentPage = 0; } @@ -377,6 +378,13 @@ public static class TextBoxPatch catch { } } + public static void OnMeetingStart() + { + PlaceHolderText?.transform.SetAsLastSibling(); + CommandInfoText?.transform.SetAsLastSibling(); + AdditionalInfoText?.transform.SetAsLastSibling(); + } + [HarmonyPatch(typeof(TextBoxTMP), nameof(TextBoxTMP.Update))] [HarmonyPrefix] public static bool UpdatePatch(TextBoxTMP __instance) diff --git a/Resources/Config/EACList.txt b/Resources/Config/EACList.txt index e4af49f44..f1d6b816a 100644 --- a/Resources/Config/EACList.txt +++ b/Resources/Config/EACList.txt @@ -129,6 +129,9 @@ primesnow#4272 | 65b98a6de | HiverXM | Toxic | The n word todayside#9634 | 4e44cffe6 | | Racist | Joined a lobby with racial slur in name roundframe#4949 | 914830596 | PeaceMaker | Toxic | The n word setbud#4013 | 99b904495 | cursed | Toxic | The n word +jacksdeep#4118 | d5d97f4a8 | SIGMAMODE | Toxic | Extremely toxic player +dimbottle#0386 | 607326ed0 | Bob | Toxic | Alt of banned user SIGMAMODE +roundhour#1689 | 4be938470 | NateHigger | Racist | Racist Hostname ## Other tenthrope#3476 | | Oldishwire | Other | diff --git a/Resources/Lang/en_US.jsonc b/Resources/Lang/en_US.jsonc index a3f8d384a..3ac73552c 100644 --- a/Resources/Lang/en_US.jsonc +++ b/Resources/Lang/en_US.jsonc @@ -1235,7 +1235,7 @@ "PortalMaker.PetToRemovePortals": "Can Pet To Remove Both Portals After Placing Them", "President": "President", "PresidentInfo": "Control The Game", - "PresidentInfoLong": "(Crewmates):\\nAs the President, you have 6 decrees each to be used once in the game. You can only use 1 decree in every meeting. To use a decree, type /cmd decree {number}, replacing {number} with the ID of the corresponding decree. To get a list of decrees and their IDs, type /cmd decree.\\n\\nList of decrees and what they do:\\n- Revealing: Reveals you as the President for everyone, makes you unguessable and cuts your vision in half for the rest of the game.\\n- Finishing: Ends the current meeting instantly without counting the votes.\\n- Declassification: Everyone will see voting colors at the end of the current meeting.\\n- Government Support: Gives all crewmates +1 ability use.\\n- Investigation: Get info about how many impostors and neutral killers are alive.\\n- Government Recruiting: After using, vote for someone to recruit them (your vote will be canceled and you'll be able to vote normally after this) to recruit that player to the role specified in the settings, if they're a crewmate.", + "PresidentInfoLong": "(Crewmates):\\nAs the President, you have 6 decrees each to be used once in the game. You can only use 1 decree in every meeting. To use a decree, type /cmd decree {number}, replacing {number} with the ID of the corresponding decree. \\n\\nList of decrees and what they do:\\n1. Revealing: Reveals you as the President for everyone, makes you unguessable and cuts your vision in half for the rest of the game.\\n2. Finishing: Ends the current meeting instantly without counting the votes.\\n3. Declassification: Everyone will see voting colors at the end of the current meeting.\\n4. Government Support: Gives all crewmates +1 ability use.\\n5. Investigation: Get info about how many impostors and neutral killers are alive.\\n6. Government Recruiting: After using, vote for someone to recruit them (your vote will be canceled and you'll be able to vote normally after this) to recruit that player to the role specified in the settings, if they're a crewmate.", "President.Decree.Declassification": "Declassification Decree", "President.Decree.Finish": "Finishing Decree", "President.Decree.GovernmentRecruiting": "Government Recruiting Decree", @@ -2099,6 +2099,9 @@ "PenguinTimerText": "Drag Timer", "PenguinVictimCanUseAbilities": "Victim Can Use Their Abilities While Being Dragged", "PenguinVictimKill": "As the victim of the Penguin/Goose, you cannot interact with others", + "Perplexer": "Perplexer", + "PerplexerInfo": "Invert a player's movement controls", + "PerplexerInfoLong": "(Impostors):\\nAs the Perplexer, use your shapeshift menu to select a player. That player will get their movement controls inverted for a certain amout of time.", "PhantomEHR": "Phantom", "PhantomEHRInfo": "Go invisible temporarily", "PhantomEHRInfoLong": "(Impostors):\\nAs the Phantom, you can go invisible for a short period. During this time, you can't be seen by Crewmates.", @@ -10339,6 +10342,7 @@ General Settings ============================== */ "NoLimitAddonsNumMax": "Max Add-ons Per Player", + "AddonAssigningRolesIgnoreMaxAddonsLimit": "Add-on Assigning Roles Ignore Max Add-ons Limit", /* ============================== Meeting Settings diff --git a/Roles/Standard/Crewmate/Investigate/Medium.cs b/Roles/Standard/Crewmate/Investigate/Medium.cs index ab8b5ad5c..7e676bb73 100644 --- a/Roles/Standard/Crewmate/Investigate/Medium.cs +++ b/Roles/Standard/Crewmate/Investigate/Medium.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; using static EHR.Translator; namespace EHR.Roles; @@ -58,11 +58,11 @@ public class Medium : RoleBase public static void OnReportDeadBody(NetworkedPlayerInfo target) { ContactPlayer = []; - if (target == null || target.Object == null) return; + if (target == null || !target.Object) return; - foreach (PlayerControl pc in Main.EnumerateAlivePlayerControls().Where(x => PlayerIdList.Contains(x.PlayerId) && x.PlayerId != target.PlayerId).ToArray()) + foreach (PlayerControl pc in Main.EnumerateAlivePlayerControls()) { - if (pc.GetAbilityUseLimit() < 1) continue; + if (!pc.Is(CustomRoles.Medium) || pc.PlayerId == target.PlayerId || pc.GetAbilityUseLimit() < 1) continue; pc.RpcRemoveAbilityUse(); ContactPlayer.TryAdd(target.PlayerId, pc.PlayerId); @@ -72,24 +72,16 @@ public class Medium : RoleBase public static bool MsMsg(PlayerControl pc, string msg) { - if (!AmongUsClient.Instance.AmHost) return false; - - if (!GameStates.IsMeeting || pc == null) return false; - - if (!ContactPlayer.ContainsKey(pc.PlayerId)) return false; - - if (OnlyReceiveMsgFromCrew.GetBool() && !pc.IsCrewmate()) return false; - - if (pc.IsAlive()) return false; + if (!AmongUsClient.Instance.AmHost || !GameStates.IsMeeting || !pc || pc.IsAlive() || !ContactPlayer.TryGetValue(pc.PlayerId, out var contact) || (OnlyReceiveMsgFromCrew.GetBool() && !pc.IsCrewmate())) return false; msg = msg.ToLower().Trim(); if (!CheckCommand(ref msg, "通灵|ms|medium", false)) return false; bool ans; - if (msg.Contains('n') || msg.Contains(GetString("No")) || msg.Contains('错') || msg.Contains("不是")) + if (msg.Contains('n') || msg.Contains(GetString("No"), StringComparison.OrdinalIgnoreCase) || msg.Contains('错') || msg.Contains("不是")) ans = false; - else if (msg.Contains('y') || msg.Contains(GetString("Yes")) || msg.Contains('对')) + else if (msg.Contains('y') || msg.Contains(GetString("Yes"), StringComparison.OrdinalIgnoreCase) || msg.Contains('对')) ans = true; else { @@ -97,7 +89,7 @@ public class Medium : RoleBase return true; } - Utils.SendMessage(GetString("Medium" + (ans ? "Yes" : "No")), ContactPlayer[pc.PlayerId], Utils.ColorString(Utils.GetRoleColor(CustomRoles.Medium), GetString("MediumTitle")), importance: MessageImportance.High); + Utils.SendMessage(GetString("Medium" + (ans ? "Yes" : "No")), contact, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Medium), GetString("MediumTitle")), importance: MessageImportance.High); Utils.SendMessage(GetString("MediumDone"), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Medium), GetString("MediumTitle"))); ContactPlayer.Remove(pc.PlayerId); diff --git a/Roles/Standard/Crewmate/Power/President.cs b/Roles/Standard/Crewmate/Power/President.cs index 998e09b3c..5f2df2b98 100644 --- a/Roles/Standard/Crewmate/Power/President.cs +++ b/Roles/Standard/Crewmate/Power/President.cs @@ -147,12 +147,14 @@ public class President : RoleBase if (!Utils.GetPlayerById(president.PresidentId).IsAlive()) return; - if (!int.TryParse(message, out int num) || num > 5) + if (!int.TryParse(message, out int num) || num is > 6 or < 1) { Utils.SendMessage(GetHelpMessage(), pc.PlayerId); return; } + num--; + var decree = (Decree)num; if (!decree.IsEnabled() || president.UsedDecrees.Contains(decree)) diff --git a/Roles/Standard/Impostor/Concealing/Fakeshifter.cs b/Roles/Standard/Impostor/Concealing/Fakeshifter.cs index 6f6b391bf..0fd07507b 100644 --- a/Roles/Standard/Impostor/Concealing/Fakeshifter.cs +++ b/Roles/Standard/Impostor/Concealing/Fakeshifter.cs @@ -39,7 +39,7 @@ public class Fakeshifter : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.ShapeshifterCooldown = AbilityCooldown.GetInt(); - opt.SetVision(false); + AURoleOptions.ShapeshifterDuration = 0.1f; } public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting) diff --git a/Roles/Standard/Impostor/Support/Perplexer.cs b/Roles/Standard/Impostor/Support/Perplexer.cs new file mode 100644 index 000000000..a2a8b6f0e --- /dev/null +++ b/Roles/Standard/Impostor/Support/Perplexer.cs @@ -0,0 +1,73 @@ +using AmongUs.GameOptions; +using EHR.Modules; +using System.Linq; + +namespace EHR.Roles; + +public class Perplexer : RoleBase +{ + public static bool On; + private const int Id = 698000; + + public override bool IsEnable => On; + + private static OptionItem KillCooldown; + private static OptionItem AbilityCooldown; + private static OptionItem AbilityDuration; + private static OptionItem AbilityUseLimit; + private static OptionItem AbilityUseGainWithEachKill; + + private byte MarkedId; + + public override void SetupCustomOption() + { + StartSetup(Id) + .AutoSetupOption(ref KillCooldown, 30f, new FloatValueRule(1, 120, 1), OptionFormat.Seconds) + .AutoSetupOption(ref AbilityCooldown, 30f, new FloatValueRule(1, 120, 1), OptionFormat.Seconds) + .AutoSetupOption(ref AbilityDuration, 10f, new FloatValueRule(1, 120, 1), OptionFormat.Seconds) + .AutoSetupOption(ref AbilityUseLimit, 3f, new FloatValueRule(0, 20, 0.05f), OptionFormat.Times) + .AutoSetupOption(ref AbilityUseGainWithEachKill, 0.5f, new FloatValueRule(0f, 5f, 0.25f), OptionFormat.Times); + } + + public override void Init() + { + On = false; + } + + public override void Add(byte playerId) + { + On = true; + MarkedId = byte.MaxValue; + playerId.SetAbilityUseLimit(AbilityUseLimit.GetFloat()); + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + AURoleOptions.ShapeshifterCooldown = AbilityCooldown.GetInt(); + AURoleOptions.ShapeshifterDuration = 0.1f; + } + + public override void SetKillCooldown(byte id) + { + Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat(); + } + + public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting) + { + if (shapeshifting && MarkedId == byte.MaxValue && target.IsAlive() && shapeshifter.GetAbilityUseLimit() >= 1f) + { + MarkedId = target.PlayerId; + Main.AllPlayerSpeed[MarkedId] *= -1; + target.MarkDirtySettings(); + shapeshifter.RpcRemoveAbilityUse(); + + LateTask.New(() => + { + if (Main.AllPlayerSpeed[MarkedId] < 0f) Main.AllPlayerSpeed[MarkedId] *= -1; + MarkedId = byte.MaxValue; + if (target && target.IsAlive()) target.MarkDirtySettings(); + }, AbilityDuration.GetFloat(), "Perplexer Revert Control Invert"); + } + return false; + } +} \ No newline at end of file diff --git a/Roles/Standard/Neutral/Killing/QuizMaster.cs b/Roles/Standard/Neutral/Killing/QuizMaster.cs index 5303f772d..a02e336d0 100644 --- a/Roles/Standard/Neutral/Killing/QuizMaster.cs +++ b/Roles/Standard/Neutral/Killing/QuizMaster.cs @@ -154,18 +154,21 @@ internal class QuizMaster : RoleBase return CanVent.GetBool(); } - public override void AfterMeetingTasks() + public static void OnMeetingEnd() { Data.NumPlayersDeadThisRound = 0; - - if (Target != byte.MaxValue) - { - CheckForEndVotingPatch.TryAddAfterMeetingDeathPlayers(PlayerState.DeathReason.WrongAnswer, Target); - Target = byte.MaxValue; - } - MessagesToSend = []; - CurrentQuestion = null; + + QuizMasters.ForEach(x => + { + if (x.Target != byte.MaxValue) + { + CheckForEndVotingPatch.TryAddAfterMeetingDeathPlayers(PlayerState.DeathReason.WrongAnswer, x.Target); + x.Target = byte.MaxValue; + } + + x.CurrentQuestion = null; + }); } public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) @@ -304,7 +307,7 @@ internal class QuizMaster : RoleBase if (CurrentQuestion.CorrectAnswerIndex == index) { - if (pc != null) RPC.PlaySoundRPC(pc.PlayerId, Sounds.TaskComplete); + if (pc) RPC.PlaySoundRPC(pc.PlayerId, Sounds.TaskComplete); Utils.SendMessage(Translator.GetString("QuizMaster.AnswerCorrect"), Target, Translator.GetString("QuizMaster.Title"), importance: MessageImportance.High); Utils.SendMessage(string.Format(Translator.GetString("QuizMaster.AnswerCorrect.Self"), CurrentQuestion.Answers[CurrentQuestion.CorrectAnswerIndex]), QuizMasterId, Translator.GetString("QuizMaster.Title"), importance: MessageImportance.High); @@ -315,9 +318,9 @@ internal class QuizMaster : RoleBase Utils.SendMessage(string.Format(Translator.GetString("QuizMaster.AnswerIncorrect"), CurrentQuestion.Answers[CurrentQuestion.CorrectAnswerIndex]), Target, Translator.GetString("QuizMaster.Title"), importance: MessageImportance.High); Utils.SendMessage(string.Format(Translator.GetString("QuizMaster.AnswerIncorrect.Self"), CurrentQuestion.Answers[index], CurrentQuestion.Answers[CurrentQuestion.CorrectAnswerIndex]), QuizMasterId, Translator.GetString("QuizMaster.Title"), importance: MessageImportance.High); - if (pc.Is(CustomRoles.Pestilence)) return; + if (!pc || pc.Is(CustomRoles.Pestilence)) return; Main.PlayerStates[Target].deathReason = PlayerState.DeathReason.WrongAnswer; - pc?.RpcGuesserMurderPlayer(); + pc.RpcGuesserMurderPlayer(); Utils.AfterPlayerDeathTasks(pc, true); Logger.Info($"Player {name} was killed for answering incorrectly", "QuizMaster");