From 955ee50e2da487f1af0b477878eefa9bb11032b2 Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Mon, 24 Aug 2026 10:51:18 +0200 Subject: [PATCH] changelog --- CHANGELOG.md | 40 +++++++++++++++++++++++-------- Main.cs | 2 +- Modules/CustomRolesHelper.cs | 2 +- Modules/OptionHolder.cs | 2 +- Patches/ChatCommandPatch.cs | 1 - Patches/ChatControlPatch.cs | 12 ---------- Patches/GameOptionsMenuPatch.cs | 10 ++++---- Patches/IntroPatch.cs | 2 ++ Roles/Standard/Coven/CovenBase.cs | 2 +- 9 files changed, 42 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c13f2aa2c..0642d536a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,35 @@ # Thank you so much for finding and using EHR! -- New mini game mode under Custom Hide And Seek: `SHIFT AND SEEK` - - This comes with a new seeker role for the game mode called Disguiser, which has a Shapeshifter basis. It has settings to make it behave like an SNS Seeker and customize it however you want. It functions just like any other seeker role in the game mode. - - For convenience, there's a `SHIFT AND SEEK` setting in Mod Settings when the game mode is set to (Custom) Hide And Seek, which makes sure all seeker roles will be Disguiser and enables the role on 100%. Disabling this setting also sets the Disguiser role's spawn chance to 0%. You CAN still use Disguiser even if `SHIFT AND SEEK` is disabled, you just have to re-enable the role yourself. It will spawn like any other seeker role. - - This mini game mode also appears as an option in /gmpoll, which when voted, sets the game mode to (Custom) Hide And Seek, and enables the `SHIFT AND SEEK` setting mentioned above. When normal HNS gets voted, the system disables the setting. -- Fixed kicks after the voting ends on vanilla regions -- Additional optimizations -- Fixed a bug that lead to kicks with large packets -- Fixed kicks caused by chat clearing -- CHNS: Seekers are announced at the start if players can see each other's roles -- First death recording now skips disconnects +Support for Among Us v18.0 (2026. 08. 18.) + +## Bug Fixes +- **Fixed kill cooldowns being resetted to half of the value after meetings** +- SNS fixes +- Fixed Quiz FFA suffix +- Fixed Solo PVP error spam +- Fixed Imitator being able to imitate Trickster +- Double Agent counts towards Impostors on /gamestate +- Fixed chat input field text color sometimes not resetting to white with dark theme +- Fixed Revenant unnecessary teleporting after meetings +- Multiple Time Master rewinds now can't happen simultaneously +- Fixed Duality being semi-revived after death on task completion + +## Changes +- EHR Judge => Prosecutor +- Roles with a voting ability can now use the vanilla judging mechanic to trigger their ability! (Game Modifiers > `Use Judge Ability in Meetings to Select Targets Instead of Commands/Votes`) +- More compatibility with LevelImposter - by Zypherus & Newholiday + +## Additions +- New role: Transposer (Impostor Concealing) +- New role: Tyrant (Impostor Support) - by Newholiday +- New role: Evader (Crewmate Miscellaneous) +- New add-on: Bluetooth (Impostor-Only Helpful) - by Newholiday +- New add-on: Priority (Coven-Only Helpful) - by Newholiday +- New add-on: Transfer (Global Mixed) +- New setting: `Hide 'EHR-Host' Text` (System Settings) +- AOU EU region support + +Thanks to TommyXL for fixing the build errors after the update! > [!WARNING] > If you're joining a lobby hosted on vanilla regions (NA/EU/AS), please make sure you have a vanilla region selected in the Create Game menu, otherwise authentication will fail. diff --git a/Main.cs b/Main.cs index f2c3de98f..77db40d11 100644 --- a/Main.cs +++ b/Main.cs @@ -43,7 +43,7 @@ public class Main : BasePlugin public const string PluginGuid = "com.gurge44.endlesshostroles"; public const string PluginVersion = "8.0.0"; public const string PluginDisplayVersion = "8.0.0"; - public const int TestBuildNumber = 3; // 0 = Release + public const int TestBuildNumber = 0; // 0 = Release public const string NeutralColor = "#ffab1b"; public const string ImpostorColor = "#ff1919"; diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index e64b436b8..192a17aaf 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -1954,7 +1954,7 @@ internal static class CustomRolesHelper CustomRoles.Rascal when !pc.IsCrewmate() => false, CustomRoles.LazyGuy when pc.GetCustomRole().IsAdditionRole() => false, CustomRoles.Stealer when pc.Is(CustomRoles.Vindicator) => false, - CustomRoles.Priority when Main.PlayerStates[pc.PlayerId].Role is not CovenBase coven || coven.CanNeverGetNecronomicon => false, + CustomRoles.Priority when !Main.PlayerStates.TryGetValue(pc.PlayerId, out PlayerState state) || state.Role is not CovenBase coven || coven.CanNeverGetNecronomicon => false, CustomRoles.Bloodlust when !pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsTaskBasedCrewmate() || pc.GetCustomRole() is CustomRoles.Medic => false, CustomRoles.Mare when pc.GetCustomRole() is CustomRoles.Inhibitor or CustomRoles.Saboteur or CustomRoles.Swift or CustomRoles.Nemesis or CustomRoles.Sniper or CustomRoles.Fireworker or CustomRoles.Swooper or CustomRoles.Vampire => false, CustomRoles.Torch when pc.GetCustomRole() is CustomRoles.Lighter or CustomRoles.Ignitor or CustomRoles.Investigator or CustomRoles.Eclipse or CustomRoles.Decryptor => false, diff --git a/Modules/OptionHolder.cs b/Modules/OptionHolder.cs index 4312ae458..ff18dca83 100644 --- a/Modules/OptionHolder.cs +++ b/Modules/OptionHolder.cs @@ -181,7 +181,7 @@ public static class Options "TempBan" ]; - public static readonly string[] ConfirmEjectionsMode = + private static readonly string[] ConfirmEjectionsMode = [ "ConfirmEjections.None", "ConfirmEjections.Team", diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index 8eca3cfb2..a5d168197 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -1112,7 +1112,6 @@ internal static class ChatCommands if (GMPollGameModes.Contains(CustomGameMode.HideAndSeek)) GMPollGameModes.Add((CustomGameMode)100); string gmNames = GMPollGameModes.Join(' ', x => GetString((int)x == 100 ? "HNS.ShiftAndSeek" : x.ToString()).Replace(' ', '_')); var msg = $"/poll {GetString("GameModePoll.Question").TrimEnd('?')}? {gmNames}"; - Logger.Info(msg, "debug"); PollCommand(player, msg, msg.Split(' ')); } diff --git a/Patches/ChatControlPatch.cs b/Patches/ChatControlPatch.cs index bec370253..cdeae9c52 100644 --- a/Patches/ChatControlPatch.cs +++ b/Patches/ChatControlPatch.cs @@ -24,18 +24,6 @@ static class ChatControllerAwakePatch { if (AmongUsClient.Instance.AmHost && DataManager.Settings.Multiplayer.ChatMode == QuickChatModes.QuickChatOnly) DataManager.Settings.Multiplayer.ChatMode = QuickChatModes.FreeChatOrQuickChat; - - if (GameSettingMenu.Instance) - { - FreeChatInputField field = GameSettingMenuPatch.InputField; - - if (field && field.gameObject.activeSelf) - { - field.background.color = DarkBackgroundColor; - field.textArea.compoText.Color(Color.white); - field.textArea.outputText.color = Color.white; - } - } var chatBubble = __instance.chatBubblePool.Prefab.CastFast(); chatBubble.TextArea.overrideColorTags = false; diff --git a/Patches/GameOptionsMenuPatch.cs b/Patches/GameOptionsMenuPatch.cs index 155f9e342..bc34893b5 100644 --- a/Patches/GameOptionsMenuPatch.cs +++ b/Patches/GameOptionsMenuPatch.cs @@ -1159,6 +1159,7 @@ public static class GameSettingMenuPatch } private static readonly System.Collections.Generic.Dictionary ExtraObjectsCache = []; + private static Coroutine KeepSearchBarDarkThemedCoroutine; // Thanks: Drakos for the preset button and search bar code (https://github.com/0xDrMoe/TownofHost-Enhanced/pull/1115) private static void SetupExtendedUI(GameSettingMenu __instance) @@ -1370,9 +1371,9 @@ public static class GameSettingMenuPatch field.transform.SetParent(parentLeftPanel.parent, false); field.gameObject.SetActive(true); } - else + else if (Main.DarkTheme.Value) { - Main.Instance.StartCoroutine(KeepSearchBarDarkThemed()); + KeepSearchBarDarkThemedCoroutine ??= Main.Instance.StartCoroutine(KeepSearchBarDarkThemed()); } field.transform.localScale = new(0.3f, 0.59f, 1); field.transform.localPosition = new(-0.47f, 2.15f, -5f); @@ -1450,9 +1451,9 @@ public static class GameSettingMenuPatch IEnumerator KeepSearchBarDarkThemed() { - while (InputField) + while (true) { - if (Main.DarkTheme.Value && GameSettingMenu.Instance && InputField.gameObject.activeSelf) + if (InputField && GameSettingMenu.Instance && InputField.gameObject.activeSelf) { InputField.background.color = ChatControllerAwakePatch.DarkBackgroundColor; InputField.textArea.compoText.Color(Color.white); @@ -1461,6 +1462,7 @@ public static class GameSettingMenuPatch yield return null; } + // ReSharper disable once IteratorNeverReturns } } diff --git a/Patches/IntroPatch.cs b/Patches/IntroPatch.cs index 9ec19e4ce..5c4fd9dcd 100644 --- a/Patches/IntroPatch.cs +++ b/Patches/IntroPatch.cs @@ -1466,5 +1466,7 @@ internal static class IntroCutsceneDestroyPatch if (Main.CurrentMap == MapNames.Airship && FastVector2.DistanceWithinRange(PlayerControl.LocalPlayer.Pos(), new Vector2(-25f, 40f), 8f) && PlayerControl.LocalPlayer.Is(CustomRoles.GM)) PlayerControl.LocalPlayer.NetTransform.SnapTo(new(15.5f, 0.0f), (ushort)(PlayerControl.LocalPlayer.NetTransform.lastSequenceId + 8)); }, 4f, "Airship Spawn FailSafe"); + + MatchInfoHudButton.defaultDistanceFromEdge = MatchInfoHudButton.adjustedDistanceFromEdge; } } \ No newline at end of file diff --git a/Roles/Standard/Coven/CovenBase.cs b/Roles/Standard/Coven/CovenBase.cs index bceb89d6c..e800caa23 100644 --- a/Roles/Standard/Coven/CovenBase.cs +++ b/Roles/Standard/Coven/CovenBase.cs @@ -24,7 +24,7 @@ public abstract class CovenBase : RoleBase private static void GiveNecronomicon() { Dictionary psDict = Main.PlayerStates - .Where(x => x.Value.Role is CovenBase { HasNecronomicon: false } coven && !coven.CanNeverGetNecronomicon) + .Where(x => x.Value.Role is CovenBase { HasNecronomicon: false, CanNeverGetNecronomicon: false }) .ToDictionary(x => x.Key, x => x.Value); if (psDict.Count == 0) return;