Merge pull request #16 from D1GQ/dev

Canary 6
This commit is contained in:
D1GQ authored and GitHub committed 2024-08-08 00:34:15 -05:00
commit 3efd1cea35
21 files changed
+439 -503

No files matched your search

+1 -1
View File
@@ -29,5 +29,5 @@
<!-- Embed all files in the Resources folder -->
<EmbeddedResource Include="Resources\**\*" />
</ItemGroup>
</Project>
+61 -54
View File
@@ -15,31 +15,6 @@ class AntiCheat
public static void Update()
{
if (GameStates.IsInGamePlay)
{
foreach (var kvp in ExtendedPlayerInfo.TimeSinceKill)
{
ExtendedPlayerInfo.TimeSinceKill[kvp.Key] += Time.deltaTime;
}
}
else
{
if (ExtendedPlayerInfo.TimeSinceKill.Any())
{
ExtendedPlayerInfo.TimeSinceKill.Clear();
}
if (ExtendedPlayerInfo.TimesCalledMeeting.Any())
{
ExtendedPlayerInfo.TimesCalledMeeting.Clear();
}
if (ExtendedPlayerInfo.HasNoisemakerNotify.Any())
{
ExtendedPlayerInfo.HasNoisemakerNotify.Clear();
}
}
if (GameStates.IsHost && GameStates.IsInGame)
{
RPC.SyncAllNames(isBetterHost: false);
@@ -69,7 +44,7 @@ class AntiCheat
public static void PauseAntiCheat()
{
float time = 2f;
float time = 4f;
if (IsEnabled)
{
IsEnabled = false;
@@ -96,25 +71,28 @@ class AntiCheat
{
if (__instance.Platform is Platforms.StandaloneWin10 or Platforms.Xbox)
{
if (__instance.XboxPlatformId == 0)
if (__instance.XboxPlatformId.ToString().Length is < 10 or > 16)
{
BetterNotificationManager.NotifyCheat(player, $"Platform Spoofer", newText: "Has been detected with a cheat");
}
player.ReportPlayer(ReportReasons.Cheating_Hacking);
BetterNotificationManager.NotifyCheat(player, $"Platform Spoofer", newText: "Has been detected with a cheat");
Logger.LogCheat($"{player.Data.PlayerName} Platform Spoofer: {__instance.XboxPlatformId} is not 10 to 16 characters");
}
}
if (__instance.Platform is Platforms.Playstation)
{
if (__instance.PsnPlatformId == 0)
if (__instance.PsnPlatformId.ToString().Length is < 14 or > 20)
{
BetterNotificationManager.NotifyCheat(player, $"Platform Spoofer", newText: "Has been detected with a cheat");
player.ReportPlayer(ReportReasons.Cheating_Hacking);
BetterNotificationManager.NotifyCheat(player, $"Platform Spoofer", newText: "Has been detected with a cheat");
Logger.LogCheat($"{player.Data.PlayerName} Platform Spoofer: {__instance.PsnPlatformId} is not 14 to 19 characters");
}
}
}
}, 1.5f, shoudLog: false);
}, 3.5f, shoudLog: false);
}
}
// Handle RPC before anti cheat detection
public static void HandleRPCBeforeCheck(PlayerControl player, byte callId, MessageReader Oldreader)
{
@@ -130,7 +108,7 @@ class AntiCheat
if (reader.BytesRemaining == 0 && !flag)
{
AmongUsClient.Instance.ReportPlayer(player.GetClientId(), ReportReasons.Cheating_Hacking);
player.ReportPlayer(ReportReasons.Cheating_Hacking);
SickoData[Utils.GetHashPuid(player)] = player.FriendCode;
BetterDataManager.SaveCheatData(Utils.GetHashPuid(player), player.Data.FriendCode, player.Data.PlayerName, "sickoData", "Sicko Menu RPC");
BetterNotificationManager.NotifyCheat(player, $"Sicko Menu", newText: "Has been detected with a cheat client");
@@ -152,7 +130,7 @@ class AntiCheat
if (!flag)
{
AmongUsClient.Instance.ReportPlayer(player.GetClientId(), ReportReasons.Cheating_Hacking);
player.ReportPlayer(ReportReasons.Cheating_Hacking);
AUMData[Utils.GetHashPuid(player)] = player.FriendCode;
BetterDataManager.SaveCheatData(Utils.GetHashPuid(player), player.Data.FriendCode, player.Data.PlayerName, "aumData", "AUM RPC");
BetterNotificationManager.NotifyCheat(player, $"AUM", newText: "Has been detected with a cheat client");
@@ -183,7 +161,7 @@ class AntiCheat
if (!flag && !flag2)
{
AmongUsClient.Instance.ReportPlayer(player.GetClientId(), ReportReasons.Cheating_Hacking);
player.ReportPlayer(ReportReasons.Cheating_Hacking);
AUMData[Utils.GetHashPuid(AUMPlayer)] = AUMPlayer.FriendCode;
BetterDataManager.SaveCheatData(Utils.GetHashPuid(player), player.Data.FriendCode, player.Data.PlayerName, "aumData", "AUM Chat RPC");
BetterNotificationManager.NotifyCheat(AUMPlayer, $"AUM", newText: "Has been detected with a cheat client");
@@ -202,7 +180,7 @@ class AntiCheat
{
MessageReader reader = MessageReader.Get(Oldreader);
if (PlayerControl.LocalPlayer == null || player == null || player == PlayerControl.LocalPlayer || player.GetIsBetterHost() || reader == null || !IsEnabled || !Main.AntiCheat.Value) return;
if (PlayerControl.LocalPlayer == null || player == null || player == PlayerControl.LocalPlayer || player.BetterData().IsBetterHost || reader == null || !IsEnabled || !Main.AntiCheat.Value) return;
RoleTypes? Role = player?.Data?.RoleType;
Role ??= RoleTypes.Crewmate;
@@ -211,7 +189,10 @@ class AntiCheat
if (callId is (byte)RpcCalls.SendChat or (byte)RpcCalls.SendQuickChat)
{
if (player.IsAlive() && GameStates.IsInGamePlay && !GameStates.IsMeeting && !GameStates.IsExilling)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.IsAlive()} - {GameStates.IsInGamePlay} - {!GameStates.IsMeeting} - {!GameStates.IsExilling}");
}
return;
}
@@ -219,7 +200,10 @@ class AntiCheat
if (callId is (byte)RpcCalls.EnterVent or (byte)RpcCalls.ExitVent)
{
if ((!player.IsImpostorTeam() && Role != RoleTypes.Engineer) || player.Data.IsDead)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.IsImpostorTeam()} - {Role != RoleTypes.Engineer} - {player.Data.IsDead}");
}
return;
}
@@ -227,32 +211,27 @@ class AntiCheat
if (callId is (byte)RpcCalls.ProtectPlayer)
{
if (Role is not RoleTypes.GuardianAngel)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {Role is not RoleTypes.GuardianAngel}");
}
return;
}
if (callId is (byte)RpcCalls.MurderPlayer)
{
bool condition = false;
if (ExtendedPlayerInfo.TimeSinceKill.TryGetValue(player, out var value))
{
if (value < GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown)
{
condition = true;
}
}
if (reader.BytesRemaining > 0)
{
PlayerControl target = reader.ReadNetObject<PlayerControl>();
if (target != null)
{
if (!player.IsImpostorTeam() || !player.IsAlive() || player.IsInVanish() || !target.IsAlive() || target.IsImpostorTeam() || condition)
if (!player.IsImpostorTeam() || !player.IsAlive() || player.IsInVanish() || target.IsImpostorTeam())
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {!player.IsImpostorTeam()} - {player.IsInVanish()}" +
$" - {!target.IsAlive()} - {target.IsImpostorTeam()}");
}
}
}
@@ -268,9 +247,9 @@ class AntiCheat
if (level >= 200)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Level: {level}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {level >= 200}");
}
}
return;
}
@@ -282,6 +261,7 @@ class AntiCheat
{
byte Type = reader.ReadByte();
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)} - {Enum.GetName((SystemTypes)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {!player.IsImpostorTeam()}");
return;
}
@@ -296,6 +276,7 @@ class AntiCheat
or (byte)SystemTypes.HeliSabotage)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)} - {Enum.GetName((SystemTypes)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {!player.IsImpostorTeam()}");
}
return;
@@ -308,6 +289,7 @@ class AntiCheat
if (callId is (byte)RpcCalls.CompleteTask or (byte)RpcCalls.BootFromVent)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.IsImpostorTeam()}");
return;
}
@@ -318,6 +300,7 @@ class AntiCheat
if (player?.CurrentOutfit?.PetId == "pet_EmptyPet")
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player?.CurrentOutfit?.PetId == "pet_EmptyPet"}");
}
return;
@@ -336,7 +319,7 @@ class AntiCheat
{
MessageReader reader = MessageReader.Get(Oldreader);
if (PlayerControl.LocalPlayer == null || player == null || player == PlayerControl.LocalPlayer || player.GetIsBetterHost() || reader == null || !IsEnabled || !Main.AntiCheat.Value) return true;
if (PlayerControl.LocalPlayer == null || player == null || player == PlayerControl.LocalPlayer || player.BetterData().IsBetterHost || reader == null || !IsEnabled || !Main.AntiCheat.Value) return true;
RoleTypes Role = player.Data.RoleType;
bool IsImpostor = player.IsImpostorTeam();
@@ -350,10 +333,13 @@ class AntiCheat
if (callId is (byte)RpcCalls.StartMeeting)
{
if (GameStates.IsMeeting || GameStates.IsHideNSeek || !player.IsAlive() || player.IsInVent() || player.shapeshifting
if (GameStates.IsMeeting && MeetingHudUpdatePatch.timeOpen > 0.5f || GameStates.IsHideNSeek || !player.IsAlive() || player.IsInVent() || player.shapeshifting
|| player.inMovingPlat || player.onLadder || player.MyPhysics.Animations.IsPlayingAnyLadderAnimation())
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {GameStates.IsMeeting} - {GameStates.IsHideNSeek} - {!player.IsAlive()} - {player.IsInVent()} - {player.shapeshifting}" +
$" - {player.inMovingPlat} - {player.onLadder} - {player.MyPhysics.Animations.IsPlayingAnyLadderAnimation()}");
if (GameStates.IsHost)
{
return false;
@@ -372,6 +358,7 @@ class AntiCheat
if (!UnityEngine.Object.FindAnyObjectByType<DeadBody>() || !deadPlayerInfo.IsDead || deadPlayerInfo == player.Data)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {!UnityEngine.Object.FindAnyObjectByType<DeadBody>()} - {!deadPlayerInfo.IsDead} - {deadPlayerInfo == player.Data}");
if (GameStates.IsHost)
{
return false;
@@ -384,9 +371,11 @@ class AntiCheat
}
else
{
if (ExtendedPlayerInfo.TimesCalledMeeting.TryGetValue(player, out var value) && value >= GameOptionsManager.Instance.currentNormalGameOptions.NumEmergencyMeetings)
if (player.BetterData().TimesCalledMeeting >= GameOptionsManager.Instance.currentNormalGameOptions.NumEmergencyMeetings)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.BetterData().TimesCalledMeeting} -> {GameOptionsManager.Instance.currentNormalGameOptions.NumEmergencyMeetings}" +
$" - {player.BetterData().TimesCalledMeeting >= GameOptionsManager.Instance.currentNormalGameOptions.NumEmergencyMeetings}");
if (GameStates.IsHost)
{
return false;
@@ -401,17 +390,21 @@ class AntiCheat
if (callId is (byte)RpcCalls.Shapeshift)
{
var target = reader.ReadNetObject<PlayerControl>();
var flag = reader.ReadBoolean();
bool ShapeshiftAsTarget = target != player;
if (Role is not RoleTypes.Shapeshifter || !player.IsAlive())
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)} 1: {Role is not RoleTypes.Shapeshifter} - {!player.IsAlive()}");
return false;
}
if (!flag && !player.IsInVent())
else if (!flag && !GameStates.IsMeeting && !GameStates.IsExilling && !player.IsInVent())
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)} 2: {!flag} - {!GameStates.IsMeeting} - {!GameStates.IsExilling} - {!player.IsInVent()}");
return false;
}
}
@@ -421,8 +414,18 @@ class AntiCheat
if (Role is not RoleTypes.Phantom || player.Data.IsDead)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)} 1: {Role is not RoleTypes.Phantom} - {player.Data.IsDead}");
return false;
}
if (callId is (byte)RpcCalls.StartVanish)
{
if (player.IsInVent())
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)} 2: {player.IsInVent()}");
}
}
}
if (!player.IsHost())
@@ -432,15 +435,17 @@ class AntiCheat
or (byte)RpcCalls.CloseMeeting)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Host RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {!player.IsHost()}");
return false;
}
}
if (player.DataIsCollected() == true)
if (player.DataIsCollected() == true && !GameStates.IsLocalGame && GameStates.IsVanillaServer)
{
if (callId is (byte)RpcCalls.SetName or (byte)RpcCalls.CheckName or (byte)RpcCalls.SetLevel)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Set RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.DataIsCollected() == true}");
return false;
}
}
@@ -455,6 +460,7 @@ class AntiCheat
or (byte)RpcCalls.SetNamePlate)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Set RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {GameStates.IsInGamePlay}");
return false;
}
}
@@ -489,6 +495,7 @@ class AntiCheat
or (byte)RpcCalls.CheckVanish)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Lobby RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {GameStates.IsInGame} - {GameStates.IsLobby}");
return false;
}
}
+11 -69
View File
@@ -8,13 +8,10 @@ namespace BetterAmongUs;
class BetterHostManager
{
private static Dictionary<byte, Dictionary<byte, string>> LastPlayerName = []; // Targetid, Playerid, Name
private static List<PlayerControl> VentStuck = [];
private static readonly List<PlayerControl> VentStuck = [];
public static void Update(PlayerControl player)
public static void PlayerUpdate(PlayerControl player)
{
if (!Main.BetterHost.Value) return;
// Lock up player vent button if it's invalid vent
if (!VentStuck.Contains(player) && player.inVent && !player.Is(RoleTypes.Engineer) && !player.IsImpostorTeam())
{
@@ -24,43 +21,6 @@ class BetterHostManager
}
}
public static bool IsSpeedExceeding(float currentSpeed)
{
float leniency = 1.8f;
float thresholdSpeed = GetAverageSpeed() + leniency;
bool isExceeding = currentSpeed > thresholdSpeed;
return isExceeding;
}
public static float GetAverageSpeed()
{
float speedMod = GameStates.IsHideNSeek
? GameOptionsManager.Instance.currentHideNSeekGameOptions.PlayerSpeedMod
: GameOptionsManager.Instance.currentNormalGameOptions.PlayerSpeedMod;
// Data points
float[] mods = { 0.5f, 1.5f, 2.0f }; // Add more as needed
float[] avgSpeeds = { 1.3f, 3.75f, 5.0f }; // Add corresponding speeds
int n = mods.Length;
float sumMod = 0, sumAvgSpeed = 0, sumModAvgSpeed = 0, sumModSquared = 0;
for (int i = 0; i < n; i++)
{
sumMod += mods[i];
sumAvgSpeed += avgSpeeds[i];
sumModAvgSpeed += mods[i] * avgSpeeds[i];
sumModSquared += mods[i] * mods[i];
}
float m = (n * sumModAvgSpeed - sumMod * sumAvgSpeed) / (n * sumModSquared - sumMod * sumMod);
float c = (sumAvgSpeed - m * sumMod) / n;
float estimatedAverageSpeed = m * speedMod + c;
return estimatedAverageSpeed;
}
public static bool CheckRange(Vector2 pos1, Vector2 pos2, float range) => Vector2.Distance(pos1, pos2) <= range;
public static bool CheckRPCAsHost(PlayerControl player, byte callId, MessageReader reader, ref bool canceled)
@@ -97,16 +57,6 @@ class BetterHostManager
{
PlayerControl target = reader.ReadNetObject<PlayerControl>();
bool condition = false;
if (ExtendedPlayerInfo.TimeSinceKill.TryGetValue(player, out var value))
{
if (value >= GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown)
{
condition = true;
}
}
if (target != null)
{
if (player.IsAlive()
@@ -117,7 +67,6 @@ class BetterHostManager
&& !player.shapeshifting
&& !player.onLadder
&& !player.MyPhysics.Animations.IsPlayingAnyLadderAnimation()
&& condition
&& CheckRange(player.GetCustomPosition(), target.GetCustomPosition(), 3f))
{
if (target.IsAlive()
@@ -152,12 +101,12 @@ class BetterHostManager
&& !player.onLadder
&& !player.MyPhysics.Animations.IsPlayingAnyLadderAnimation())
{
if (!target.IsInVent() && flag == false)
if (!target.IsInVent() && !GameStates.IsMeeting && !GameStates.IsExilling && flag == false)
{
break;
}
player.RpcShapeshift(target, !target.IsInVent());
player.RpcShapeshift(target, !target.IsInVent() && !GameStates.IsMeeting && !GameStates.IsExilling);
break;
}
}
@@ -246,7 +195,7 @@ class BetterHostManager
foreach (PlayerControl target in Main.AllPlayerControls)
{
if (target == null || target == PlayerControl.LocalPlayer || target.GetIsBetterUser()) continue;
if (target == null || target == PlayerControl.LocalPlayer || target.BetterData().IsBetterUser) continue;
string NewName = player.CurrentOutfit.PlayerName;
@@ -265,7 +214,7 @@ class BetterHostManager
if (player == PlayerControl.LocalPlayer)
sbTopTag.Append($"<color=#0dff00>Better Host</color>+++");
else if (player.GetIsBetterUser())
else if (player.BetterData().IsBetterUser)
sbTopTag.Append("<color=#0dff00>Better User</color>+++");
}
else if (GameStates.IsInGamePlay)
@@ -298,27 +247,20 @@ class BetterHostManager
}
if (sbTopInfo.Length > 0)
NewName = $"<size=50%>{sbTopInfo}</size>\n{NewName}";
NewName = $"<size=65%>{sbTopInfo}</size>\n{NewName}";
else
NewName = $"{NewName}";
// Don't send rpc if name is the same!
if (LastPlayerName.TryGetValue(target.Data.PlayerId, out var playerNameDict))
if (player.BetterData().LastNameSetFor.TryGetValue(target.PlayerId, out var lastName) && lastName == NewName)
{
if (playerNameDict.TryGetValue(player.Data.PlayerId, out var currentName) && currentName == NewName)
if (!force)
{
if (!force)
{
return;
}
return;
}
}
else
{
LastPlayerName[target.Data.PlayerId] = new Dictionary<byte, string>();
}
LastPlayerName[target.Data.PlayerId][player.Data.PlayerId] = NewName;
player.BetterData().LastNameSetFor[target.PlayerId] = NewName;
player.RpcSetNamePrivate(NewName, target);
Logger.Log($"Set {player.Data.PlayerName} name to {NewName.Replace("\n", "-")} for {target.Data.PlayerName}", "RPC");
+28 -12
View File
@@ -34,29 +34,29 @@ static class ExtendedPlayerControl
public static void SetPlayerTextInfo(this PlayerControl player, string text, bool isBottom = false, bool isInfo = false)
{
if (player == null) return;
GameObject playerbase = player.gameObject;
string InfoType = isBottom ? "InfoText_B_TMP" : "InfoText_T_TMP";
string infoType = isBottom ? "InfoText_B_TMP" : "InfoText_T_TMP";
if (isInfo)
{
InfoType = "InfoText_Info_TMP";
GameObject TopText = GameObject.Find($"{playerbase.transform.name}/Names/NameText_TMP/InfoText_T_TMP");
if (TopText != null)
infoType = "InfoText_Info_TMP";
var topText = player.gameObject.transform.Find("Names/NameText_TMP/InfoText_T_TMP")?.GetComponent<TextMeshPro>();
if (topText != null && string.IsNullOrEmpty(Utils.GetRawText(topText.text)))
{
if (TopText.GetComponent<TextMeshPro>()?.text.Replace("<size=65%>", string.Empty).Replace("</size>", string.Empty).Length < 1)
{
text = "<voffset=-2.25em>" + text + "</voffset>";
}
text = "<voffset=-2.25em>" + text + "</voffset>";
}
}
text = "<size=65%>" + text + "</size>";
GameObject TextObj = GameObject.Find($"{player?.gameObject.transform.name}/Names/NameText_TMP/{InfoType}");
if (TextObj != null)
var textObj = player.gameObject.transform.Find($"Names/NameText_TMP/{infoType}")?.GetComponent<TextMeshPro>();
if (textObj != null)
{
TextObj.GetComponent<TextMeshPro>().text = text;
textObj.text = text;
}
}
// Reset players over head text
public static void ResetAllPlayerTextInfo(this PlayerControl player)
{
@@ -70,6 +70,11 @@ static class ExtendedPlayerControl
{
if (player == null) return false;
if (player.isDummy || GameStates.IsLocalGame || !GameStates.IsVanillaServer)
{
return true;
}
if (player.gameObject.transform.Find("Names/NameText_TMP").GetComponent<TextMeshPro>().text
is "???" or "Player" or "<color=#b5b5b5>Loading</color>" or null
|| player.Data == null
@@ -170,4 +175,15 @@ static class ExtendedPlayerControl
// Check if player is the host
public static bool IsHost(this PlayerControl player) => player?.Data != null && GameData.Instance?.GetHost()?.Puid == player.Data.Puid;
// Report player
public static void ReportPlayer(this PlayerControl player, ReportReasons reason = ReportReasons.None)
{
if (player != null)
{
if (!player.GetClient().HasBeenReported)
{
AmongUsClient.Instance.ReportPlayer(player.GetClientId(), reason);
}
}
}
}
+22 -33
View File
@@ -1,38 +1,27 @@
namespace BetterAmongUs;
namespace BetterAmongUs;
static class ExtendedPlayerInfo
public class ExtendedPlayerInfo
{
public static List<PlayerControl> HasNoisemakerNotify = [];
public static Dictionary<PlayerControl, float> TimeSinceKill = [];
public static Dictionary<PlayerControl, int> TimesCalledMeeting = [];
private static Dictionary<PlayerControl, bool> IsBetterUser = new Dictionary<PlayerControl, bool>();
private static Dictionary<PlayerControl, bool> IsBetterHost = new Dictionary<PlayerControl, bool>();
public Dictionary<byte, string> LastNameSetFor { get; set; } = [];
public bool IsBetterUser { get; set; } = false;
public bool IsBetterHost { get; set; } = false;
public bool IsTOHEHost { get; set; } = false;
public bool HasNoisemakerNotify { get; set; } = false;
public int TimesCalledMeeting { get; set; } = 0;
public static bool GetIsBetterUser(this PlayerControl player)
{
if (IsBetterUser.ContainsKey(player))
return IsBetterUser[player];
else
return false;
}
public static bool GetIsBetterHost(this PlayerControl player)
{
if (player.IsHost() && IsBetterHost.ContainsKey(player))
return IsBetterHost[player];
else
return false;
}
public static void SetIsBetterUser(this PlayerControl player, bool value)
{
IsBetterUser[player] = value;
}
public static void SetIsBetterHost(this PlayerControl player, bool value)
{
IsBetterHost[player] = value;
}
}
public static class PlayerControlExtensions
{
private static readonly Dictionary<PlayerControl, ExtendedPlayerInfo> playerInfo = [];
public static ExtendedPlayerInfo BetterData(this PlayerControl player)
{
if (!playerInfo.ContainsKey(player))
{
playerInfo[player] = new ExtendedPlayerInfo();
}
return playerInfo[player];
}
}
+2 -1
View File
@@ -45,7 +45,8 @@ public static class GameStates
public static bool IsCountDown => GameStartManager.InstanceExists && GameStartManager.Instance.startState == GameStartManager.StartingStates.Countdown;
public static bool IsShip => ShipStatus.Instance != null;
public static bool IsHost => AmongUsClient.Instance != null && AmongUsClient.Instance.AmHost;
public static bool IsBetterHostLobby => (PlayerControl.LocalPlayer.IsHost() && Main.BetterHost.Value) || Main.AllPlayerControls.Any(pc => pc.IsHost() && pc.GetIsBetterHost());
public static bool IsBetterHostLobby => (PlayerControl.LocalPlayer.IsHost() && Main.BetterHost.Value) || Main.AllPlayerControls.Any(pc => pc.IsHost() && pc.BetterData().IsBetterHost);
public static bool IsTOHEHostLobby => Main.AllPlayerControls.Any(pc => pc.IsHost() && pc.BetterData().IsTOHEHost);
public static bool IsCanMove => PlayerControl.LocalPlayer?.CanMove is true;
public static bool IsDead => PlayerControl.LocalPlayer?.Data?.IsDead is true;
}
+4 -3
View File
@@ -86,7 +86,7 @@ internal static class RPC
{
if (!GameStates.IsHost) return;
if (player.GetIsBetterUser())
if (player.BetterData().IsBetterUser)
{
if (sendToBetterUser)
{
@@ -148,8 +148,8 @@ internal static class RPC
break;
}
player.SetIsBetterUser(true);
player.SetIsBetterHost(IsBetterHost);
player.BetterData().IsBetterUser = true;
player.BetterData().IsBetterHost = IsBetterHost;
}
break;
case (byte)CustomRPC.AddChat:
@@ -158,6 +158,7 @@ internal static class RPC
case (byte)CustomRPC.VersionCheck or (byte)CustomRPC.RequestRetryVersionCheck:
if (player.IsHost())
{
player.BetterData().IsTOHEHost = true;
var BAU = "<color=#278720>♻</color><color=#0ed400><b>BetterAmongUs</b></color><color=#278720>♻</color>";
Utils.DisconnectSelf($"{BAU} does not support <color=#ff9cdc><b>TOHE</b></color>");
}
+2
View File
@@ -219,6 +219,8 @@ public static class Utils
case Platforms.Unknown:
PlatformName = "None";
break;
default:
return string.Empty;
}
if (useTag == false)
-46
View File
@@ -1,46 +0,0 @@
using HarmonyLib;
namespace BetterAmongUs.Patches;
internal class ButtonsPatch
{
// Handle EFC
[HarmonyPatch(typeof(SabotageButton))]
internal class SabotageButtonPatch
{
[HarmonyPatch(nameof(SabotageButton.DoClick))]
[HarmonyPrefix]
public static bool DoClick_Prefix(SabotageButton __instance)
{
if (PlayerControl.LocalPlayer.Data.Role.IsImpostor && GameManager.Instance.SabotagesEnabled())
{
DestroyableSingleton<HudManager>.Instance.ToggleMapVisible(new MapOptions
{
Mode = MapOptions.Modes.Sabotage
});
}
return false;
}
[HarmonyPatch(nameof(SabotageButton.Refresh))]
[HarmonyPrefix]
public static bool Refresh_Prefix(SabotageButton __instance)
{
if (GameManager.Instance == null || PlayerControl.LocalPlayer == null)
{
__instance.ToggleVisible(false);
__instance.SetDisabled();
return false;
}
if (!GameManager.Instance.SabotagesEnabled() || PlayerControl.LocalPlayer.petting)
{
__instance.ToggleVisible(PlayerControl.LocalPlayer.Data.Role.IsImpostor && GameManager.Instance.SabotagesEnabled());
__instance.SetDisabled();
return false;
}
__instance.SetEnabled();
return false;
}
}
}
+7 -6
View File
@@ -123,6 +123,7 @@ class ChatPatch
ChatBubble pooledBubble = __instance.GetPooledBubble();
try
{
chatText = chatText.Replace("\n", "");
pooledBubble.transform.SetParent(__instance.scroller.Inner);
pooledBubble.transform.localScale = Vector3.one;
bool flag = sourcePlayer == PlayerControl.LocalPlayer;
@@ -170,9 +171,9 @@ class ChatPatch
if (sourcePlayer.IsDev())
sbTag.Append("<color=#0088ff>Dev</color>+++");
if (((sourcePlayer == PlayerControl.LocalPlayer && GameStates.IsHost && Main.BetterHost.Value) || sourcePlayer.GetIsBetterHost() == true) && !GameStates.IsInGamePlay)
if (((sourcePlayer == PlayerControl.LocalPlayer && GameStates.IsHost && Main.BetterHost.Value) || sourcePlayer.BetterData().IsBetterHost) && !GameStates.IsInGamePlay)
sbTag.Append("<color=#0dff00>Better Host</color>+++");
else if ((sourcePlayer == PlayerControl.LocalPlayer || sourcePlayer.GetIsBetterUser() == true) && !GameStates.IsInGamePlay)
else if ((sourcePlayer == PlayerControl.LocalPlayer || sourcePlayer.BetterData().IsBetterUser) && !GameStates.IsInGamePlay)
sbTag.Append("<color=#0dff00>Better User</color>+++");
if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.SickoData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.SickoData.ContainsValue(friendCode))
@@ -242,15 +243,15 @@ class ChatPatch
__instance.textArea.AllowSymbols = true;
__instance.textArea.AllowPaste = true;
__instance.textArea.AllowEmail = true;
__instance.textArea.characterLimit = 120;
__instance.charCountText.text = "0/120";
__instance.textArea.characterLimit = 118;
__instance.charCountText.text = "0/118";
}
[HarmonyPatch(nameof(FreeChatInputField.UpdateCharCount))]
[HarmonyPostfix]
public static void UpdateCharCount_Postfix(FreeChatInputField __instance)
{
int length = __instance.textArea.text.Length;
__instance.charCountText.text = string.Format("{0}/120", length);
__instance.charCountText.text = string.Format("{0}/118", length);
__instance.charCountText.color = GetCharColor(length, UnityEngine.Color.white);
}
}
@@ -260,7 +261,7 @@ class ChatPatch
switch (length)
{
case int n when n > 119:
case int n when n > 117:
if (ColorUtility.TryParseHtmlString("#ff0000", out UnityEngine.Color newColor1))
color = newColor1;
break;
+28
View File
@@ -32,4 +32,32 @@ public class ClientPatch
return false;
}
}
[HarmonyPatch(typeof(RegionMenu))]
public class RegionMenuPatch
{
[HarmonyPatch(nameof(RegionMenu.OnEnable))]
[HarmonyPostfix]
public static void AdjustButtonPositions_Postfix(RegionMenu __instance)
{
const int buttonsPerColumn = 6;
float buttonSpacing = 0.6f;
float buttonSpacingSide = 2.25f;
List<UiElement> buttons = __instance.controllerSelectable.ToArray().ToList();
int columnCount = (buttons.Count + buttonsPerColumn - 1) / buttonsPerColumn;
float totalWidth = (columnCount - 1) * buttonSpacingSide;
float totalHeight = (buttonsPerColumn - 1) * buttonSpacing;
Vector3 startPosition = new Vector3(-totalWidth / 2, totalHeight / 2, 0f);
for (int i = 0; i < buttons.Count; i++)
{
int col = i / buttonsPerColumn;
int row = i % buttonsPerColumn;
buttons[i].transform.localPosition = startPosition + new Vector3(col * buttonSpacingSide, -row * buttonSpacing, 0f);
}
}
}
}
+6
View File
@@ -313,6 +313,9 @@ class CommandsPatch
case "tracker" or "7":
role = RoleTypes.Tracker;
break;
case "noisemaker" or "8":
role = RoleTypes.Noisemaker;
break;
default:
Utils.AddChatPrivate($"<color=#730000>{error}\nInvalid RoleType!");
return;
@@ -360,6 +363,9 @@ class CommandsPatch
case "tracker" or "7":
role = RoleTypes.Tracker;
break;
case "noisemaker" or "8":
role = RoleTypes.Noisemaker;
break;
default:
Utils.AddChatPrivate($"<color=#730000>{error}\nInvalid RoleType!");
return;
-15
View File
@@ -1,15 +0,0 @@
using HarmonyLib;
namespace BetterAmongUs.Patches;
[HarmonyPatch(typeof(EOSManager))]
public class EOSManagerPatch
{
[HarmonyPatch(nameof(EOSManager.Update))]
[HarmonyPostfix]
public static void Postfix(EOSManager __instance)
{
__instance.ageOfConsent = 21;
__instance.isKWSMinor = false;
}
}
+14 -8
View File
@@ -97,27 +97,31 @@ internal class MainMenuPatch
buttons.Add(button);
button.name = name;
UnityEngine.Object.Destroy(button.GetComponent<AspectPosition>());
for (int i = 0; i < buttons.ToList().Count; i++)
{
float baseY = -2.7182f;
float newY = baseY + (0.35f * i);
button.transform.localPosition = new(-0.8118f, newY, -5f);
button.transform.localScale = new(0.78f, 0.78f, 0.78f);
}
// Set button position and scale
float baseY = -2.7882f;
float newY = baseY + (0.38f * (buttons.Count - 1));
button.transform.localPosition = new Vector3(-0.8118f, newY, -5f);
button.transform.localScale = new Vector3(0.78f, 0.78f, 0.78f);
// Set button action
button.OnClick = new();
button.OnClick.AddListener(action);
// Set button text
var buttonText = button.transform.Find("FontPlacer/Text_TMP").GetComponent<TMP_Text>();
buttonText.DestroyTranslator();
buttonText.fontSize = buttonText.fontSizeMax = buttonText.fontSizeMin = 3.5f;
buttonText.enableWordWrapping = false;
buttonText.text = label;
// Set button colors
var normalSprite = button.inactiveSprites.GetComponent<SpriteRenderer>();
var hoverSprite = button.activeSprites.GetComponent<SpriteRenderer>();
normalSprite.color = normalColor;
hoverSprite.color = hoverColor;
// Align text
var container = buttonText.transform.parent;
UnityEngine.Object.Destroy(container.GetComponent<AspectPosition>());
UnityEngine.Object.Destroy(buttonText.GetComponent<AspectPosition>());
@@ -125,15 +129,17 @@ internal class MainMenuPatch
buttonText.transform.SetLocalX(0f);
buttonText.horizontalAlignment = HorizontalAlignmentOptions.Center;
// Set button collider
var buttonCollider = button.GetComponent<BoxCollider2D>();
if (scale.HasValue)
{
normalSprite.size = hoverSprite.size = buttonCollider.size = scale.Value;
}
buttonCollider.offset = new(0f, 0f);
buttonCollider.offset = new Vector2(0f, 0f);
return button;
}
}
}
+18 -1
View File
@@ -1,9 +1,11 @@
using HarmonyLib;
using Hazel;
using System.Text;
using TMPro;
using UnityEngine;
namespace BetterAmongUs;
namespace BetterAmongUs;
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Start))]
class MeetingHudStartPatch
{
@@ -50,9 +52,13 @@ class MeetingHudStartPatch
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Update))]
class MeetingHudUpdatePatch
{
public static float timeOpen = 0f;
// Set player meeting info
public static void Postfix(MeetingHud __instance)
{
timeOpen += Time.deltaTime;
foreach (var pva in __instance.playerStates)
{
if (pva == null) return;
@@ -165,4 +171,15 @@ class MeetingHudUpdatePatch
TextObj.GetComponent<TextMeshPro>().text = text;
}
}
}
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.OnDestroy))]
class MeetingHud_OnDestroyPatch
{
public static void Postfix()
{
MeetingHudUpdatePatch.timeOpen = 0f;
Logger.LogHeader("Meeting Has Endded");
RPC.SyncAllNames(force: true);
}
}
+4 -84
View File
@@ -9,92 +9,12 @@ public class MiniMapBehaviourPatch
[HarmonyPatch(typeof(MapBehaviour))]
class MapBehaviourPatch
{
[HarmonyPatch(nameof(MapBehaviour.Awake))]
[HarmonyPostfix]
public static void Awake_Postfix(MapBehaviour __instance)
{
PoolablePlayer NewDisplay = __instance.HerePoint.gameObject.AddComponent<PoolablePlayer>();
if (NewDisplay != null)
{
NewDisplay.SetBodyCosmeticsVisible(true);
}
}
[HarmonyPatch(nameof(MapBehaviour.Show))]
[HarmonyPrefix]
public static bool Show_Prefix(MapBehaviour __instance, ref MapOptions opts)
{
if (__instance.IsOpen)
{
__instance.Close();
return false;
}
if (!PlayerControl.LocalPlayer.CanMove && !PlayerControl.LocalPlayer.IsInVent() && !PlayerControl.LocalPlayer.onLadder && !PlayerControl.LocalPlayer.inMovingPlat && !GameStates.IsMeeting)
{
return false;
}
switch (opts.Mode)
{
case MapOptions.Modes.Normal:
__instance.ShowNormalMap();
break;
case MapOptions.Modes.CountOverlay:
__instance.ShowCountOverlay(opts.AllowMovementWhileMapOpen, opts.ShowLivePlayerPosition, opts.IncludeDeadBodies);
break;
case MapOptions.Modes.Sabotage:
__instance.ShowSabotageMap();
break;
}
return false;
}
[HarmonyPatch(nameof(MapBehaviour.ShowNormalMap))]
[HarmonyPrefix]
public static bool ShowNormalMap_Prefix(MapBehaviour __instance)
{
if (__instance.IsOpen)
{
__instance.Close();
return false;
}
if (!PlayerControl.LocalPlayer.CanMove && !PlayerControl.LocalPlayer.IsInVent() && !PlayerControl.LocalPlayer.onLadder && !PlayerControl.LocalPlayer.inMovingPlat && !GameStates.IsMeeting)
{
return false;
}
PlayerControl.LocalPlayer.SetPlayerMaterialColors(__instance.HerePoint);
if (PlayerControl.LocalPlayer.isTrackingPlayer)
{
if (PlayerControl.LocalPlayer.trackedPlayer.Data.Disconnected)
{
__instance.TrackedHerePoint.gameObject.SetActive(false);
}
else
{
__instance.SetTrackedHerePointColor(PlayerControl.LocalPlayer.trackedPlayerColorID);
__instance.TrackedHerePoint.gameObject.SetActive(true);
__instance.UpdateTrackedPosition();
}
}
__instance.GenericShow();
__instance.taskOverlay.Show();
__instance.ColorControl.SetColor(new Color(0.05f, 0.6f, 1f, 1f));
DestroyableSingleton<HudManager>.Instance.SetHudActive(false);
return false;
}
[HarmonyPostfix]
public static void ShowNormalMap_Postfix(MapBehaviour __instance) => __instance.ColorControl.SetColor(new Color(0.05f, 0.6f, 1f, 1f));
[HarmonyPatch(nameof(MapBehaviour.ShowSabotageMap))]
[HarmonyPrefix]
public static bool ShowSabotageMap_Prefix(MapBehaviour __instance)
{
if (!PlayerControl.LocalPlayer.CanMove && !PlayerControl.LocalPlayer.IsInVent() && !PlayerControl.LocalPlayer.onLadder && !PlayerControl.LocalPlayer.inMovingPlat)
{
return false;
}
PlayerControl.LocalPlayer.SetPlayerMaterialColors(__instance.HerePoint);
__instance.GenericShow();
__instance.infectedOverlay.gameObject.SetActive(true);
__instance.taskOverlay.Show();
__instance.ColorControl.SetColor(new Color(1f, 0.3f, 0f, 1f));
return false;
}
[HarmonyPostfix]
public static void ShowSabotageMap_Postfix(MapBehaviour __instance) => __instance.ColorControl.SetColor(new Color(1f, 0.3f, 0f, 1f));
[HarmonyPatch(nameof(MapBehaviour.ShowCountOverlay))]
[HarmonyPostfix]
public static void ShowCountOverlay_Postfix(MapBehaviour __instance) => __instance.ColorControl.SetColor(new Color(0.2f, 0.5f, 0f, 1f));
+1 -1
View File
@@ -10,7 +10,7 @@ public class ModManagerPatch
[HarmonyPostfix]
public static void LateUpdate_Postfix(ModManager __instance)
{
// __instance.ShowModStamp();
__instance.ShowModStamp();
if (__instance.ModStamp.gameObject.active == true)
__instance.ModStamp.GetComponent<SpriteRenderer>().sprite = Utils.LoadSprite("BetterAmongUs.Resources.Images.BetterAmongUs-Mod.png", 250f);
+159 -159
View File
@@ -1,11 +1,13 @@
using AmongUs.Data;
using HarmonyLib;
using Hazel;
using Il2CppSystem.Linq;
using LibCpp2IL;
using System.Text;
using System.Text.RegularExpressions;
using TMPro;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;
namespace BetterAmongUs.Patches;
@@ -18,30 +20,29 @@ class PlayerControlPatch
public static void FixedUpdate_Prefix(PlayerControl __instance)
{
// Set up player text info
var NameText = GameObject.Find($"{__instance.gameObject.transform.name}/Names/NameText_TMP");
var InfoText = GameObject.Find($"{__instance.gameObject.transform.name}/Names/NameText_TMP/InfoText_T_TMP");
if (NameText != null && InfoText == null)
var nameTextTransform = __instance.gameObject.transform.Find("Names/NameText_TMP");
var nameText = nameTextTransform?.gameObject;
var infoText = nameTextTransform?.Find("InfoText_T_TMP");
if (nameText != null && infoText == null)
{
GameObject playerInfoDisplayInfo = UnityEngine.Object.Instantiate(NameText, NameText.transform);
playerInfoDisplayInfo.name = "InfoText_Info_TMP";
playerInfoDisplayInfo.transform.DestroyChildren();
playerInfoDisplayInfo.transform.position += new Vector3(0f, 0.25f);
playerInfoDisplayInfo.GetComponent<TextMeshPro>().text = string.Empty;
playerInfoDisplayInfo.SetActive(true);
void InstantiatePlayerInfoText(string name, Vector3 positionOffset)
{
var newTextObject = UnityEngine.Object.Instantiate(nameText, nameTextTransform);
newTextObject.name = name;
newTextObject.transform.DestroyChildren();
newTextObject.transform.position += positionOffset;
var textMesh = newTextObject.GetComponent<TextMeshPro>();
if (textMesh != null)
{
textMesh.text = string.Empty;
}
newTextObject.SetActive(true);
}
GameObject playerInfoDisplayTop = UnityEngine.Object.Instantiate(NameText, NameText.transform);
playerInfoDisplayTop.name = "InfoText_T_TMP";
playerInfoDisplayTop.transform.DestroyChildren();
playerInfoDisplayTop.transform.position += new Vector3(0f, 0.15f);
playerInfoDisplayTop.GetComponent<TextMeshPro>().text = string.Empty;
playerInfoDisplayTop.SetActive(true);
GameObject playerInfoDisplayBottom = UnityEngine.Object.Instantiate(NameText, NameText.transform);
playerInfoDisplayBottom.name = "InfoText_B_TMP";
playerInfoDisplayBottom.transform.DestroyChildren();
playerInfoDisplayBottom.transform.position += new Vector3(0f, -0.15f);
playerInfoDisplayBottom.GetComponent<TextMeshPro>().text = string.Empty;
playerInfoDisplayBottom.SetActive(true);
InstantiatePlayerInfoText("InfoText_Info_TMP", new Vector3(0f, 0.25f));
InstantiatePlayerInfoText("InfoText_T_TMP", new Vector3(0f, 0.15f));
InstantiatePlayerInfoText("InfoText_B_TMP", new Vector3(0f, -0.15f));
}
// Set color blind text on player
@@ -54,167 +55,168 @@ class PlayerControlPatch
__instance.cosmetics.colorBlindText.text = string.Empty;
}
if (GameStates.IsInGame && GameStates.IsHost && Main.BetterHost.Value)
{
BetterHostManager.PlayerUpdate(__instance);
}
infotime -= Time.deltaTime;
if (infotime <= 0)
{
SetPlayerInfo(__instance);
infotime = 0.6f;
infotime = 0.4f;
}
if (GameStates.IsInGame && GameStates.IsHost)
if (!GameStates.IsInGamePlay)
{
BetterHostManager.Update(__instance);
__instance.BetterData().TimesCalledMeeting = 0;
__instance.BetterData().HasNoisemakerNotify = false;
}
}
public static void SetPlayerInfo(PlayerControl player)
{
if (player == null || player.Data == null) return;
// Set player text info
if (player.DataIsCollected() != true)
try
{
if (player.gameObject.transform.Find("Names/NameText_TMP").GetComponent<TextMeshPro>().text is "???" or "Player")
if (player == null || player.Data == null) return;
var nameText = player.gameObject.transform.Find("Names/NameText_TMP").GetComponent<TextMeshPro>();
// Set player text info
if (!player.DataIsCollected())
{
player.gameObject.transform.Find("Names/NameText_TMP").GetComponent<TextMeshPro>().text = "<color=#b5b5b5>Loading</color>";
nameText.text = "<color=#b5b5b5>Loading</color>";
return;
}
return;
}
if (Main.AllPlayerControls.Any(pc => player.Data.PlayerId == pc.shapeshiftTargetPlayerId))
return;
string NewName = player.Data.PlayerName;
string hashPuid = Utils.GetHashPuid(player);
string friendCode = player.Data.FriendCode;
int playerId = player.PlayerId;
string Lv = " - <color=#ffd829>Lv: " + player.Data.PlayerLevel.ToString() + "</color>";
string pattern = @"^[a-zA-Z0-9#]+$";
string hashtagPattern = @"^#[0-9]{4}$";
string friendCodeColor = (Regex.Replace(friendCode, hashtagPattern, string.Empty).Length is > 10 or < 5 || !Regex.IsMatch(friendCode, pattern) || !Regex.IsMatch(friendCode, hashtagPattern)) ? "#00f7ff" : "#ff0000";
if (string.IsNullOrEmpty(friendCode) || friendCode == "")
friendCode = "???";
if (DataManager.Settings.Gameplay.StreamerMode == true)
friendCode = string.Concat('*').Repeat(friendCode.Length);
StringBuilder sbTag = new StringBuilder();
StringBuilder sbInfo = new StringBuilder();
// Put +++ at the end of each tag
if (player.IsDev() && !GameStates.IsInGamePlay)
sbTag.Append("<color=#6e6e6e>(<color=#0088ff>Dev</color>)</color>+++");
if (((player == PlayerControl.LocalPlayer && GameStates.IsHost && Main.BetterHost.Value) || player.GetIsBetterHost() == true) && !GameStates.IsInGamePlay)
sbTag.Append("<color=#0dff00>Better Host</color>+++");
else if ((player == PlayerControl.LocalPlayer || player.GetIsBetterUser() == true) && !GameStates.IsInGamePlay)
sbTag.Append("<color=#0dff00>Better User</color>+++");
if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.SickoData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.SickoData.ContainsValue(friendCode))
sbTag.Append("<color=#00f583>Sicko User</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.AUMData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.AUMData.ContainsValue(friendCode))
sbTag.Append("<color=#4f0000>AUM User</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.PlayerData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.PlayerData.ContainsValue(friendCode))
sbTag.Append("<color=#fc0000>Known Cheater</color>+++");
if (GameStates.IsLobby && !GameStates.IsFreePlay)
sbTag.Append($"<color=#b554ff>ID: {playerId}</color>+++");
for (int i = 0; i < sbTag.ToString().Split("+++").Length; i++)
{
if (!string.IsNullOrEmpty(sbTag.ToString().Split("+++")[i]))
{
if (i < sbTag.ToString().Split("+++").Length)
{
sbInfo.Append(sbTag.ToString().Split("+++")[i]);
}
if (i != sbTag.ToString().Split("+++").Length - 2)
{
sbInfo.Append(" - ");
}
}
}
PlayerControl Host = AmongUsClient.Instance.GetHost().Character;
if (player.IsHost() && GameStates.InGame && GameStates.IsLobby && !GameStates.IsFreePlay)
{
if (Main.LobbyPlayerInfo.Value == true)
{
NewName = player.GetPlayerNameAndColor();
}
}
if (player.IsImpostorTeammate() && player != PlayerControl.LocalPlayer)
{
NewName = $"<color=#ff1919>{player.Data.PlayerName}</color>";
}
if (!player.IsInShapeshift())
player.RawSetName(NewName);
if (!GameStates.IsVanillaServer)
{
friendCode = string.Empty;
Lv = string.Empty;
}
StringBuilder sbTag2 = new StringBuilder();
StringBuilder sbInfo2 = new StringBuilder();
// Put +++ at the end of each tag
sbTag2.Append($"<color=#9e9e9e>{Utils.GetPlatformName(player, useTag: true)}</color>"); // Don't put +++ here
sbTag2.Append($"{Lv}+++");
for (int i = 0; i < sbTag2.ToString().Split("+++").Length; i++)
{
if (!string.IsNullOrEmpty(sbTag2.ToString().Split("+++")[i]))
{
if (i < sbTag2.ToString().Split("+++").Length)
{
sbInfo2.Append(sbTag2.ToString().Split("+++")[i]);
}
if (i != sbTag2.ToString().Split("+++").Length - 2)
{
sbInfo2.Append(" - ");
}
}
}
if (GameStates.IsLobby && !GameStates.IsFreePlay)
{
if (Main.LobbyPlayerInfo.Value == true)
{
player.SetPlayerTextInfo($"{sbInfo}", isInfo: true);
player.SetPlayerTextInfo($"{sbInfo2}");
player.SetPlayerTextInfo($"<color={friendCodeColor}>{friendCode}</color>", isBottom: true);
}
else
if (!Main.LobbyPlayerInfo.Value && GameStates.IsLobby)
{
player.ResetAllPlayerTextInfo();
return;
}
}
else
{
string Role = $"<color={player.GetTeamHexColor()}>{player.GetRoleName()}</color>";
if (!player.IsImpostorTeammate())
if (Main.AllPlayerControls.Any(pc => player.Data.PlayerId == pc.shapeshiftTargetPlayerId))
return;
string NewName = player.Data.PlayerName;
string hashPuid = Utils.GetHashPuid(player);
string pattern = @"^[a-zA-Z0-9#]+$";
string hashtagPattern = @"^#[0-9]{4}$";
string friendCode = player.Data.FriendCode;
string friendCodeColor = (Regex.Replace(friendCode, hashtagPattern, string.Empty).Length is > 10 or < 5 || !Regex.IsMatch(friendCode, pattern) || !Regex.IsMatch(friendCode, hashtagPattern)) ? "#00f7ff" : "#ff0000";
if (string.IsNullOrEmpty(friendCode) || friendCode == "")
{
if (PlayerControl.LocalPlayer != null && PlayerControl.LocalPlayer.IsAlive() && player != PlayerControl.LocalPlayer)
friendCode = "???";
friendCodeColor = "#ff0000";
}
if (DataManager.Settings.Gameplay.StreamerMode == true)
friendCode = string.Concat('*').Repeat(friendCode.Length);
var sbTag = new StringBuilder();
var sbInfo = new StringBuilder();
var sbTagTop = new StringBuilder();
var sbInfoTop = new StringBuilder();
var sbTagBottom = new StringBuilder();
var sbInfoBottom = new StringBuilder();
// Put +++ at the end of each tag
if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.SickoData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.SickoData.ContainsValue(friendCode))
sbTag.Append("<color=#00f583>Sicko User</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.AUMData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.AUMData.ContainsValue(friendCode))
sbTag.Append("<color=#4f0000>AUM User</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.PlayerData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.PlayerData.ContainsValue(friendCode))
sbTag.Append("<color=#fc0000>Known Cheater</color>+++");
if (GameStates.IsInGame && GameStates.IsLobby && !GameStates.IsFreePlay)
{
if (player.IsHost())
{
if (!DebugMenu.RevealRoles)
if (Main.LobbyPlayerInfo.Value == true)
{
Role = "";
NewName = player.GetPlayerNameAndColor();
}
}
if (player.IsDev() && !GameStates.IsInGamePlay)
sbTag.Append("<color=#6e6e6e>(<color=#0088ff>Dev</color>)</color>+++");
if (((player == PlayerControl.LocalPlayer && GameStates.IsHost && Main.BetterHost.Value) || player.BetterData().IsBetterHost) && !GameStates.IsInGamePlay)
sbTag.Append("<color=#0dff00>Better Host</color>+++");
else if ((player == PlayerControl.LocalPlayer || player.BetterData().IsBetterUser) && !GameStates.IsInGamePlay)
sbTag.Append("<color=#0dff00>Better User</color>+++");
sbTag.Append($"<color=#b554ff>ID: {player.PlayerId}</color>+++");
sbTagTop.Append($"<color=#9e9e9e>{Utils.GetPlatformName(player, useTag: true)}</color>+++");
sbTagTop.Append($"<color=#ffd829>Lv: {player.Data.PlayerLevel.ToString()}</color>+++");
sbTagBottom.Append($"<color={friendCodeColor}>{friendCode}</color>+++");
}
else if (GameStates.IsInGame || GameStates.IsFreePlay)
{
if (player.IsImpostorTeammate() || player == PlayerControl.LocalPlayer || !PlayerControl.LocalPlayer.IsAlive() || DebugMenu.RevealRoles)
{
string Role = $"<color={player.GetTeamHexColor()}>{player.GetRoleName()}</color>";
sbTagTop.Append($"{Role}+++");
}
}
if (player.IsImpostorTeammate() && player != PlayerControl.LocalPlayer)
{
NewName = $"<color=#ff1919>{player.Data.PlayerName}</color>";
}
if (!player.IsInShapeshift())
{
player.RawSetName(NewName);
}
// Put +++ at the end of each tag
void AppendTagInfo(StringBuilder source, StringBuilder destination)
{
if (source.Length > 0)
{
string text = source.ToString();
string[] parts = text.Split("+++");
for (int i = 0; i < parts.Length; i++)
{
if (!string.IsNullOrEmpty(Utils.GetRawText(parts[i])))
{
destination.Append(parts[i]);
if (i != parts.Length - 2)
{
destination.Append(" - ");
}
}
}
}
}
player.SetPlayerTextInfo($"{sbInfo}", isInfo: true);
player.SetPlayerTextInfo($"{Role}");
player.SetPlayerTextInfo("", isBottom: true);
AppendTagInfo(sbTag, sbInfo);
AppendTagInfo(sbTagTop, sbInfoTop);
AppendTagInfo(sbTagBottom, sbInfoBottom);
player.SetPlayerTextInfo(sbInfoTop.ToString());
player.SetPlayerTextInfo(sbInfoBottom.ToString(), isBottom: true);
player.SetPlayerTextInfo(sbInfo.ToString(), isInfo: true);
} catch (Exception ex)
{
Logger.Error(ex.ToString());
}
}
[HarmonyPatch(nameof(PlayerControl.SetColor))]
[HarmonyPostfix]
public static void SetColor_Postfix()
{
if (Main.BetterHost.Value && GameStates.IsLobby)
{
_ = new LateTask(() =>
{
RPC.SyncAllNames(force: true);
}, 0.25f, shoudLog: false);
}
}
@@ -227,8 +229,6 @@ class PlayerControlPatch
if (PlayerControl.LocalPlayer.IsImpostorTeam() && GameStates.IsInGamePlay && !GameStates.IsHideNSeek && HudManager.Instance.CrewmatesKilled.isActiveAndEnabled)
HudManager.Instance?.NotifyOfDeath();
ExtendedPlayerInfo.TimeSinceKill[__instance] = 0f;
Logger.LogPrivate($"{__instance.Data.PlayerName} Has killed {target.Data.PlayerName} as {Utils.GetRoleName(__instance.Data.RoleType)}", "EventLog");
}
[HarmonyPatch(nameof(PlayerControl.Shapeshift))]
+63 -2
View File
@@ -26,6 +26,24 @@ public class RoleManagerPatch
int NumImpostors = GameOptionsManager.Instance.CurrentGameOptions.NumImpostors;
int NumPlayers = Main.AllPlayerControls.Length;
var impostorLimits = new Dictionary<int, int>
{
{ 3, 1 },
{ 5, 2 },
{ 6, 3 }
};
foreach (var limit in impostorLimits)
{
if (NumPlayers <= limit.Key)
{
NumImpostors = Math.Min(NumImpostors, limit.Value);
break;
}
}
List<PlayerControl> Impostors = [];
List<PlayerControl> Crewmates = [];
@@ -132,7 +150,7 @@ public class RoleManagerPatch
var impRoles = Shuffle(ImpostorRoles);
foreach (var kvp in impRoles)
{
if (RNG() < GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(kvp.Key) && kvp.Value > 0)
if (RNG() <= GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(kvp.Key) && kvp.Value > 0)
{
ImpostorMultiplier[Utils.GetHashPuid(pc)] += 15;
ImpostorRoles[kvp.Key]--;
@@ -158,7 +176,7 @@ public class RoleManagerPatch
var crewRoles = Shuffle(CrewmateRoles);
foreach (var kvp in crewRoles)
{
if (RNG() < GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(kvp.Key) && kvp.Value > 0)
if (RNG() <= GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(kvp.Key) && kvp.Value > 0)
{
ImpostorMultiplier[Utils.GetHashPuid(pc)] = 0;
CrewmateRoles[kvp.Key]--;
@@ -193,6 +211,49 @@ public class RoleManagerPatch
return false;
}
[HarmonyPatch(nameof(RoleManager.AssignRoleOnDeath))]
[HarmonyPrefix]
public static bool AssignRoleOnDeath_Prefix(/*RoleManager __instance*/ [HarmonyArgument(0)] PlayerControl player)
{
if (!Main.BetterRoleAlgorithma.Value) return true;
Dictionary<RoleTypes, int> GhostRoles = new() // Role, Amount
{
{ RoleTypes.GuardianAngel, 0 },
};
List<RoleTypes> Roles = [.. GhostRoles.Keys];
foreach (RoleTypes role in Roles)
{
GhostRoles[role] = GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetNumPerGame(role);
}
foreach (var allDeadPlayers in Main.AllPlayerControls.Where(pc => !pc.IsAlive()))
{
for (int i = 0; i < Roles.Count; i++)
{
if (allDeadPlayers.Is(Roles[i]))
{
GhostRoles[Roles[i]]--;
}
}
}
var ghostRoles = Shuffle(GhostRoles);
foreach (var kvp in ghostRoles)
{
if (kvp.Value > 0 && RNG() <= GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(kvp.Key))
{
player.RpcSetRole(kvp.Key);
break;
}
}
return false;
}
private static bool IsImpostorRole(RoleTypes role) => role is RoleTypes.Impostor or RoleTypes.Shapeshifter or RoleTypes.Phantom;
private static Dictionary<TKey, TValue> Shuffle<TKey, TValue>(Dictionary<TKey, TValue> dictionary)
+3 -2
View File
@@ -1,4 +1,5 @@
using HarmonyLib;
using Rewired;
namespace BetterAmongUs.Patches;
@@ -11,12 +12,12 @@ class RolePatch
[HarmonyPrefix]
public static bool NotifyOfDeath_Prefix(NoisemakerRole __instance)
{
if (ExtendedPlayerInfo.HasNoisemakerNotify.Contains(__instance.Player))
if (__instance.Player.BetterData().HasNoisemakerNotify)
{
return false;
}
ExtendedPlayerInfo.HasNoisemakerNotify.Add(__instance.Player);
__instance.Player.BetterData().HasNoisemakerNotify = true;
return true;
}
+5 -6
View File
@@ -2,7 +2,6 @@
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BetterAmongUs.Patches;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Innersloth.IO;
@@ -22,14 +21,14 @@ public enum ReleaseTypes : int
public class Main : BasePlugin
{
public const ReleaseTypes ReleaseBuildType = ReleaseTypes.Canary;
public const string CanaryNum = "5";
public const string HotfixNum = "3";
public const bool IsHotFix = true;
public const string CanaryNum = "6";
public const string HotfixNum = "0";
public const bool IsHotFix = false;
public const string PluginGuid = "com.d1gq.betteramongus";
public const string PluginVersion = "1.0.0";
public const string ReleaseDate = "08.01.2024"; // mm/dd/yyyy
public const string ReleaseDate = "08.08.2024"; // mm/dd/yyyy
public const string Github = "https://github.com/D1GQ/BetterAmongUs";
public const string Discord = "https://discord.gg/a3eVJHp9p5";
public const string Discord = "https://discord.gg/vjYrXpzNAn";
public static string GetVersionText(bool newLine = false)
{