diff --git a/Gamemodes/CustomHnS.cs b/Gamemodes/CustomHnS.cs index bb6d5b118..c79d12d4b 100644 --- a/Gamemodes/CustomHnS.cs +++ b/Gamemodes/CustomHnS.cs @@ -98,9 +98,6 @@ internal static class CustomHnS Main.AllPlayerKillCooldown.SetAllValues(Seeker.KillCooldown.GetFloat()); IsBlindTime = true; Utils.MarkEveryoneDirtySettingsV4(); - - float time = Seeker.BlindTime.GetFloat() + 14f; - if (PlayersSeeRoles.GetBool()) Main.EnumerateAlivePlayerControls().NotifyPlayers(string.Format(Translator.GetString("HNSSeekers"), string.Join(", ", PlayerRoles.Where(x => x.Value.Interface.Team == Team.Impostor).Select(x => x.Key.ColoredPlayerName()))), time + 3f, setName: false); LateTask.New(() => { @@ -113,7 +110,7 @@ internal static class CustomHnS .Do(x => x.pc.SetKillCooldown()); LateTask.New(() => Main.Instance.StartCoroutine(Utils.NotifyEveryoneAsync(noCache: false)), 3f, log: false); - }, time, "Blind Time Expire"); + }, Seeker.BlindTime.GetFloat() + 14f, "Blind Time Expire"); } public static List GetAllHnsRoles(Type[] types) @@ -378,29 +375,66 @@ internal static class CustomHnS } } + private static readonly StringBuilder Suffix = new(); + public static string GetSuffixText(PlayerControl seer, PlayerControl target, bool hud = false) { - if (Main.HasJustStarted || seer.PlayerId != target.PlayerId || (seer.IsModdedClient() && !hud) || TimeLeft < 0) return string.Empty; + if (!Main.IntroDestroyed || seer.PlayerId != target.PlayerId || (seer.IsModdedClient() && !hud) || TimeLeft < 0) return string.Empty; - string dangerMeter = GetDangerMeter(seer); + Suffix.Clear(); - if (PlayerRoles.TryGetValue(seer.PlayerId, out (IHideAndSeekRole Interface, CustomRoles Role) seerRole) && seerRole.Interface.Team == Team.Impostor && PlayerRoles.FindFirst(x => x.Value.Role == CustomRoles.Agent, out KeyValuePair kvp)) + if (PlayerRoles.TryGetValue(seer.PlayerId, out (IHideAndSeekRole Interface, CustomRoles Role) seerRole)) { - byte agent = kvp.Key; - dangerMeter += TargetArrow.GetArrows(seer, agent); + if (seerRole.Interface.Team == Team.Impostor) + { + if (PlayerRoles.FindFirst(x => x.Value.Role == CustomRoles.Agent, out KeyValuePair kvp)) + { + byte agent = kvp.Key; + Suffix.Append(TargetArrow.GetArrows(seer, agent)); + } + } + else + { + Suffix.Append(GetDangerMeter(seer)); + + if (PlayersSeeRoles.GetBool() && !CustomRoles.Agent.IsEnable() && IntroCutsceneDestroyPatch.IntroDestroyTS + 15 > Utils.TimeStamp) + { + Suffix.AppendLine(); + Suffix.AppendFormat(Translator.GetString("HNSSeekers"), string.Join(", ", PlayerRoles.Where(x => x.Value.Interface.Team == Team.Impostor).Select(x => x.Key.ColoredPlayerName()))); + } + } } - if (TimeLeft == 60) + Suffix.AppendLine(); + + if (TimeLeft <= 60) { - SoundManager.Instance.PlaySound(HudManager.Instance.LobbyTimerExtensionUI.lobbyTimerPopUpSound, false); - Utils.FlashColor(new(1f, 1f, 0f, 0.4f), 1.4f); + Suffix.Append("'); + Suffix.Append(Translator.GetString("TimeLeft")); + Suffix.Append(": "); + Suffix.Append(TimeLeft); + Suffix.Append('s'); + } + else + { + int minutes = TimeLeft / 60; + int seconds = TimeLeft % 60; + + if (hud) + { + Suffix.Append($"{minutes:00}"); + Suffix.Append(':'); + Suffix.Append($"{seconds:00}"); + } + else + { + Suffix.AppendFormat(Translator.GetString("MinutesLeft"), $"{minutes}-{minutes + 1}"); + } } - if (TimeLeft <= 60) return $"{dangerMeter}\n{Translator.GetString("TimeLeft")}: {TimeLeft}s"; - - int minutes = TimeLeft / 60; - int seconds = TimeLeft % 60; - return dangerMeter + "\n" + (hud ? $"{minutes:00}:{seconds:00}" : $"{string.Format(Translator.GetString("MinutesLeft"), $"{minutes}-{minutes + 1}")}"); + return Suffix.ToString(); } private static string GetDangerMeter(PlayerControl seer) diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 049d49071..5facbcdd0 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -101,7 +101,7 @@ internal static class CustomRolesHelper CustomRoles.Telecommunication => new AntiAdminer(), // Else, the role class is the role name - if the class doesn't exist, it defaults to VanillaRole - _ => Main.AllRoleClasses.FirstOrDefault(x => x.GetType().Name.Equals(role.ToString(), StringComparison.OrdinalIgnoreCase)) ?? new VanillaRole() + _ => Main.AllRoleClasses.Find(x => x.GetType().Name.Equals(role.ToString(), StringComparison.OrdinalIgnoreCase)) ?? new VanillaRole() }; return Activator.CreateInstance(roleClass.GetType()) as RoleBase; diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 61c7be349..e3a5e319c 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -2525,9 +2525,10 @@ public static class Utils if (GameStates.IsOnlineGame || GameStates.IsLocalGame) name = $"{GetString("HostText")}{GetString("Icon")}{name}"; - var modeText = $"{GetString($"Mode{Options.CurrentGameMode}")}"; + CustomGameMode gameMode = Options.CurrentGameMode; + var modeText = $"{GetString(gameMode == CustomGameMode.HideAndSeek && CustomHnS.SNS ? "HNS.ShiftAndSeek" : $"Mode{gameMode}")}"; - name = Options.CurrentGameMode switch + name = gameMode switch { CustomGameMode.SoloPVP => $"{modeText}\r\n{name}", CustomGameMode.FFA => $"{modeText}\r\n{name}", diff --git a/Patches/OutroPatch.cs b/Patches/OutroPatch.cs index 8a6f71d61..0a157643b 100644 --- a/Patches/OutroPatch.cs +++ b/Patches/OutroPatch.cs @@ -475,9 +475,6 @@ internal static class SetEverythingUpPatch EndOfText: LastWinsText = winnerText.text /*.RemoveHtmlTags()*/; - - // Clean up memory for objects that are no longer referenced - GC.Collect(); return; IEnumerator SetupPoolablePlayers() @@ -487,11 +484,6 @@ internal static class SetEverythingUpPatch yield return null; - GC.Collect(); - Resources.UnloadUnusedAssets(); - GC.Collect(); - yield return null; - Vector3 pos = main.ViewportToWorldPoint(new(0f, 1f, main.nearClipPlane)); GameObject roleSummaryObject = Object.Instantiate(__instance.WinText.gameObject); roleSummaryObject.transform.position = new(__instance.Navigation.ExitButton.transform.position.x + 0.1f, pos.y - 0.1f, -15f); @@ -803,6 +795,13 @@ internal static class SetEverythingUpPatch yield return null; } } + + yield return null; + + GC.Collect(); + yield return null; + Resources.UnloadUnusedAssets(); + GC.Collect(); } static string GetAdditionalWinnerRoleName(string role) diff --git a/Roles/Standard/Coven/Shadow.cs b/Roles/Standard/Coven/Shadow.cs index bf5d5b565..2059c424b 100644 --- a/Roles/Standard/Coven/Shadow.cs +++ b/Roles/Standard/Coven/Shadow.cs @@ -99,14 +99,13 @@ public class Shadow : CovenBase OriginalOutfit = Camouflage.PlayerSkins[pc.PlayerId]; Utils.RpcChangeSkin(pc, new NetworkedPlayerInfo.PlayerOutfit().Set("​", 15, "", "", "", "", "")); - Utils.NotifyRoles(SpecifyTarget: pc); SelfTimer = new CountdownTimer(SelfCamoDuration.GetFloat(), () => { SelfTimer = null; if (Camouflage.IsCamouflage || !pc) return; Utils.RpcChangeSkin(pc, OriginalOutfit); - Utils.NotifyRoles(SpecifyTarget: pc); + LateTask.New(() => Utils.NotifyRoles(SpecifyTarget: pc, NoCache: true), 0.2f); pc.RpcResetAbilityCooldown(); }, cancelOnMeeting: false, onCanceled: () => SelfTimer = null); @@ -164,14 +163,13 @@ public class Shadow : CovenBase TargetId = target.PlayerId; OriginalTargetOutfit = Camouflage.PlayerSkins[target.PlayerId]; Utils.RpcChangeSkin(target, new NetworkedPlayerInfo.PlayerOutfit().Set("​", 15, "", "", "", "", "")); - Utils.NotifyRoles(SpecifyTarget: target); OthersCamoTimer = new CountdownTimer(OthersCamoDuration.GetFloat(), () => { OthersCamoTimer = null; if (Camouflage.IsCamouflage || !target) return; Utils.RpcChangeSkin(target, OriginalTargetOutfit); - Utils.NotifyRoles(SpecifyTarget: target); + LateTask.New(() => Utils.NotifyRoles(SpecifyTarget: target, NoCache: true), 0.2f); }, cancelOnMeeting: false, onCanceled: () => OthersCamoTimer = null); } } diff --git a/Roles/Standard/Crewmate/Investigate/Revenant.cs b/Roles/Standard/Crewmate/Investigate/Revenant.cs index c96f8dde2..e3efeacdb 100644 --- a/Roles/Standard/Crewmate/Investigate/Revenant.cs +++ b/Roles/Standard/Crewmate/Investigate/Revenant.cs @@ -37,6 +37,7 @@ internal class Revenant : RoleBase public override void OnReportDeadBody() { + ShouldBeRevived = false; PlayerControl pc = RevenantId.GetPlayer(); if (pc && pc.IsAlive() && !pc.AllTasksCompleted()) @@ -66,4 +67,9 @@ internal class Revenant : RoleBase } }, 2f, "Revenant Revive Delay"); } + + public override void OnRevived(PlayerControl pc) + { + + } } \ No newline at end of file diff --git a/Roles/Standard/Crewmate/Support/Altruist.cs b/Roles/Standard/Crewmate/Support/Altruist.cs index 712f56bc7..e6bdc8237 100644 --- a/Roles/Standard/Crewmate/Support/Altruist.cs +++ b/Roles/Standard/Crewmate/Support/Altruist.cs @@ -85,7 +85,7 @@ public class Altruist : RoleBase RevivedPlayers.Add(ReviveTarget); - if (killer != null && ReviveTargetsKillerGetsAlert.GetBool()) + if (killer && ReviveTargetsKillerGetsAlert.GetBool()) { if (ReviveTargetsKillerGetsArrow.GetBool()) TargetArrow.Add(killer.PlayerId, ReviveTarget); @@ -97,7 +97,7 @@ public class Altruist : RoleBase ReviveTarget = byte.MaxValue; ReviveTargetPos = Vector2.zero; - if (reporter.AmOwner && rtg != null && !rtg.Is(Team.Crewmate)) + if (reporter.AmOwner && rtg && !rtg.Is(Team.Crewmate)) Achievements.Type.IWishIReported.Complete(); }, onTick: () => Utils.NotifyRoles(SpecifySeer: reporter, SpecifyTarget: reporter), onCanceled: () => {