diff --git a/EHR.csproj b/EHR.csproj index 689cd68af..ec548ca4a 100644 --- a/EHR.csproj +++ b/EHR.csproj @@ -27,9 +27,9 @@ - + - + diff --git a/GameMode/HideAndSeekRoles/Hider.cs b/GameMode/HideAndSeekRoles/Hider.cs index efb553836..51b7e43f2 100644 --- a/GameMode/HideAndSeekRoles/Hider.cs +++ b/GameMode/HideAndSeekRoles/Hider.cs @@ -61,9 +61,9 @@ namespace EHR.GameMode.HideAndSeekRoles public static void OnSpecificTaskComplete(PlayerControl pc, PlayerTask task) { int time = 0; - if (ShipStatus.Instance.ShortTasks.Any(x => x.Id == task.Id)) time = TimeDecreaseOnShortTaskComplete.GetInt(); - else if (ShipStatus.Instance.CommonTasks.Any(x => x.Id == task.Id)) time = TimeDecreaseOnCommonTaskComplete.GetInt(); - else if (ShipStatus.Instance.LongTasks.Any(x => x.Id == task.Id)) time = TimeDecreaseOnLongTaskComplete.GetInt(); + if (ShipStatus.Instance.ShortTasks.Any(x => x.TaskType == task.TaskType)) time = TimeDecreaseOnShortTaskComplete.GetInt(); + else if (ShipStatus.Instance.CommonTasks.Any(x => x.TaskType == task.TaskType)) time = TimeDecreaseOnCommonTaskComplete.GetInt(); + else if (ShipStatus.Instance.LongTasks.Any(x => x.TaskType == task.TaskType)) time = TimeDecreaseOnLongTaskComplete.GetInt(); HnSManager.TimeLeft -= time; pc.Notify(string.Format(Translator.GetString("TimeDecreased"), time)); diff --git a/GameMode/HnSManager.cs b/GameMode/HnSManager.cs index f2d5cd96a..a2ffb1c67 100644 --- a/GameMode/HnSManager.cs +++ b/GameMode/HnSManager.cs @@ -91,6 +91,8 @@ namespace EHR .Join(PlayerRoles, x => x.PlayerId, x => x.Key, (pc, role) => (pc, role.Value.Interface)) .Where(x => x.Interface.Team == Team.Impostor) .Do(x => x.pc.MarkDirtySettings()); + + LateTask.New(() => Main.Instance.StartCoroutine(Utils.NotifyEveryoneAsync()), 3f, log: false); }, Seeker.BlindTime.GetFloat() + 8f, "Blind Time Expire"); } @@ -225,8 +227,6 @@ namespace EHR .ToDictionary(x => x.GetType().Name, x => x); PlayerRoles = result.ToDictionary(x => x.Key.PlayerId, x => (roleInterfaces[x.Value.ToString()], x.Value)); - result.IntersectBy(Main.PlayerStates.Keys, x => x.Key.PlayerId).Do(x => x.Key.RpcSetCustomRole(x.Value)); - // ================================================================================================================== if (result.ContainsValue(CustomRoles.Agent)) @@ -248,10 +248,10 @@ namespace EHR public static bool KnowTargetRoleColor(PlayerControl seer, PlayerControl target, ref string color) { - if (seer.PlayerId == target.PlayerId || PlayersSeeRoles.GetBool()) return true; + if (seer.PlayerId == target.PlayerId) return true; - var targetRole = PlayerRoles[target.PlayerId]; - var seerRole = PlayerRoles[seer.PlayerId]; + if (!PlayerRoles.TryGetValue(target.PlayerId, out var targetRole)) return false; + if (!PlayerRoles.TryGetValue(seer.PlayerId, out var seerRole)) return false; if (PlayersSeeRoles.GetBool()) { @@ -279,8 +279,8 @@ namespace EHR public static bool IsRoleTextEnabled(PlayerControl seer, PlayerControl target) { if (seer.PlayerId == target.PlayerId || PlayersSeeRoles.GetBool()) return true; - var targetRole = PlayerRoles[target.PlayerId]; - var seerRole = PlayerRoles[seer.PlayerId]; + if (!PlayerRoles.TryGetValue(target.PlayerId, out var targetRole)) return false; + if (!PlayerRoles.TryGetValue(seer.PlayerId, out var seerRole)) return false; return targetRole.Interface.Team == Team.Impostor && (targetRole.Role != CustomRoles.Agent || seerRole.Interface.Team == Team.Impostor); } @@ -291,9 +291,9 @@ namespace EHR string dangerMeter = GetDangerMeter(seer); - if (PlayerRoles[seer.PlayerId].Interface.Team == Team.Impostor && PlayerRoles.Values.Any(x => x.Role == CustomRoles.Agent)) + if (PlayerRoles.TryGetValue(seer.PlayerId, out var seerRole) && seerRole.Interface.Team == Team.Impostor && PlayerRoles.FindFirst(x => x.Value.Role == CustomRoles.Agent, out var kvp)) { - var agent = PlayerRoles.First(x => x.Value.Role == CustomRoles.Agent).Key; + var agent = kvp.Key; dangerMeter += TargetArrow.GetArrows(seer, agent); } diff --git a/Modules/Camouflague.cs b/Modules/Camouflague.cs index e69d64c83..2c6459a06 100644 --- a/Modules/Camouflague.cs +++ b/Modules/Camouflague.cs @@ -75,7 +75,7 @@ public static class Camouflage } } - public static void CheckCamouflage() + public static bool CheckCamouflage() { if (!AmongUsClient.Instance.AmHost || (!Options.CommsCamouflage.GetBool() && !Camouflager.On)) return; @@ -106,7 +106,10 @@ public static class Camouflage } Utils.NotifyRoles(NoCache: true); + return true; } + + return false; } public static void RpcSetSkin(PlayerControl target, bool ForceRevert = false, bool RevertToDefault = false, bool GameEnd = false) diff --git a/Modules/CustomNetObject.cs b/Modules/CustomNetObject.cs index 964db1e7e..40e500ffe 100644 --- a/Modules/CustomNetObject.cs +++ b/Modules/CustomNetObject.cs @@ -92,7 +92,14 @@ namespace EHR } catch (Exception e) { - if (Options.CurrentGameMode == CustomGameMode.NaturalDisasters) return; + if (Options.CurrentGameMode == CustomGameMode.NaturalDisasters) + { + if (HiddenList.Contains(PlayerControl.LocalPlayer.PlayerId)) return; + Logger.Warn("Error during despawn, hiding instead", "CNO.Despawn"); + Main.AllPlayerControls.Do(Hide); + return; + } + Utils.ThrowException(e); } } @@ -289,7 +296,7 @@ namespace EHR protected void CreateNetObject(string sprite, Vector2 position) { - Logger.Info($" Create Custom Net Object {this.GetType().Name} (ID {Id}) at {position}", "CNO.CreateNetObject"); + Logger.Info($" Create Custom Net Object {this.GetType().Name} (ID {MaxId + 1}) at {position}", "CNO.CreateNetObject"); playerControl = Object.Instantiate(AmongUsClient.Instance.PlayerPrefab, Vector2.zero, Quaternion.identity); playerControl.PlayerId = 255; playerControl.isNew = false; @@ -407,7 +414,14 @@ namespace EHR LateTask.New(() => Utils.SendRPC(CustomRPC.FixModdedClientCNO, playerControl), 0.4f); // Fix for Non-Host Modded } - public static void FixedUpdate() => AllObjects.ToArray().Do(x => x.OnFixedUpdate()); + public static void FixedUpdate() + { + foreach (var cno in AllObjects.ToArray()) + { + cno?.OnFixedUpdate(); + } + } + public static CustomNetObject Get(int id) => AllObjects.FirstOrDefault(x => x.Id == id); public static void Reset() @@ -679,19 +693,14 @@ namespace EHR public float SpawnTimer { get; private set; } private DisasterWarningTimer WarningTimer { get; } - private void RemoveWarningAndSpawn() - { - WarningTimer.Despawn(); - CreateNetObject(Sprite, WarningTimer.Position); - } - public void Update() { if (float.IsNaN(SpawnTimer)) return; SpawnTimer -= Time.fixedDeltaTime; if (SpawnTimer <= 0f) { - RemoveWarningAndSpawn(); + WarningTimer.Despawn(); + CreateNetObject(Sprite, WarningTimer.Position); SpawnTimer = float.NaN; } } diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 178502b70..5ba58ca58 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -796,11 +796,13 @@ internal static class CustomRolesHelper CustomRoles.LastImpostor; public static bool ForceCancelShapeshift(this CustomRoles role) => role is + CustomRoles.Swapster or CustomRoles.Echo or CustomRoles.Hangman or CustomRoles.Generator; public static bool IsNoAnimationShifter(this CustomRoles role) => role is + CustomRoles.Generator or CustomRoles.Echo; public static bool AlwaysUsesUnshift(this CustomRoles role) => role is diff --git a/Modules/ExtendedPlayerControl.cs b/Modules/ExtendedPlayerControl.cs index bfdf4d403..4d326f70e 100644 --- a/Modules/ExtendedPlayerControl.cs +++ b/Modules/ExtendedPlayerControl.cs @@ -237,13 +237,19 @@ static class ExtendedPlayerControl public static void RpcSetNameEx(this PlayerControl player, string name) { + if (player == null) + { + Logger.Warn("The player is null", "RpcSetNameEx"); + return; + } + foreach (PlayerControl seer in Main.AllPlayerControls) { Main.LastNotifyNames[(player.PlayerId, seer.PlayerId)] = name; } - Logger.Info($"Set: {player?.Data?.PlayerName} => {name} for Everyone", "RpcSetNameEx"); - player?.RpcSetName(name); + if (player.Data != null) Logger.Info($"Set: {player.Data.PlayerName} => {name} for Everyone", "RpcSetNameEx"); + player.RpcSetName(name); } public static void RpcSetNamePrivate(this PlayerControl player, string name, PlayerControl seer = null, bool force = false) diff --git a/Modules/GhostRolesManager.cs b/Modules/GhostRolesManager.cs index 87ddfb3c0..f75e4c90d 100644 --- a/Modules/GhostRolesManager.cs +++ b/Modules/GhostRolesManager.cs @@ -66,7 +66,7 @@ namespace EHR.Modules var text = $"{Translator.GetString("GotGhostRoleNotify")}\n{info.Message}"; var notifyText = $"{Translator.GetString("GotGhostRoleNotify")}\n{info.Split}"; Utils.SendMessage(title: text, sendTo: pc.PlayerId, text: "\n"); - pc.Notify(notifyText, 5 * text.Count(x => x == '\n')); + pc.Notify(notifyText, 5 + (5 * text.Count(x => x == '\n'))); return; (string Split, string Message) GetMessage(string baseMessage) diff --git a/Modules/LateTask.cs b/Modules/LateTask.cs index acde072fb..04df6b9d6 100644 --- a/Modules/LateTask.cs +++ b/Modules/LateTask.cs @@ -8,9 +8,9 @@ class LateTask { private static readonly List Tasks = []; private readonly Action action; + private readonly string callerData; private readonly bool log; private readonly string name; - private readonly string callerData; private float timer; private LateTask(Action action, float time, string name, bool log, string callerData) @@ -45,7 +45,7 @@ class LateTask /// The name of the task /// Whether to send log of the creation and completion of the Late Task public static void New(Action action, float time, string name = "No Name Task", bool log = true, [CallerFilePath] string path = "", [CallerMemberName] string member = "", [CallerLineNumber] int line = 0) - => _ = new LateTask(action, time, name, log, $"created at {path}, by member {member}, at line {line}"); + => _ = new LateTask(action, time, name, log, $"created at {path.Split('\\')[^1]}, by member {member}, at line {line}"); public static void Update(float deltaTime) { diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 8593c8efe..6f8cc4b1e 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -614,8 +615,8 @@ public static class Utils case Vector3 v: w.Write(v); break; - case PlayerControl pc: - w.WriteNetObject(pc); + case InnerNetObject ino: + w.WriteNetObject(ino); break; default: try @@ -953,7 +954,7 @@ public static class Utils case CustomRoles.Workaholic when Workaholic.WorkaholicVisibleToEveryone.GetBool(): case CustomRoles.Doctor when !__instance.HasEvilAddon() && Options.DoctorVisibleToEveryone.GetBool(): case CustomRoles.Mayor when Mayor.MayorRevealWhenDoneTasks.GetBool() && __instance.GetTaskState().IsTaskFinished: - case CustomRoles.Marshall when PlayerControl.LocalPlayer.Is(CustomRoleTypes.Crewmate) && __instance.GetTaskState().IsTaskFinished: + case CustomRoles.Marshall when Marshall.CanSeeMarshall(PlayerControl.LocalPlayer) && __instance.GetTaskState().IsTaskFinished: return true; } @@ -1456,8 +1457,9 @@ public static class Utils { try { - if (EndGamePatch.SummaryText[id].Contains("")) continue; - sb.Append("\n\u3000 ").Append(EndGamePatch.SummaryText[id]); + if (!EndGamePatch.SummaryText.TryGetValue(id, out var summaryText)) continue; + if (summaryText.Contains("")) continue; + sb.Append("\n\u3000 ").Append(summaryText); } catch (Exception ex) { @@ -1904,6 +1906,20 @@ public static class Utils public static NetworkedPlayerInfo GetPlayerInfoById(int PlayerId) => GameData.Instance.AllPlayers.ToArray().FirstOrDefault(info => info.PlayerId == PlayerId); + public static IEnumerator NotifyEveryoneAsync() + { + int count = 0; + PlayerControl[] aapc = Main.AllAlivePlayerControls; + foreach (var seer in aapc) + { + foreach (var target in aapc) + { + NotifyRoles(SpecifySeer: seer, SpecifyTarget: target); + if (count++ % 2 == 0) yield return null; + } + } + } + public static void NotifyRoles(bool isForMeeting = false, PlayerControl SpecifySeer = null, PlayerControl SpecifyTarget = null, bool NoCache = false, bool ForceLoop = false, bool CamouflageIsForMeeting = false, bool GuesserIsForMeeting = false, bool MushroomMixup = false) { if (!SetUpRoleTextPatch.IsInIntro && ((SpecifySeer != null && SpecifySeer.IsModClient() && (Options.CurrentGameMode == CustomGameMode.Standard || SpecifySeer.IsHost())) || !AmongUsClient.Instance.AmHost || Main.AllPlayerControls == null || (GameStates.IsMeeting && !isForMeeting))) return; @@ -2275,7 +2291,7 @@ public static class Utils (target.Is(CustomRoles.Workaholic) && Workaholic.WorkaholicVisibleToEveryone.GetBool()) || (target.Is(CustomRoles.Doctor) && !target.HasEvilAddon() && Options.DoctorVisibleToEveryone.GetBool()) || (target.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && target.GetTaskState().IsTaskFinished) || - (seer.Is(CustomRoleTypes.Crewmate) && target.Is(CustomRoles.Marshall) && target.GetTaskState().IsTaskFinished) || + (Marshall.CanSeeMarshall(seer) && target.Is(CustomRoles.Marshall) && target.GetTaskState().IsTaskFinished) || (Main.PlayerStates[target.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) || CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(seer.PlayerId, CTAOption.KnowRoles) || Main.PlayerStates.Values.Any(x => x.Role.KnowRole(seer, target)) || @@ -2346,7 +2362,7 @@ public static class Utils if (seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoles.Snitch) && target.Is(CustomRoles.Madmate) && target.GetTaskState().IsTaskFinished) TargetMark.Append(ColorString(GetRoleColor(CustomRoles.Impostor), "★")); - if (seer.Is(CustomRoleTypes.Crewmate) && target.Is(CustomRoles.Marshall) && target.GetTaskState().IsTaskFinished) + if (Marshall.CanSeeMarshall(seer) && target.Is(CustomRoles.Marshall) && target.GetTaskState().IsTaskFinished) TargetMark.Append(ColorString(GetRoleColor(CustomRoles.Marshall), "★")); TargetMark.Append(Executioner.TargetMark(seer, target)); @@ -2380,7 +2396,7 @@ public static class Utils Main.PlayerStates.Values.Do(x => TargetSuffix.Append(x.Role.GetSuffix(seer, target, meeting: isForMeeting))); - if (MeetingStates.FirstMeeting && Main.ShieldPlayer == target.FriendCode && !string.IsNullOrEmpty(target.FriendCode) && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.SoloKombat or CustomGameMode.FFA) + if (MeetingStates.FirstMeeting && Main.ShieldPlayer == target.FriendCode && !string.IsNullOrEmpty(target.FriendCode) && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.FFA or CustomGameMode.Speedrun) TargetSuffix.Append(GetString("DiedR1Warning")); TargetSuffix.Append(AFKDetector.GetSuffix(seer, target)); @@ -2603,6 +2619,7 @@ public static class Utils CustomRoles.Tiger => Tiger.EnrageCooldown.GetInt() + (includeDuration ? Tiger.EnrageDuration.GetInt() : 0), CustomRoles.Nonplus => Nonplus.BlindCooldown.GetInt() + (includeDuration ? Nonplus.BlindDuration.GetInt() : 0), CustomRoles.Cherokious => Cherokious.KillCooldown.GetInt(), + CustomRoles.Shifter => Shifter.KillCooldown.GetInt(), _ => -1 }; if (CD == -1) return; diff --git a/Modules/Zoom.cs b/Modules/Zoom.cs index cb25eabff..aa0cbfeb1 100644 --- a/Modules/Zoom.cs +++ b/Modules/Zoom.cs @@ -17,7 +17,7 @@ public static class Zoom try { if (Camera.main == null) return; - if (((GameStates.IsShip && !GameStates.IsMeeting && GameStates.IsCanMove && PlayerControl.LocalPlayer.Data.IsDead) || (GameStates.IsLobby && GameStates.IsCanMove)) && !InGameRoleInfoMenu.Showing) + if (((GameStates.IsShip && !GameStates.IsMeeting && GameStates.IsCanMove && PlayerControl.LocalPlayer.Data != null && PlayerControl.LocalPlayer.Data.IsDead) || (GameStates.IsLobby && GameStates.IsCanMove)) && !InGameRoleInfoMenu.Showing) { if (Camera.main.orthographicSize > 3.0f) ResetButtons = true; @@ -60,7 +60,7 @@ public static class Zoom } } - private static void SetZoomSize(bool times = false, bool reset = false) + public static void SetZoomSize(bool times = false, bool reset = false) { if (Camera.main == null) return; @@ -79,7 +79,7 @@ public static class Zoom HudManager.Instance.UICamera.orthographicSize *= size; } - DestroyableSingleton.Instance?.ShadowQuad?.gameObject?.SetActive((reset || Mathf.Approximately(Camera.main.orthographicSize, 3.0f)) && PlayerControl.LocalPlayer.IsAlive()); + DestroyableSingleton.Instance?.ShadowQuad?.gameObject.SetActive((reset || Mathf.Approximately(Camera.main.orthographicSize, 3.0f)) && PlayerControl.LocalPlayer.IsAlive()); if (ResetButtons) { diff --git a/Patches/ClientOptionsPatch.cs b/Patches/ClientOptionsPatch.cs index c9ec04317..7e200e7b1 100644 --- a/Patches/ClientOptionsPatch.cs +++ b/Patches/ClientOptionsPatch.cs @@ -92,7 +92,16 @@ public static class OptionsMenuBehaviourStartPatch static void SwitchVanillaButtonToggle() { - if (PlayerControl.LocalPlayer == null) MainMenuManagerPatch.ShowRightPanelImmediately(); + if (PlayerControl.LocalPlayer != null) + { + Zoom.SetZoomSize(reset: true); + AmongUsClient.Instance.ExitGame(DisconnectReasons.ExitGame); + SceneChanger.ChangeScene("MainMenu"); + HudManager.Instance.ShowPopUp(Translator.GetString("RejoinRequiredDueToVanillaSwitch")); + } + + MainMenuManagerPatch.ShowRightPanelImmediately(); + Harmony.UnpatchAll(); Main.Instance.Unload(); } diff --git a/Patches/DleksPatch.cs b/Patches/DleksPatch.cs index c2c1b1470..95c8b698c 100644 --- a/Patches/DleksPatch.cs +++ b/Patches/DleksPatch.cs @@ -15,14 +15,17 @@ static class AllMapIconsPatch { if (__instance == null) return; - if (Main.NormalOptions.MapId == 3) + LateTask.New(() => { - Main.NormalOptions.MapId = 0; - __instance.UpdateMapImage(MapNames.Skeld); + if (Main.NormalOptions.MapId == 3) + { + Main.NormalOptions.MapId = 0; + __instance.UpdateMapImage(MapNames.Skeld); - if (!Options.RandomMapsMode.GetBool()) - CreateOptionsPickerPatch.SetDleks = true; - } + if (!Options.RandomMapsMode.GetBool()) + CreateOptionsPickerPatch.SetDleks = true; + } + }, AmongUsClient.Instance.AmHost ? 1f : 4f, "Set Skeld Icon For Dleks Map"); MapIconByName dleksIcon = Object.Instantiate(__instance, __instance.gameObject.transform).AllMapIcons[0]; dleksIcon.Name = MapNames.Dleks; diff --git a/Patches/GameOptionsPatch.cs b/Patches/GameOptionsPatch.cs index 0698f795d..7203cc522 100644 --- a/Patches/GameOptionsPatch.cs +++ b/Patches/GameOptionsPatch.cs @@ -5,23 +5,38 @@ using HarmonyLib; namespace EHR.Patches; [HarmonyPatch(typeof(GameOptionsManager), nameof(GameOptionsManager.SwitchGameMode))] -class SwitchGameModePatch +static class SwitchGameModePatch { + private static bool Warned; + + public static bool Prefix(GameModes gameMode) + { + if (!AmongUsClient.Instance.AmHost || gameMode != GameModes.HideNSeek || Warned) return true; + HudManager.Instance.ShowPopUp(Translator.GetString("HnSUnloadWarning")); + return false; + } + public static void Postfix(GameModes gameMode) { - if (gameMode == GameModes.HideNSeek) + if (!AmongUsClient.Instance.AmHost || gameMode != GameModes.HideNSeek) return; + + if (!Warned) { - ErrorText.Instance.HnSFlag = true; - ErrorText.Instance.AddError(ErrorCode.HnsUnload); - Harmony.UnpatchAll(); - Main.Instance.Unload(); + Warned = true; + return; } + + ErrorText.Instance.HnSFlag = true; + ErrorText.Instance.AddError(ErrorCode.HnsUnload); + Zoom.SetZoomSize(reset: true); + Harmony.UnpatchAll(); + Main.Instance.Unload(); } } -[HarmonyPatch(typeof(NormalGameOptionsV08), nameof(NormalGameOptionsV08.SetRecommendations), [typeof(int), typeof(bool), typeof(RulesPresets)])] -[HarmonyPatch(typeof(NormalGameOptionsV08), nameof(NormalGameOptionsV08.SetRecommendations), [typeof(int), typeof(bool)])] -class SetRecommendationsPatch +[HarmonyPatch(typeof(NormalGameOptionsV08), nameof(NormalGameOptionsV08.SetRecommendations), typeof(int), typeof(bool), typeof(RulesPresets))] +[HarmonyPatch(typeof(NormalGameOptionsV08), nameof(NormalGameOptionsV08.SetRecommendations), typeof(int), typeof(bool))] +static class SetRecommendationsPatch { public static void Postfix(NormalGameOptionsV08 __instance, [HarmonyArgument(0)] int numPlayers, diff --git a/Patches/HudPatch.cs b/Patches/HudPatch.cs index b7a4ddcba..9d5d64d06 100644 --- a/Patches/HudPatch.cs +++ b/Patches/HudPatch.cs @@ -232,6 +232,8 @@ static class HudManagerPatch break; } + if (role.PetActivatedAbility()) __instance.AbilityButton?.Hide(); + if (LowerInfoText == null) { LowerInfoText = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform, true); diff --git a/Patches/IntroPatch.cs b/Patches/IntroPatch.cs index c8d824d44..ac0bdeda4 100644 --- a/Patches/IntroPatch.cs +++ b/Patches/IntroPatch.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Linq; using System.Text; using AmongUs.GameOptions; @@ -214,6 +213,7 @@ static class CoBeginPatch { Utils.LongRoleDescriptions.Clear(); + int charsInOneLine = GetUserTrueLang() is SupportedLangs.Russian or SupportedLangs.SChinese or SupportedLangs.TChinese or SupportedLangs.Japanese or SupportedLangs.Korean ? 35 : 50; foreach (var seer in Main.AllPlayerControls) { var longInfo = seer.GetRoleInfo(InfoLong: true).Split("\n\n")[0]; @@ -229,7 +229,7 @@ static class CoBeginPatch tooLong = true; } - for (int i = 50; i < longInfo.Length; i += 50) + for (int i = charsInOneLine; i < longInfo.Length; i += charsInOneLine) { if (tooLong && i > 296) break; int index = longInfo.LastIndexOf(' ', i); @@ -937,7 +937,7 @@ static class IntroCutsceneDestroyPatch LateTask.New(() => aapc.Do(AFKDetector.RecordPosition), 1f, log: false); } - LateTask.New(() => Main.Instance.StartCoroutine(NotifyEveryone()), 3f, log: false); + LateTask.New(() => Main.Instance.StartCoroutine(Utils.NotifyEveryoneAsync()), 3f, log: false); } else { @@ -948,18 +948,5 @@ static class IntroCutsceneDestroyPatch } Logger.Info("OnDestroy", "IntroCutscene"); - - IEnumerator NotifyEveryone() - { - int count = 0; - foreach (var seer in aapc) - { - foreach (var target in aapc) - { - Utils.NotifyRoles(SpecifySeer: seer, SpecifyTarget: target); - if (count++ % 2 == 0) yield return null; - } - } - } } } \ No newline at end of file diff --git a/Patches/MeetingHudPatch.cs b/Patches/MeetingHudPatch.cs index 6cce7e0d3..8aa67091d 100644 --- a/Patches/MeetingHudPatch.cs +++ b/Patches/MeetingHudPatch.cs @@ -800,7 +800,7 @@ static class MeetingHudStartPatch (target.Is(CustomRoles.Workaholic) && Workaholic.WorkaholicVisibleToEveryone.GetBool()) || (target.Is(CustomRoles.Doctor) && !target.HasEvilAddon() && Options.DoctorVisibleToEveryone.GetBool()) || (target.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && target.GetTaskState().IsTaskFinished) || - (target.Is(CustomRoles.Marshall) && seer.Is(CustomRoleTypes.Crewmate) && target.GetTaskState().IsTaskFinished) || + (target.Is(CustomRoles.Marshall) && Marshall.CanSeeMarshall(seer) && target.GetTaskState().IsTaskFinished) || (Main.PlayerStates[target.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) || CustomTeamManager.AreInSameCustomTeam(target.PlayerId, seer.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(target.PlayerId, CTAOption.KnowRoles) || Main.PlayerStates.Values.Any(x => x.Role.KnowRole(seer, target)) || diff --git a/Patches/OnGameStartedPatch.cs b/Patches/OnGameStartedPatch.cs index 722dba910..b02465214 100644 --- a/Patches/OnGameStartedPatch.cs +++ b/Patches/OnGameStartedPatch.cs @@ -599,21 +599,8 @@ internal static class StartGameHostPatch foreach (PlayerControl pc in Main.AllPlayerControls) { - //pc.Data.IsDead = false; if (Main.PlayerStates[pc.PlayerId].MainRole != CustomRoles.NotAssigned) continue; - var role = pc.Data.Role.Role switch - { - RoleTypes.Crewmate => CustomRoles.Crewmate, - RoleTypes.Impostor => CustomRoles.Impostor, - RoleTypes.Scientist => CustomRoles.Scientist, - RoleTypes.Engineer => CustomRoles.Engineer, - RoleTypes.GuardianAngel => CustomRoles.GuardianAngel, - RoleTypes.Shapeshifter => CustomRoles.Shapeshifter, - RoleTypes.Noisemaker => CustomRoles.Noisemaker, - RoleTypes.Phantom => CustomRoles.Phantom, - RoleTypes.Tracker => CustomRoles.Tracker, - _ => CustomRoles.NotAssigned - }; + var role = Enum.TryParse($"{pc.Data.Role.Role}EHR", out CustomRoles parsedRole) ? parsedRole : CustomRoles.NotAssigned; if (role == CustomRoles.NotAssigned) Logger.SendInGame(string.Format(GetString("Error.InvalidRoleAssignment"), pc?.Data?.PlayerName)); Main.PlayerStates[pc.PlayerId].SetMainRole(role); } diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index 4fba9b04d..b793e9e11 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -1178,10 +1178,10 @@ static class FixedUpdatePatch { if (__instance == null || __instance.PlayerId == 255) return; - if (__instance.PlayerId == PlayerControl.LocalPlayer.PlayerId && CustomNetObject.AllObjects.Count > 0) + if (AmongUsClient.Instance.AmHost && __instance.AmOwner) CustomNetObject.FixedUpdate(); - if (__instance.IsAlive()) + if (AmongUsClient.Instance.AmHost && __instance.IsAlive()) VentilationSystemDeterioratePatch.CheckVentInteraction(__instance); byte id = __instance.PlayerId; @@ -1225,7 +1225,7 @@ static class FixedUpdatePatch } } - if (Options.DontUpdateDeadPlayers.GetBool() && !__instance.IsAlive() && !__instance.GetCustomRole().NeedsUpdateAfterDeath() && Options.CurrentGameMode != CustomGameMode.RoomRush) + if (GameStates.InGame && Options.DontUpdateDeadPlayers.GetBool() && !__instance.IsAlive() && !__instance.GetCustomRole().NeedsUpdateAfterDeath() && Options.CurrentGameMode != CustomGameMode.RoomRush) { var buffer = Options.DeepLowLoad.GetBool() ? 30 : 10; DeadBufferTime.TryAdd(id, buffer); @@ -1258,7 +1258,7 @@ static class FixedUpdatePatch } } - public static void DoPostfix(PlayerControl __instance) + private static void DoPostfix(PlayerControl __instance) { var player = __instance; var playerId = player.PlayerId; @@ -1893,7 +1893,7 @@ static class EnterVentPatch { Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "EnterVent"); - if (!pc.CanUseVent() && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.HideAndSeek && !pc.Is(CustomRoles.Nimble) && !pc.Is(CustomRoles.Bloodlust)) + if (AmongUsClient.Instance.AmHost && !pc.CanUseVent() && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.HideAndSeek && !pc.Is(CustomRoles.Nimble) && !pc.Is(CustomRoles.Bloodlust)) { pc.MyPhysics?.RpcBootFromVent(__instance.Id); return; @@ -1906,7 +1906,7 @@ static class EnterVentPatch switch (pc.GetCustomRole()) { case CustomRoles.Mayor when !Options.UsePets.GetBool() && Mayor.MayorUsedButtonCount.TryGetValue(pc.PlayerId, out var count2) && count2 < Mayor.MayorNumOfUseButton.GetInt(): - pc.MyPhysics?.RpcBootFromVent(__instance.Id); + if (AmongUsClient.Instance.AmHost) pc.MyPhysics?.RpcBootFromVent(__instance.Id); pc.ReportDeadBody(null); break; } diff --git a/Patches/ShipStatusPatch.cs b/Patches/ShipStatusPatch.cs index 725c6653d..af67753a0 100644 --- a/Patches/ShipStatusPatch.cs +++ b/Patches/ShipStatusPatch.cs @@ -88,11 +88,7 @@ static class RepairSystemPatch if ((Options.CurrentGameMode != CustomGameMode.Standard || Options.DisableSabotage.GetBool()) && systemType == SystemTypes.Sabotage) return false; - // Note: "SystemTypes.Laboratory" сauses bugs in the Host, it is better not to use - if (player.Is(CustomRoles.Fool) && (systemType is SystemTypes.Comms or SystemTypes.Electrical)) - { - return false; - } + if (player.Is(CustomRoles.Fool) && (systemType is SystemTypes.Comms or SystemTypes.Electrical)) return false; switch (player.GetCustomRole()) { @@ -215,13 +211,14 @@ static class RepairSystemPatch public static void Postfix([HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player) { - Camouflage.CheckCamouflage(); - switch (systemType) { + case SystemTypes.Comms: + if (!Camouflage.CheckCamouflage()) + Utils.NotifyRoles(); + goto case SystemTypes.Electrical; case SystemTypes.Reactor: case SystemTypes.LifeSupp: - case SystemTypes.Comms: case SystemTypes.Laboratory: case SystemTypes.HeliSabotage: case SystemTypes.Electrical: diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index 9eaf8fadb..b7f48158a 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -1119,6 +1119,8 @@ "ConfirmEgoistOnEject": "Confirm Egoists on ejection", "ConfirmLoversOnEject": "Confirm Lovers on ejection", "ShowTeamNextToRoleNameOnEject": "Show what team the ejected player's role is on", + "HnSUnloadWarning": "<#ffff00>WARNING:\\nEHR doesn't support vanilla Hide And Seek and will unload if you enable it.\\nYou can use EHR's Custom Hide And Seek game mode with unique roles instead.", + "RejoinRequiredDueToVanillaSwitch": "You've decided to switch to vanilla mode, so it was required to disconnect you from the current game, or it would've caused issues. Please rejoin the game.", "Addon": "Add-on", "Ban": "Ban", "Kick": "Kick", diff --git a/Roles/Crewmate/Alchemist.cs b/Roles/Crewmate/Alchemist.cs index 65c1d92ce..050a85640 100644 --- a/Roles/Crewmate/Alchemist.cs +++ b/Roles/Crewmate/Alchemist.cs @@ -156,8 +156,6 @@ namespace EHR.Crewmate { if (Main.PlayerStates[player.PlayerId].Role is not Alchemist am) return; - NameNotifyManager.Notifies.Remove(player.PlayerId); - switch (am.PotionID) { case 1: // Shield @@ -252,7 +250,6 @@ namespace EHR.Crewmate if (PotionID != 6) return; PotionID = 10; var pc = instance.myPlayer; - NameNotifyManager.Notifies.Remove(pc.PlayerId); if (!AmongUsClient.Instance.AmHost) return; LateTask.New(() => { @@ -289,7 +286,7 @@ namespace EHR.Crewmate InvisTime = -10; break; case <= 10 when !player.IsModClient(): - player.Notify(string.Format(GetString("SwooperInvisStateCountdown"), remainTime + 1)); + player.Notify(string.Format(GetString("SwooperInvisStateCountdown"), remainTime + 1), overrideAll: true); break; } diff --git a/Roles/Neutral/Postman.cs b/Roles/Neutral/Postman.cs index 66bb24548..79954b7a7 100644 --- a/Roles/Neutral/Postman.cs +++ b/Roles/Neutral/Postman.cs @@ -155,7 +155,7 @@ public class Postman : RoleBase public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false) { if (hud) return GetHudText(seer); - if (seer.IsModClient() || Main.PlayerStates[seer.PlayerId].Role is not Postman { IsEnable: true } pm) return string.Empty; + if (seer.IsModClient() || seer.PlayerId != target.PlayerId || Main.PlayerStates[seer.PlayerId].Role is not Postman { IsEnable: true } pm) return string.Empty; return !pm.IsFinished ? string.Format(GetString("PostmanTarget"), Utils.GetPlayerById(pm.Target).GetRealName()) : "✓"; } diff --git a/Roles/Neutral/Shifter.cs b/Roles/Neutral/Shifter.cs index 1a94c2848..bae371e9f 100644 --- a/Roles/Neutral/Shifter.cs +++ b/Roles/Neutral/Shifter.cs @@ -13,7 +13,7 @@ namespace EHR.Neutral public static List WasShifter = []; - private static OptionItem KillCooldown; + public static OptionItem KillCooldown; private static OptionItem CanVent; private static OptionItem HasImpostorVision; @@ -43,6 +43,13 @@ namespace EHR.Neutral public override void Add(byte playerId) { On = true; + + var pc = playerId.GetPlayer(); + if (pc == null) return; + pc.AddAbilityCD(); + pc.ResetKillCooldown(); + pc.SyncSettings(); + pc.SetKillCooldown(); } public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat(); diff --git a/Roles/Neutral/Vortex.cs b/Roles/Neutral/Vortex.cs index 3127c8cee..a1c0bcba1 100644 --- a/Roles/Neutral/Vortex.cs +++ b/Roles/Neutral/Vortex.cs @@ -52,6 +52,7 @@ namespace EHR.Neutral } LateTask.New(() => target.Suicide(PlayerState.DeathReason.Kill, killer), 0.2f, log: false); + killer.SetKillCooldown(); return false; } }