fixes & optimizations

This commit is contained in:
Gurge44 committed 2026-07-31 15:03:12 +02:00
1 parent 4bed4f6d0e
commit e1c21be60e
11 files changed
+165 -59

No files matched your search

+18 -1
View File
@@ -82,6 +82,23 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Housekeeping/Layout/SolBuilderDuoView/ShowBuildProgressInToolWindow/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Applicability/=Live/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Applicability/=Surround/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Description/@EntryValue">Reformat into LateTask</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Field/=DELAY/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Field/=DELAY/Expression/@EntryValue">constant("0.2f")</s:String>
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Field/=DELAY/Order/@EntryValue">0</s:Int64>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Reformat/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Shortcut/@EntryValue">latetask</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/ShortenQualifiedReferences/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=98B559F14581554F8D9507F43BE0B5C5/Text/@EntryValue">LateTask.New(() =&gt;
{
$SELECTION$
}, $DELAY$);</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=A0247799D36DB94EBB3D0F552C99C784/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=A0247799D36DB94EBB3D0F552C99C784/Applicability/=Live/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=A0247799D36DB94EBB3D0F552C99C784/Applicability/=Surround/@EntryIndexedValue">True</s:Boolean>
@@ -100,7 +117,7 @@
$SELECTION$
}
catch { }</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DED7798D82D02045ABA68FC339C76DFA/Field/=EXCEPTION/Expression/@EntryValue">constant("System.Exception")</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DED7798D82D02045ABA68FC339C76DFA/Field/=EXCEPTION/Expression/@EntryValue">suggestVariableType()</s:String>
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DED7798D82D02045ABA68FC339C76DFA/Field/=EXCEPTION/InitialRange/@EntryValue">-1</s:Int64>
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DED7798D82D02045ABA68FC339C76DFA/Field/=EX_005FNAME/InitialRange/@EntryValue">-1</s:Int64>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DED7798D82D02045ABA68FC339C76DFA/Text/@EntryValue">try
+2 -2
View File
@@ -41,8 +41,8 @@ public class Main : BasePlugin
private const string DebugKeyHash = "c0fd562955ba56af3ae20d7ec9e64c664f0facecef4b3e366e109306adeae29d";
private const string DebugKeySalt = "59687b";
public const string PluginGuid = "com.gurge44.endlesshostroles";
public const string PluginVersion = "7.8.0";
public const string PluginDisplayVersion = "7.8.0";
public const string PluginVersion = "7.9.0";
public const string PluginDisplayVersion = "7.9.0";
public const bool TestBuild = false;
public const string NeutralColor = "#ffab1b";
+1 -1
View File
@@ -117,7 +117,7 @@ public static class AntiBlackout
}
catch (Exception e) { Utils.ThrowException(e); }
}
}, 0.2f, "Set Desync Roles");
}, 0.2f, "Set Desync Roles", log: false);
}
catch (Exception e) { Utils.ThrowException(e); }
}
+33 -25
View File
@@ -166,36 +166,21 @@ public class CustomRpcSender
if (currentState == State.InRootPackedMessage)
{
static int GetPackedIntSize(int value)
{
uint v = (uint)value;
int count = 0;
do
{
v >>= 7;
count++;
}
while (v != 0);
return count;
}
if (3 + GetPackedIntSize(AmongUsClient.Instance.GameId) >= stream.Length)
if (stream.Length <= 11)
dispose = true;
else
EndMessage();
}
if (currentState != State.Ready)
if (!dispose && currentState != State.Ready)
{
if (currentState == State.Finished)
{
Logger.Warn($"Tried to send RPC but \"{name}\" is already Finished", "CustomRpcSender.Warn");
Logger.Warn($"Tried to send Message but \"{name}\" is already Finished", "CustomRpcSender.Warn");
return;
}
var errorMsg = $"Tried to send RPC but State is not Ready (in: \"{name}\", state: {currentState})";
var errorMsg = $"Tried to send Message but State is not Ready (in: \"{name}\", state: {currentState})";
if (isUnsafe)
Logger.Warn(errorMsg, "CustomRpcSender.Warn");
@@ -242,7 +227,7 @@ public class CustomRpcSender
{
if (currentState != State.InRpc)
{
var errorMsg = $"Tried to write RPC, but State is not InRpc (in: \"{name}\")";
var errorMsg = $"Tried to write into RPC, but State is not InRpc (in: \"{name}\")";
if (isUnsafe)
Logger.Warn(errorMsg, "CustomRpcSender.Warn");
@@ -273,7 +258,7 @@ public class CustomRpcSender
if (currentState == State.InRootPackedMessage && targetClientId < 0)
{
var errorMsg = $"Tried to start RPC, but State is InRootPackedMessage and the requested targetClientId is negative. Only GameDataTo messages can be started in this state. (in: \"{name}\")";
var errorMsg = $"Tried to start Message, but State is InRootPackedMessage and the requested targetClientId is negative. Only GameDataTo messages can be started in this state. (in: \"{name}\")";
if (isUnsafe)
Logger.Warn(errorMsg, "CustomRpcSender.Warn");
@@ -323,7 +308,7 @@ public class CustomRpcSender
{
if (currentState != State.Ready)
{
var errorMsg = $"Tried to start Message but State is not Ready (in: \"{name}\")";
var errorMsg = $"Tried to start Packed Message but State is not Ready (in: \"{name}\")";
if (isUnsafe)
Logger.Warn(errorMsg, "CustomRpcSender.Warn");
@@ -351,7 +336,7 @@ public class CustomRpcSender
{
if (currentState is not State.InRootMessage and not State.InRootPackedMessage)
{
var errorMsg = $"Tried to exit Message but State is not InRootMessage or InRootPackedMessage (in: \"{name}\")";
var errorMsg = $"Tried to end Message but State is not InRootMessage or InRootPackedMessage (in: \"{name}\")";
if (isUnsafe)
Logger.Warn(errorMsg, "CustomRpcSender.Warn");
@@ -418,8 +403,9 @@ public class CustomRpcSender
if (messages >= AmongUsClient.Instance.GetMaxMessagePackingLimit())
{
int targetClientId = currentRpcTarget;
EndMessage(startNew: true);
StartMessage(currentRpcTarget);
StartMessage(targetClientId);
}
messages++;
@@ -436,7 +422,7 @@ public class CustomRpcSender
{
if (currentState != State.InRpc)
{
var errorMsg = $"Tried to terminate RPC but State is not InRpc (in: \"{name}\")";
var errorMsg = $"Tried to end RPC but State is not InRpc (in: \"{name}\")";
if (isUnsafe)
Logger.Warn(errorMsg, "CustomRpcSender.Warn");
@@ -966,6 +952,28 @@ public static class CustomRpcSenderExtensions
return true;
}
public bool RpcExitVentDesync(PlayerPhysics physics, int ventId, PlayerControl seer)
{
if (!physics) return false;
int clientId = seer.OwnerId;
if (AmongUsClient.Instance.ClientId == clientId)
{
physics.StopAllCoroutines();
physics.StartCoroutine(physics.CoExitVent(ventId));
return false;
}
if (clientId < 0) return false;
sender.AutoStartRpc(physics.NetId, RpcCalls.ExitVent, clientId);
sender.WritePacked(ventId);
sender.EndRpc();
return true;
}
}
}
+54 -8
View File
@@ -25,6 +25,7 @@ internal static class ExtendedPlayerControl
public static readonly HashSet<byte> CancelBlackScreenFix = [];
private static readonly List<Vent> ResultBuffer = [];
public static readonly HashSet<byte> TempExiled = [];
public static readonly Dictionary<byte, string> NameWithRoleCache = [];
extension(PlayerControl player)
{
@@ -570,6 +571,8 @@ internal static class ExtendedPlayerControl
var players = Main.CachedAllPlayerControls();
HashSet<(PlayerControl target, RoleTypes roleType, int seerClientId)> setRoleCallsMap = [];
switch (oldRoleIsDesync, newRoleIsDesync)
{
// Desync role to normal role
@@ -591,7 +594,7 @@ internal static class ExtendedPlayerControl
// Set role type for seer
StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(seer.PlayerId, player.PlayerId)] = (rememberRoleType, newCustomRole);
player.RpcSetRoleDesync(rememberRoleType, seerClientId);
setRoleCallsMap.Add((player, rememberRoleType, seerClientId));
if (self) continue;
@@ -609,13 +612,13 @@ internal static class ExtendedPlayerControl
if (!playerIsKiller && seer.Is(Team.Impostor)) rememberRoleType = RoleTypes.ImpostorGhost;
StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(player.PlayerId, seer.PlayerId)] = (seerCustomRole.IsDesyncRole() ? RoleTypes.Crewmate : seerRoleType, seerCustomRole);
seer.RpcSetRoleDesync(rememberRoleType, player.OwnerId);
setRoleCallsMap.Add((seer, rememberRoleType, player.OwnerId));
continue;
}
// Set role type for player
StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(player.PlayerId, seer.PlayerId)] = (rememberRoleType, seerCustomRole);
seer.RpcSetRoleDesync(rememberRoleType, player.OwnerId);
setRoleCallsMap.Add((seer, rememberRoleType, player.OwnerId));
}
break;
@@ -643,7 +646,7 @@ internal static class ExtendedPlayerControl
rememberRoleType = newRoleVN is CustomRoles.Noisemaker ? RoleTypes.Noisemaker : RoleTypes.Crewmate;
StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(seer.PlayerId, player.PlayerId)] = (rememberRoleType, newCustomRole);
player.RpcSetRoleDesync(rememberRoleType, seerClientId);
setRoleCallsMap.Add((player, rememberRoleType, seerClientId));
if (self) continue;
@@ -656,13 +659,13 @@ internal static class ExtendedPlayerControl
rememberRoleType = RoleTypes.CrewmateGhost;
StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(player.PlayerId, seer.PlayerId)] = (seerCustomRole.GetVNRole() is CustomRoles.Noisemaker ? RoleTypes.Noisemaker : RoleTypes.Crewmate, seerCustomRole);
seer.RpcSetRoleDesync(rememberRoleType, player.OwnerId);
setRoleCallsMap.Add((seer, rememberRoleType, player.OwnerId));
continue;
}
// Set role type for player
StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(player.PlayerId, seer.PlayerId)] = (rememberRoleType, seerCustomRole);
seer.RpcSetRoleDesync(rememberRoleType, player.OwnerId);
setRoleCallsMap.Add((seer, rememberRoleType, player.OwnerId));
}
break;
@@ -685,12 +688,54 @@ internal static class ExtendedPlayerControl
rememberRoleType = newRoleType;
StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(seer.PlayerId, player.PlayerId)] = (rememberRoleType, newCustomRole);
player.RpcSetRoleDesync(rememberRoleType, seerClientId);
setRoleCallsMap.Add((player, rememberRoleType, seerClientId));
}
break;
}
}
foreach (var targetGroup in setRoleCallsMap.GroupBy(x => x.target))
{
Dictionary<RoleTypes, int> counts = [];
RoleTypes globalRole = default;
int maxCount = 0;
foreach (var call in targetGroup)
{
int count = counts.TryGetValue(call.roleType, out int c) ? ++c : 1;
counts[call.roleType] = count;
if (count > maxCount)
{
maxCount = count;
globalRole = call.roleType;
}
}
int total = targetGroup.Count();
if (maxCount > 1 && 1 + total - maxCount < total)
{
targetGroup.Key.RpcSetRoleGlobal(globalRole);
LateTask.New(() =>
{
foreach (var call in targetGroup)
{
if (call.roleType != globalRole)
targetGroup.Key.RpcSetRoleDesync(call.roleType, call.seerClientId);
}
}, 0.2f);
}
else
{
foreach (var call in targetGroup)
targetGroup.Key.RpcSetRoleDesync(call.roleType, call.seerClientId);
}
}
if (loggerRoleMap)
{
@@ -1090,8 +1135,9 @@ internal static class ExtendedPlayerControl
{
try
{
if (NameWithRoleCache.TryGetValue(player?.PlayerId ?? 250, out string cache)) return cache;
bool addRoleName = GameStates.IsInGame && Options.CurrentGameMode is not CustomGameMode.FFA and not CustomGameMode.StopAndGo and not CustomGameMode.HotPotato and not CustomGameMode.Speedrun and not CustomGameMode.CaptureTheFlag and not CustomGameMode.NaturalDisasters and not CustomGameMode.RoomRush and not CustomGameMode.Quiz and not CustomGameMode.TheMindGame and not CustomGameMode.BedWars and not CustomGameMode.Deathrace and not CustomGameMode.Mingle and not CustomGameMode.Snowdown;
return $"{player?.Data?.PlayerName}" + (addRoleName ? $" ({player?.GetAllRoleName(forUser).RemoveHtmlTags().Replace('\n', ' ')})" : string.Empty);
return NameWithRoleCache[player?.PlayerId ?? 250] = $"{player?.Data?.PlayerName}" + (addRoleName ? $" ({player?.GetAllRoleName(forUser).RemoveHtmlTags().Replace('\n', ' ')})" : string.Empty);
}
catch (Exception e)
{
+7 -4
View File
@@ -145,6 +145,8 @@ public class PlayerState(byte playerId)
MainRole = role;
Role.Add(PlayerId);
ExtendedPlayerControl.NameWithRoleCache.Remove(PlayerId);
Logger.Info($"ID {PlayerId} ({Player.GetRealName()}) => {role}, CountTypes => {countTypes}", "SetMainRole");
@@ -158,10 +160,7 @@ public class PlayerState(byte playerId)
if (role.IsVanilla() || role.IsVanillaEHR())
Main.AbilityUseLimit.Remove(PlayerId);
}
if (Main.IntroDestroyed && GameStates.InGame)
{
if (PlayerId == PlayerControl.LocalPlayer.PlayerId && GameStates.IsInTask)
{
HudManager.Instance.SetHudActive(true);
@@ -239,6 +238,8 @@ public class PlayerState(byte playerId)
SetAddonCountTypes(role);
Logger.Info($" ID {PlayerId} ({Player?.GetRealName()}) => {role}, CountTypes => {countTypes}", "SetSubRole");
ExtendedPlayerControl.NameWithRoleCache.Remove(PlayerId);
}
private void SetAddonCountTypes(CustomRoles role)
@@ -361,6 +362,8 @@ public class PlayerState(byte playerId)
}
Utils.SendRPC(CustomRPC.RemoveSubRole, PlayerId, 1, (int)role);
ExtendedPlayerControl.NameWithRoleCache.Remove(PlayerId);
}
public void SetDead()
+1 -1
View File
@@ -320,7 +320,7 @@ public static class ChatManager
if (!AmongUsClient.Instance.AmHost) return;
PlayerControl player = Main.AllAlivePlayerControlsCount == 0 ? PlayerControl.LocalPlayer : Main.CachedAlivePlayerControls().MinBy(x => x.PlayerId);
if (!player) return;
if (targets.Count == 0 || targets.Count >= Main.AllAlivePlayerControlsCount) SendEmptyMessage(null);
if (targets == null || targets.Count == 0 || targets.Count >= Main.AllAlivePlayerControlsCount) SendEmptyMessage(null);
else targets.Do(SendEmptyMessage);
return;
+1
View File
@@ -200,6 +200,7 @@ internal static class ChangeRoleSettings
ExtendedPlayerControl.TempExiled.Clear();
Utils.CachedRoleSettings.Clear();
MeetingHudCastVotePatch.ShouldCancelVoteList.Clear();
ExtendedPlayerControl.NameWithRoleCache.Clear();
MeetingTimeManager.Init();
Main.DefaultCrewmateVision = Main.RealOptionsData.GetFloat(FloatOptionNames.CrewLightMod);
+35 -12
View File
@@ -1312,7 +1312,16 @@ internal static class ReportDeadBodyPatch
}); }
catch (Exception e) { ThrowException(e); }
try { if (Lovers.PrivateChat.GetBool() && Main.LoversPlayers.Count > 0) ChatManager.ClearChat(Main.EnumerateAlivePlayerControls().ExceptBy(Main.LoversPlayers.ConvertAll(x => x.PlayerId), x => x.PlayerId).ToArray()); }
try
{
if (Lovers.PrivateChat.GetBool() && Main.LoversPlayers.Count > 0)
{
if (GameStates.CurrentServerType != GameStates.ServerType.Vanilla)
ChatManager.ClearChat(Main.CachedAlivePlayerControls().FindAll(x => !Main.LoversPlayers.Exists(l => l.PlayerId == x.PlayerId)));
else
ChatManager.ClearChat();
}
}
catch (Exception e) { ThrowException(e); }
CustomSabotage.Reset();
@@ -1391,18 +1400,21 @@ internal static class ReportDeadBodyPatch
QuizMaster.Data.NumMeetings++;
}
if (Main.IsLoversDead && Lovers.LoverDieConsequence.GetValue() == 1 && Main.LoversPlayers.Exists(x => x && x.IsAlive()))
if (Main.IsLoversDead && Lovers.LoverDieConsequence.GetValue() == 1)
{
PlayerControl aliveLover = Main.LoversPlayers.First(x => x && x.IsAlive());
PlayerControl aliveLover = Main.LoversPlayers.Find(x => x && x.IsAlive());
switch (Lovers.LoverSuicideTime.GetValue())
if (aliveLover)
{
case 1:
aliveLover.Suicide(PlayerState.DeathReason.FollowingSuicide);
break;
case 2:
CheckForEndVotingPatch.TryAddAfterMeetingDeathPlayers(PlayerState.DeathReason.FollowingSuicide, aliveLover.PlayerId);
break;
switch (Lovers.LoverSuicideTime.GetValue())
{
case 1:
aliveLover.Suicide(PlayerState.DeathReason.FollowingSuicide);
break;
case 2:
CheckForEndVotingPatch.TryAddAfterMeetingDeathPlayers(PlayerState.DeathReason.FollowingSuicide, aliveLover.PlayerId);
break;
}
}
}
}
@@ -2065,8 +2077,19 @@ internal static class FixedUpdatePatch
if (!lowLoad)
{
Main.LoversPlayers.RemoveAll(x => !x);
if (!Main.HasJustStarted) Main.LoversPlayers.DoIf(x => !x.Is(CustomRoles.Lovers), x => x.RpcSetCustomRole(CustomRoles.Lovers));
for (int i = Main.LoversPlayers.Count - 1; i >= 0; i--)
{
PlayerControl lover = Main.LoversPlayers[i];
if (!lover)
{
Main.LoversPlayers.RemoveAt(i);
continue;
}
if (!Main.HasJustStarted && !lover.Is(CustomRoles.Lovers))
lover.RpcSetCustomRole(CustomRoles.Lovers);
}
}
if (Main.LoversPlayers.Exists(x => x.PlayerId == target.PlayerId) && (Main.LoversPlayers.Exists(x => x.PlayerId == lpId) || !seer.IsAlive()))
+4 -1
View File
@@ -254,7 +254,10 @@ public class Alchemist : RoleBase
{
InvisTimer = null;
if (!pc || !pc.IsAlive()) return;
Main.EnumeratePlayerControls().Without(pc).Do(x => instance.RpcExitVentDesync(ventId, x));
bool hasValue = false;
CustomRpcSender sender = CustomRpcSender.Create("Alchemist RpcExitVentDesync calls", SendOption.Reliable).StartPackedMessage();
Main.EnumeratePlayerControls().Without(pc).Do(x => hasValue |= sender.RpcExitVentDesync(instance, ventId, x));
sender.SendMessage(dispose: !hasValue);
pc.Notify(GetString("SwooperInvisStateOut"));
}, onTick: pc.IsModdedClient() ? null : () => pc.Notify(string.Format(GetString("SwooperInvisStateCountdown"), (int)Math.Ceiling(InvisTimer.Remaining.TotalSeconds)), overrideAll: true), onCanceled: () => InvisTimer = null);
@@ -153,7 +153,7 @@ public class Swooper : RoleBase
if (!AmongUsClient.Instance.AmHost) return;
var player = SwooperId.GetPlayer();
if (player == null || !player.IsAlive()) return;
if (!player || !player.IsAlive()) return;
if (!player.IsModdedClient() && !(UsedRole != CustomRoles.Chameleon && UsePhantomBasis.GetBool() && (UsedRole != CustomRoles.Wraith || UsePhantomBasisForNKs.GetBool())))
player.Notify(GetString("SwooperCanVent"), 10f);
@@ -162,7 +162,7 @@ public class Swooper : RoleBase
if (!AmongUsClient.Instance.AmHost) return;
var player = SwooperId.GetPlayer();
if (player == null || !player.IsAlive()) return;
if (!player || !player.IsAlive()) return;
if (!(UsePhantomBasis.GetBool() && (UsedRole != CustomRoles.Wraith || UsePhantomBasisForNKs.GetBool())))
player.Notify(string.Format(GetString("CDPT"), (int)Math.Ceiling(CooldownTimer.Remaining.TotalSeconds)), 3f, true);
@@ -178,7 +178,12 @@ public class Swooper : RoleBase
InvisTimer = null;
if (UsedRole == CustomRoles.Chameleon && !UsePets.GetBool())
Main.EnumeratePlayerControls().Without(player).Do(x => player.MyPhysics.RpcExitVentDesync(ventId, x));
{
bool hasValue = false;
CustomRpcSender sender = CustomRpcSender.Create("Swooper RpcExitVentDesync calls", SendOption.Reliable).StartPackedMessage();
Main.EnumeratePlayerControls().Without(player).Do(x => hasValue |= sender.RpcExitVentDesync(player.MyPhysics, ventId, x));
sender.SendMessage(dispose: !hasValue);
}
else
player.RpcMakeVisible(phantom: UsedRole == CustomRoles.Swooper);
@@ -268,7 +273,7 @@ public class Swooper : RoleBase
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false)
{
if (!hud || seer == null || seer.PlayerId != SwooperId || !GameStates.IsInTask || ExileController.Instance || !seer.IsAlive()) return string.Empty;
if (!hud || seer.PlayerId != SwooperId || meeting || !seer.IsAlive()) return string.Empty;
Suffix.Clear();