Fix meeting info not properly being set up on disconnected players

This commit is contained in:
D1GQ committed 2026-08-18 22:15:44 -05:00
1 parent 7d05220ace
commit d5a64de858
6 files changed
+72 -21

No files matched your search

@@ -226,6 +226,11 @@ internal sealed class ExtendedRoleInfo
/// </summary>
internal int Kills { get; set; } = 0;
/// <summary>
/// Gets or sets the player that was judged.
/// </summary>
internal PlayerId Judged { get; set; } = PlayerId.Invalid;
/// <summary>
/// Gets or sets whether noisemaker notification is enabled.
/// </summary>
+8 -10
View File
@@ -17,6 +17,7 @@ namespace BetterAmongUs.MonoScripts;
[RegisterInIl2Cpp]
internal sealed class MeetingInfoDisplay : PlayerInfoDisplay
{
private NetworkedPlayerInfo? _playerInfo;
private PlayerVoteArea? _pva;
private Vector3 _namePos;
private Vector3 _infoPos;
@@ -33,9 +34,9 @@ internal sealed class MeetingInfoDisplay : PlayerInfoDisplay
/// </summary>
/// <param name="player">The player to display info for.</param>
/// <param name="pva">The PlayerVoteArea associated with the player.</param>
internal void Init(PlayerControl? player, PlayerVoteArea pva)
internal void Init(NetworkedPlayerInfo? playerInfo, PlayerVoteArea pva)
{
_player = player;
_playerInfo = playerInfo;
_pva = pva;
_nameText = pva.NameText;
@@ -77,7 +78,7 @@ internal sealed class MeetingInfoDisplay : PlayerInfoDisplay
_ssbTag.Clear();
_ssbInfo.Clear();
if (_player != null)
if (_playerInfo.Object != null)
{
UpdateInfo();
}
@@ -138,11 +139,11 @@ internal sealed class MeetingInfoDisplay : PlayerInfoDisplay
/// </summary>
private void UpdateInfo()
{
if (_player == null || _player.Data == null || _player.ExtendedData() == null)
if (_playerInfo == null || _playerInfo.ExtendedData() == null)
return;
SetPlayerTags(_ssbTag);
_ssbInfo.Append(_player.GetRoleInfo(true));
_ssbInfo.Append(_playerInfo.GetRoleInfo(true));
UpdateNameTextPosition(_ssbInfo.ToString(), _ssbInfo.ToString());
@@ -157,13 +158,10 @@ internal sealed class MeetingInfoDisplay : PlayerInfoDisplay
[HideFromIl2Cpp]
private void SetPlayerTags(SplitStringBuilder ssbTag)
{
if (_player == null)
if (_playerInfo == null)
return;
if (_player.Data == null)
return;
if (BetterDataManager.Files.BetterDataFile.TryGetCheatInfo(_player.Data, out var info))
if (BetterDataManager.Files.BetterDataFile.TryGetCheatInfo(_playerInfo, out var info))
{
ssbTag.Append(info.title.ToColor(info.hexColor));
}
+13
View File
@@ -1,5 +1,7 @@
using BetterAmongUs.MonoScripts.Extended;
using BetterAmongUs.Utilities;
using HarmonyLib;
using InnerNet;
namespace BetterAmongUs.Patches.Gameplay;
@@ -21,4 +23,15 @@ internal static class RolePatch
return true;
}
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.SetJudgeOverrule))]
[HarmonyPostfix]
private static void MeetingHud_SetJudgeOverrule_Postfix(MeetingHud __instance, PlayerId judgePlayerId, PlayerId targetPlayerId, ushort overruleNonce)
{
var judge = Utils.PlayerFromPlayerId(judgePlayerId);
if (judge != null)
{
judge.ExtendedData().RoleInfo.Judged = targetPlayerId;
}
}
}
+1 -1
View File
@@ -32,7 +32,7 @@ internal static class MeetingHudPatch
{
if (pva == null) continue;
var target = Utils.PlayerFromPlayerId(pva.PlayerId);
var target = Utils.PlayerDataFromPlayerId(pva.PlayerId);
if (target == null) continue;
pva.gameObject.AddComponent<MeetingInfoDisplay>().Init(target, pva);
+29 -5
View File
@@ -160,7 +160,7 @@ internal static class PlayerControlUtils
KickCooldownManager.Trigger();
player.PerformKick(shouldBan, setReasonInfo, antiCheatBan);
}
/// <summary>
/// Kicks a player from the game immediately, regardless of cooldown.
/// Only use this if the target player is extremely dangerous and must be removed immediately.
@@ -217,7 +217,7 @@ internal static class PlayerControlUtils
shouldBan = ban && BetterGameSettings.WhenCheating.GetStringIndex() == 2;
return BetterGameSettings.WhenCheating.GetStringIndex() != 0;
}
/// <summary>
/// Kicks a player from the game with optional ban and anti-cheat features.
/// </summary>
@@ -293,6 +293,13 @@ internal static class PlayerControlUtils
/// <returns>True if the player is the local player.</returns>
internal static bool IsLocalPlayer(this PlayerControl player) => player != null && PlayerControl.LocalPlayer != null && player == PlayerControl.LocalPlayer;
/// <summary>
/// Checks if a player data is the local player data.
/// </summary>
/// <param name="playerData">The player data to check.</param>
/// <returns>True if the player data is the local player data.</returns>
internal static bool IsLocalData(this NetworkedPlayerInfo playerData) => playerData != null && PlayerControl.LocalPlayer != null && playerData == PlayerControl.LocalPlayer.Data;
/// <summary>
/// Gets the ID of the vent the player is currently in.
/// </summary>
@@ -502,13 +509,30 @@ internal static class PlayerControlUtils
/// <returns>True if the player is an impostor teammate.</returns>
internal static bool IsImpostorTeammate(this PlayerControl player)
{
if (player == null || PlayerControl.LocalPlayer == null)
if (player == null)
return false;
var data = player.Data;
if (data == null)
return false;
return data.IsImpostorTeammate();
}
/// <summary>
/// Checks if a player data is an impostor teammate of the local player data.
/// </summary>
/// <param name="playerData">The player data to check.</param>
/// <returns>True if the player data is an impostor teammate.</returns>
internal static bool IsImpostorTeammate(this NetworkedPlayerInfo playerData)
{
if (playerData == null || PlayerControl.LocalPlayer == null)
return false;
bool localIsImpostor = PlayerControl.LocalPlayer.IsImpostorTeam();
bool playerIsImpostor = player.IsImpostorTeam();
bool playerIsImpostor = playerData.IsImpostorTeam();
return (player.IsLocalPlayer() && localIsImpostor) ||
return (playerData.IsLocalData() && localIsImpostor) ||
(localIsImpostor && playerIsImpostor);
}
+16 -5
View File
@@ -90,13 +90,24 @@ internal static class RoleUtils
/// <param name="displayTask">Whether to display the player's task completion progress.</param>
/// <returns>Returns role info or <see cref="string.Empty"/> if the player's role information cannot be displayed.</returns>
internal static string GetRoleInfo(this PlayerControl player, bool displayTask)
{
return player.Data.GetRoleInfo(displayTask);
}
/// <summary>
/// Gets the role information for a specified player, optionally including task progress.
/// </summary>
/// <param name="playerData">The player data to get role information for.</param>
/// <param name="displayTask">Whether to display the player's task completion progress.</param>
/// <returns>Returns role info or <see cref="string.Empty"/> if the player's role information cannot be displayed.</returns>
internal static string GetRoleInfo(this NetworkedPlayerInfo playerData, bool displayTask)
{
if (!GameState.IsInGamePlay)
{
return string.Empty;
}
if (!player.IsLocalPlayer() && !player.IsImpostorTeammate())
if (playerData.PlayerId != PlayerControl.LocalPlayer.PlayerId && !playerData.IsImpostorTeammate())
{
if (PlayerControl.LocalPlayer.IsAlive())
{
@@ -109,19 +120,19 @@ internal static class RoleUtils
}
}
string roleInfo = player.GetRoleName().ToColor(player.Data.Role.TeamColor);
string roleInfo = playerData.RoleType.GetRoleName().ToColor(playerData.Role.TeamColor);
if (!player.IsImpostorTeam() && player.myTasks.Count > 0)
if (!playerData.IsImpostorTeam() && playerData.Tasks.Count > 0)
{
if (displayTask)
{
int completedTasks = 0;
foreach (var task in player.Data.Tasks)
foreach (var task in playerData.Tasks)
{
if (task.Complete)
completedTasks++;
}
roleInfo += $" <color=#cbcbcb>({completedTasks}/{player.Data.Tasks.Count})</color>";
roleInfo += $" <color=#cbcbcb>({completedTasks}/{playerData.Tasks.Count})</color>";
}
}