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;
}
}