Merge pull request #22 from D1GQ/dev

v1.0.3
This commit is contained in:
D1GQ authored and GitHub committed 2024-08-17 10:52:00 -05:00
commit 5c3266756a
22 files changed
+795 -125

No files matched your search

-3
View File
@@ -25,7 +25,4 @@
<!-- Embed all files in the Resources folder -->
<EmbeddedResource Include="Resources\**\*" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy &quot;$(TargetDir)BetterAmongUs.dll&quot; &quot;C:\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us - Mods\Among Us - BetterAmongUs\BepInEx\plugins&quot;" />
</Target>
</Project>
+59 -32
View File
@@ -3,6 +3,7 @@ using HarmonyLib;
using Hazel;
using InnerNet;
using UnityEngine;
using UnityEngine.Purchasing;
namespace BetterAmongUs;
@@ -194,7 +195,7 @@ class AntiCheat
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}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.IsAlive()} && {GameStates.IsInGamePlay} && {!GameStates.IsMeeting} && {!GameStates.IsExilling}");
}
return;
@@ -205,7 +206,7 @@ class AntiCheat
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}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.IsImpostorTeam()} && {Role != RoleTypes.Engineer} || {player.Data.IsDead}");
}
return;
@@ -233,8 +234,8 @@ class AntiCheat
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()}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {!player.IsImpostorTeam()} || {player.IsInVanish()}" +
$" || {!target.IsAlive()} || {target.IsImpostorTeam()}");
}
}
}
@@ -266,36 +267,31 @@ class AntiCheat
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;
}
if (callId is (byte)RpcCalls.UpdateSystem)
{
byte Type = reader.ReadByte();
if (Type is (byte)SystemTypes.Reactor
or (byte)SystemTypes.Laboratory
or (byte)SystemTypes.Comms
or (byte)SystemTypes.LifeSupp
or (byte)SystemTypes.MushroomMixupSabotage
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;
}
}
}
if (player.IsImpostorTeam())
if (callId is (byte)RpcCalls.CompleteTask)
{
if (callId is (byte)RpcCalls.CompleteTask or (byte)RpcCalls.BootFromVent)
var taskId = reader.ReadPackedUInt32();
if (player.IsImpostorTeam() || !player.Data.Tasks.ToArray().Any(task => task.Id == taskId)
|| player.BetterData().LastTaskId == taskId || player.BetterData().LastTaskId != taskId
&& player.BetterData().TimeSinceLastTask < 1.25f)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.IsImpostorTeam()}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {player.IsImpostorTeam()} || {!player.Data.Tasks.ToArray().Any(task => task.Id == taskId)} ||" +
$" {player.BetterData().LastTaskId == taskId} || {player.BetterData().LastTaskId != taskId} && {player.BetterData().TimeSinceLastTask < 1.25f}");
player.BetterData().TimeSinceLastTask = 0f;
player.BetterData().LastTaskId = taskId;
return;
}
player.BetterData().TimeSinceLastTask = 0f;
player.BetterData().LastTaskId = taskId;
}
if (callId is (byte)RpcCalls.Pet or (byte)RpcCalls.CancelPet)
@@ -309,12 +305,37 @@ class AntiCheat
return;
}
}
catch (Exception ex)
catch (Exception ex)
{
Logger.Error(ex.ToString());
}
}
// Check game states when sabotaging
public static bool RpcUpdateSystemCheck(PlayerControl player, SystemTypes systemType, byte amount)
{
if (!player.IsImpostorTeam() || !GameStates.IsSystemActive(systemType) && GameStates.IsAnySabotageActive() || Utils.SystemTypeIsSabotage(systemType)
|| ShipStatus.Instance.AllDoors.ToArray().Any(door => !door.IsOpen))
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName(systemType)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName(systemType)} Start Sabotage: {!player.IsImpostorTeam()} || {!GameStates.IsSystemActive(systemType)}" +
$"&& {GameStates.IsAnySabotageActive()} || {Utils.SystemTypeIsSabotage(systemType)} || {ShipStatus.Instance.AllDoors.ToArray().Any(door => !door.IsOpen)}");
return false;
}
// Fix Sabo
if (amount == 16)
{
if (!GameStates.IsSystemActive(systemType))
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName(systemType)}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName(systemType)} Fix Sabotage: {!GameStates.IsSystemActive(systemType)}");
}
}
return true;
}
// Check notify and cancel out request for invalid rpcs
public static bool CheckCancelRPC(PlayerControl player, byte callId, MessageReader Oldreader)
{
@@ -361,8 +382,8 @@ class AntiCheat
|| 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()}");
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)
{
@@ -382,7 +403,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}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {!UnityEngine.Object.FindAnyObjectByType<DeadBody>()} || {!deadPlayerInfo.IsDead} || {deadPlayerInfo == player.Data}");
if (GameStates.IsHost)
{
return false;
@@ -421,14 +442,14 @@ class AntiCheat
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()}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)} 1: {Role is not RoleTypes.Shapeshifter} || {!player.IsAlive()}");
return false;
}
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()}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)} 2: {!flag} && {!GameStates.IsMeeting} && {!GameStates.IsExilling} && {!player.IsInVent()}");
return false;
}
}
@@ -438,7 +459,7 @@ 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}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)} 1: {Role is not RoleTypes.Phantom} || {player.Data.IsDead}");
return false;
}
@@ -466,10 +487,16 @@ class AntiCheat
if (player.DataIsCollected() == true && !GameStates.IsLocalGame && GameStates.IsVanillaServer)
{
if (callId is (byte)RpcCalls.SetName or (byte)RpcCalls.CheckName or (byte)RpcCalls.SetLevel)
if (callId is (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}");
if (callId is (byte)RpcCalls.CheckName)
{
var name = reader.ReadString();
Logger.LogCheat($"{player.Data.PlayerName} Has tried to change their name to '{name}' but has been undone!");
}
return false;
}
}
@@ -519,7 +546,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}");
Logger.LogCheat($"{player.Data.PlayerName} {Enum.GetName((RpcCalls)callId)}: {GameStates.IsInGame} && {GameStates.IsLobby}");
return false;
}
}
+63 -4
View File
@@ -1,10 +1,15 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json;
namespace BetterAmongUs;
class BetterDataManager
{
private static string filePath = GetFilePath("BetterData");
public static string filePathFolder = Path.Combine(Main.GetGamePathToAmongUs(), $"Better_Data");
public static string filePathFolderSaveInfo = Path.Combine(filePathFolder, $"SaveInfo");
public static string banPlayerListFile = Path.Combine(filePathFolderSaveInfo, "BanPlayerList.txt");
public static string banNameListFile = Path.Combine(filePathFolderSaveInfo, "BanNameList.txt");
public static string GetFilePath(string name)
{
return Path.Combine(Main.GetDataPathToAmongUs(), $"{name}.json");
@@ -12,7 +17,25 @@ class BetterDataManager
public static void SetUp()
{
string filePath = GetFilePath("BetterData");
if (!Directory.Exists(filePathFolder))
{
Directory.CreateDirectory(filePathFolder);
}
if (!Directory.Exists(filePathFolderSaveInfo))
{
Directory.CreateDirectory(filePathFolderSaveInfo);
}
if (!File.Exists(banPlayerListFile))
{
File.WriteAllText(banPlayerListFile, "// Example\nFriendCode#0000\nHashPUID\n// Or\nFriendCode#0000, HashPUID");
}
if (!File.Exists(banNameListFile))
{
File.WriteAllText(banNameListFile, "// Example\nBanName1\nBanName2");
}
if (!File.Exists(filePath))
{
@@ -90,7 +113,7 @@ class BetterDataManager
return jsonData[category][name];
}
}
catch (Exception ex)
catch (Exception ex)
{
Logger.Error(ex.ToString());
}
@@ -98,6 +121,37 @@ class BetterDataManager
return string.Empty;
}
public static void SaveBanList(string friendCode = "", string hashPUID = "")
{
if (!string.IsNullOrEmpty(friendCode) || !string.IsNullOrEmpty(hashPUID))
{
// Create the new string with the separator if both are not empty
string newText = string.Empty;
if (!string.IsNullOrEmpty(friendCode))
{
newText = friendCode;
}
if (!string.IsNullOrEmpty(hashPUID))
{
if (!string.IsNullOrEmpty(newText))
{
newText += ", ";
}
newText += Utils.GetHashPuid(hashPUID);
}
// Check if the file already contains the new entry
if (!File.Exists(banPlayerListFile) || !File.ReadLines(banPlayerListFile).Any(line => line.Equals(newText)))
{
// Append the new string to the file if it's not already present
File.AppendAllText(banPlayerListFile, Environment.NewLine + newText);
}
}
}
public static void SaveCheatData(string puid, string friendCode, string name, string category = "cheatData", string reason = "None")
{
string filePath = GetFilePath("BetterData");
@@ -251,6 +305,11 @@ class BetterDataManager
Logger.LogCheat("Cleared cheat memory and data");
}
public static void LoadData()
{
LoadCheatData();
}
public static void LoadCheatData()
{
try
+16 -1
View File
@@ -1,8 +1,8 @@
using AmongUs.GameOptions;
using Hazel;
using InnerNet;
using UnityEngine;
using System.Text;
using UnityEngine;
namespace BetterAmongUs;
@@ -167,6 +167,17 @@ class BetterHostManager
}
break;
case (byte)RpcCalls.CompleteTask:
{
_ = new LateTask(() =>
{
RPC.SyncAllNames(force: true);
}, 1f, shoudLog: false);
shouldReturn = true;
}
break;
default:
shouldReturn = true;
break;
@@ -220,6 +231,10 @@ class BetterHostManager
else if (GameStates.IsInGamePlay)
{
string Role = $"<color={player.GetTeamHexColor()}>{player.GetRoleName()}</color>";
if (!player.IsImpostorTeam() && player.myTasks.Count > 0)
{
Role += $" <color=#cbcbcb>({player.Data.Tasks.ToArray().Where(task => task.Complete).Count()}/{player.Data.Tasks.Count})</color>";
}
if (player.IsImpostorTeam() is false || target.IsImpostorTeam() is false)
{
if (target.IsAlive() && player != target)
+5
View File
@@ -53,6 +53,11 @@ public class DebugMenu : MonoBehaviour
BetterDataManager.ClearCheatData();
});
AddButtonToTab(Main, "Send Better RPC", () =>
{
RPC.SendBetterCheck();
}, true);
AddButtonToTab(HostOnly, "Sync All Names", () =>
{
RPC.SyncAllNames();
+2 -2
View File
@@ -6,7 +6,7 @@ class Logger
public static void Log(string info, string tag = "Log")
{
string mark = $"{DateTime.Now:HH:mm} [BetterLog][{tag}]";
string logFilePath = Path.Combine(Environment.CurrentDirectory, "better-log.txt");
string logFilePath = Path.Combine(BetterDataManager.filePathFolder, "better-log.txt");
string newLine = $"{mark}: {info}";
File.AppendAllText(logFilePath, newLine + Environment.NewLine);
Main.Logger.LogInfo($"[{tag}] {info}");
@@ -34,7 +34,7 @@ class Logger
}
string mark = $"{DateTime.Now:HH:mm} [BetterLog][PrivateLog][{tag}]";
string logFilePath = Path.Combine(Environment.CurrentDirectory, "better-log.txt");
string logFilePath = Path.Combine(BetterDataManager.filePathFolder, "better-log.txt");
string newLine = $"{mark}: " + Encryptor.Encrypt($"{info}");
File.AppendAllText(logFilePath, newLine + Environment.NewLine);
}
+2 -3
View File
@@ -1,5 +1,4 @@
using AmongUs.GameOptions;
using Hazel;
using InnerNet;
using TMPro;
using UnityEngine;
@@ -103,7 +102,7 @@ static class ExtendedPlayerControl
// Kick player
public static void Kick(this PlayerControl player, bool ban = false, string setReasonInfo = "")
{
if (!GameStates.IsHost || !player.DataIsCollected() || player.IsHost() || player.BetterData().BannedByAntiCheat)
if (!GameStates.IsHost || PlayerControl.LocalPlayer == player || !player.DataIsCollected() || player.IsHost() || player.BetterData().BannedByAntiCheat || player.isDummy)
{
return;
}
@@ -164,7 +163,7 @@ static class ExtendedPlayerControl
// Check if player role name
public static string GetRoleName(this PlayerControl player)
{
if (!player.IsAlive() && !player.IsGhostRole() && Main.GetRoleName.TryGetValue((int)player.BetterData().DeadDisplayRole, out var roleName))
if (!player.IsAlive() && !player.IsGhostRole() && Main.GetRoleName.TryGetValue((int)player.BetterData().RoleInfo.DeadDisplayRole, out var roleName))
{
return roleName;
}
+35 -13
View File
@@ -10,35 +10,54 @@ public class ExtendedPlayerInfo
public bool IsBetterHost { get; set; } = false;
public bool IsTOHEHost { get; set; } = false;
public bool BannedByAntiCheat { get; set; } = false;
public bool HasNoisemakerNotify { get; set; } = false;
// Track Game Info
public float TimeSinceLastTask { get; set; } = 5f;
public uint LastTaskId { get; set; } = 0;
public int TimesCalledMeeting { get; set; } = 0;
public DisconnectReasons DisconnectReason { get; set; } = DisconnectReasons.Unknown;
public ExtendedRoleInfo? RoleInfo { get; set; }
}
public class ExtendedRoleInfo
{
public int Kills { get; set; } = 0;
public bool HasNoisemakerNotify { get; set; } = false;
public RoleTypes DeadDisplayRole { get; set; }
}
public static class PlayerControlExtensions
{
private static readonly Dictionary<NetworkedPlayerInfo, ExtendedPlayerInfo> playerInfo = [];
public static readonly Dictionary<string, ExtendedPlayerInfo> playerInfo = [];
// Get BetterData from PlayerControl
public static ExtendedPlayerInfo BetterData(this PlayerControl player)
public static ExtendedPlayerInfo? BetterData(this PlayerControl player)
{
if (!playerInfo.ContainsKey(player.Data))
if (player == null) return null;
if (!playerInfo.ContainsKey(player.Data.Puid))
{
playerInfo[player.Data] = new ExtendedPlayerInfo();
playerInfo[player.Data.Puid] = new ExtendedPlayerInfo
{
RoleInfo = new ExtendedRoleInfo()
};
}
return playerInfo[player.Data];
return playerInfo[player.Data.Puid];
}
// Get BetterData from NetworkedPlayerInfo
public static ExtendedPlayerInfo BetterData(this NetworkedPlayerInfo info)
public static ExtendedPlayerInfo? BetterData(this NetworkedPlayerInfo info)
{
if (!playerInfo.ContainsKey(info))
if (!playerInfo.ContainsKey(info.Puid))
{
playerInfo[info] = new ExtendedPlayerInfo();
playerInfo[info.Puid] = new ExtendedPlayerInfo
{
RoleInfo = new ExtendedRoleInfo()
};
}
return playerInfo[info];
return playerInfo[info.Puid];
}
// Get BetterData from ClientData
@@ -48,12 +67,15 @@ public static class PlayerControlExtensions
if (player != null)
{
if (!playerInfo.ContainsKey(player.Data))
if (!playerInfo.ContainsKey(player.Data.Puid))
{
playerInfo[player.Data] = new ExtendedPlayerInfo();
playerInfo[player.Data.Puid] = new ExtendedPlayerInfo
{
RoleInfo = new ExtendedRoleInfo()
};
}
return playerInfo[player.Data];
return playerInfo[player.Data.Puid];
}
return null;
+2 -2
View File
@@ -7,7 +7,7 @@ class FileChecker
{
private static bool Enabled = true;
private static readonly ReadOnlyCollection<string> UnsupportedBepInExMods = new(new List<string> { "TOHE", "YuAntiCheat" }); // Put BepInEx BepInPlugin name, not dll name here lol.
private static readonly ReadOnlyCollection<string> BannedBepInExMods = new(new List<string> { "MalumMenu", "MalumMenu-Yu", "MalumMenuYu", "AUnlocker" }); // Put BepInEx BepInPlugin name, not dll name here lol.
private static readonly ReadOnlyCollection<string> BannedBepInExMods = new(new List<string> { "MalumMenu", "MalumMenu-Yu", "MalumMenuYu"/*, "AUnlocker" */}); // Put BepInEx BepInPlugin name, not dll name here lol.
private static readonly ReadOnlyCollection<string> KeyWordsInVersionInfo = new(new List<string> { "Malum", "Sicko", "AUM" }); // Banned words for version text
public static string UnauthorizedReason = string.Empty;
public static List<string> CheatTags = []; // For API report
@@ -232,7 +232,7 @@ class FileChecker
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.FullName.Contains(modName))
if (assembly.FullName.Contains(modName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
+61 -1
View File
@@ -1,5 +1,4 @@
using AmongUs.GameOptions;
using BetterAmongUs.Patches;
namespace BetterAmongUs;
@@ -18,6 +17,67 @@ public static class GameStates
public static bool DleksIsActive => (MapNames)GameOptionsManager.Instance.CurrentGameOptions.MapId == MapNames.Dleks;
public static bool AirshipIsActive => (MapNames)GameOptionsManager.Instance.CurrentGameOptions.MapId == MapNames.Airship;
public static bool FungleIsActive => (MapNames)GameOptionsManager.Instance.CurrentGameOptions.MapId == MapNames.Fungle;
public static byte GetActiveMapId => GameOptionsManager.Instance.CurrentGameOptions.MapId;
public static bool IsSystemActive(SystemTypes type)
{
if (IsHideNSeek || !ShipStatus.Instance.Systems.TryGetValue(type, out var system))
{
return false;
}
int mapId = GetActiveMapId;
return type switch
{
SystemTypes.Electrical when mapId != 5 => system.Cast<SwitchSystem>()?.IsActive ?? false,
SystemTypes.Reactor when mapId != 2 => system.Cast<ReactorSystemType>()?.IsActive ?? false,
SystemTypes.Laboratory when mapId == 2 => system.Cast<ReactorSystemType>()?.IsActive ?? false,
SystemTypes.LifeSupp when mapId is 0 or 3 => system.Cast<LifeSuppSystemType>()?.IsActive ?? false,
SystemTypes.HeliSabotage when mapId == 4 => system.Cast<HeliSabotageSystem>()?.IsActive ?? false,
SystemTypes.Comms when mapId is 1 or 5 => system.Cast<HqHudSystemType>()?.IsActive ?? false,
SystemTypes.Comms => system.Cast<HudOverrideSystemType>()?.IsActive ?? false,
SystemTypes.MushroomMixupSabotage when mapId == 5 => system.Cast<MushroomMixupSabotageSystem>()?.IsActive ?? false,
_ => false
};
}
public static bool IsCriticalSabotageActive()
{
var deathSabotages = new[]
{
SystemTypes.Reactor,
SystemTypes.Laboratory,
SystemTypes.LifeSupp,
SystemTypes.HeliSabotage,
};
return deathSabotages.Any(IsSystemActive);
}
public static bool IsNoneCriticalSabotageActive()
{
var noneDeathSabotages = new[]
{
SystemTypes.Electrical,
SystemTypes.Comms,
SystemTypes.MushroomMixupSabotage
};
return noneDeathSabotages.Any(IsSystemActive);
}
public static bool IsAnySabotageActive()
{
var allSabotages = new[]
{
SystemTypes.Electrical,
SystemTypes.Reactor,
SystemTypes.Laboratory,
SystemTypes.LifeSupp,
SystemTypes.HeliSabotage,
SystemTypes.Comms,
SystemTypes.MushroomMixupSabotage
};
return allSabotages.Any(IsSystemActive);
}
public static bool IsInGame => InGame;
public static bool IsLobby => AmongUsClient.Instance?.GameState == InnerNet.InnerNetClient.GameStates.Joined;
public static bool IsInIntro => IntroCutscene.Instance != null;
+33 -4
View File
@@ -1,6 +1,7 @@
using BetterAmongUs.Patches;
using HarmonyLib;
using Hazel;
using InnerNet;
namespace BetterAmongUs;
@@ -55,14 +56,42 @@ internal class RPCHandlerPatch
{
RPC.HandleCustomRPC(__instance, callId, reader);
}
}
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(MessageReader))]
public static class MessageReaderUpdateSystemPatch
{
public static bool Prefix(/*ShipStatus __instance,*/ [HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
{
if (GameStates.IsHideNSeek) return false;
var amount = MessageReader.Get(reader).ReadByte();
if (AntiCheat.RpcUpdateSystemCheck(player, systemType, amount) != true)
{
Logger.LogCheat($"RPC canceled by Anti-Cheat: {Enum.GetName(typeof(SystemTypes), (int)systemType)} - {amount}");
return false;
}
return true;
}
}
internal static class RPC
{
public static void SendBetterCheck()
{
var flag = GameStates.IsHost && Main.BetterHost.Value;
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.BetterCheck, SendOption.None, -1);
messageWriter.Write(true);
messageWriter.Write(flag);
messageWriter.Write(Main.GetVersionText().Replace(" ", ""));
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
}
public static void SetNamePrivate(PlayerControl player, string name, PlayerControl target)
{
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(player.NetId, (byte)RpcCalls.SetName, SendOption.Reliable, target.GetClientId());
writer.Write(player.NetId);
writer.Write(player.Data.NetId);
writer.Write(name);
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
@@ -138,17 +167,17 @@ internal static class RPC
switch (callId)
{
case (byte)CustomRPC.BetterCheck:
if (reader.ReadByte() == player.Data.NetId)
{
var SetBetterUser = reader.ReadBoolean();
var IsBetterHost = reader.ReadBoolean();
if (!player.IsHost() && IsBetterHost)
{
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((RpcCalls)callId)} called as BetterHost");
BetterNotificationManager.NotifyCheat(player, $"Invalid Action RPC: {Enum.GetName((CustomRPC)callId)} called as BetterHost");
break;
}
player.BetterData().IsBetterUser = true;
player.BetterData().IsBetterUser = SetBetterUser;
player.BetterData().IsBetterHost = IsBetterHost;
}
break;
+24
View File
@@ -63,6 +63,18 @@ public static class Utils
throw;
}
}
public static bool SystemTypeIsSabotage(SystemTypes type) => type is SystemTypes.Reactor
or SystemTypes.Laboratory
or SystemTypes.Comms
or SystemTypes.LifeSupp
or SystemTypes.MushroomMixupSabotage
or SystemTypes.HeliSabotage;
public static bool SystemTypeIsSabotage(int typeNum) => (SystemTypes)typeNum is SystemTypes.Reactor
or SystemTypes.Laboratory
or SystemTypes.Comms
or SystemTypes.LifeSupp
or SystemTypes.MushroomMixupSabotage
or SystemTypes.HeliSabotage;
// Get players HashPuid
public static string GetHashPuid(PlayerControl player)
{
@@ -94,6 +106,18 @@ public static class Utils
}
// Get name for role
public static string GetRoleName(RoleTypes role) => Main.GetRoleName[(int)role];
// Get hex color for team
public static string GetTeamHexColor(RoleTeamTypes team)
{
if (team == RoleTeamTypes.Impostor)
{
return "#f00202";
}
else
{
return "#8cffff";
}
}
public static string Color32ToHex(Color32 color) => $"#{color.r:X2}{color.g:X2}{color.b:X2}{255:X2}";
// Disconnect client
public static void DisconnectSelf(string reason, bool showReason = true)
+3 -9
View File
@@ -1,5 +1,4 @@
using HarmonyLib;
using Hazel;
using UnityEngine;
namespace BetterAmongUs.Patches;
@@ -52,12 +51,7 @@ public static class OptionsMenuBehaviourPatch
BetterHost = ClientOptionItem.Create("<color=#4f92ff>Better Host</color>", Main.BetterHost, __instance, BetterHostButtonToggle, () => !toggleCheckInGamePlay("<color=#4f92ff>Better Host</color>"));
static void BetterHostButtonToggle()
{
var flag = GameStates.IsHost && Main.BetterHost.Value;
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, unchecked((byte)CustomRPC.BetterCheck), SendOption.None, -1);
messageWriter.Write((byte)PlayerControl.LocalPlayer.NetId);
messageWriter.Write(flag);
messageWriter.Write(Main.GetVersionText().Replace(" ", ""));
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
RPC.SendBetterCheck();
RPC.SyncAllNames(force: true);
}
@@ -66,8 +60,8 @@ public static class OptionsMenuBehaviourPatch
if (BetterRoleAlgorithma == null || BetterRoleAlgorithma.ToggleButton == null)
{
BetterRoleAlgorithma = ClientOptionItem.Create("<color=#4f92ff>Better Role Algorithma</color>", Main.BetterRoleAlgorithma, __instance, toggleCheck: () => !toggleCheckInGamePlay("<color=#4f92ff>Better Role Algorithma</color>"));
}
}
if (BetterNotifications == null || BetterNotifications.ToggleButton == null)
{
BetterNotifications = ClientOptionItem.Create("<color=#4f92ff>Better Notifications</color>", Main.BetterNotifications, __instance, BetterNotificationsToggle);
+10 -1
View File
@@ -73,6 +73,16 @@ public class ClientPatch
__result = GameStates.IsHost || (GameStates.IsInGamePlay && (GameStates.IsMeeting || GameStates.IsExilling));
return false;
}
[HarmonyPatch(nameof(InnerNetClient.KickPlayer))]
[HarmonyPrefix]
public static void KickPlayer_Prefix(ref int clientId, ref bool ban)
{
if (ban)
{
NetworkedPlayerInfo info = Utils.PlayerFromClientId(clientId).Data;
BetterDataManager.SaveBanList(info.FriendCode, info.Puid);
}
}
}
// Set text color
[HarmonyPatch(typeof(CosmeticsLayer))]
@@ -146,7 +156,6 @@ public class ClientPatch
string extractedText = playerName.Split(new[] { "<color=#ffea00>", "</color>" }, StringSplitOptions.None)[1];
playerName = extractedText;
}
}
}
}
+1 -1
View File
@@ -107,7 +107,7 @@ class CommandsPatch
case "dump":
if (GameStates.IsInGamePlay && !GameStates.IsDev) return;
string logFilePath = Path.Combine(Environment.CurrentDirectory, "better-log.txt");
string logFilePath = Path.Combine(BetterDataManager.filePathFolder, "better-log.txt");
string log = File.ReadAllText(logFilePath);
string newLog = string.Empty;
string[] logArray = log.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
+219 -4
View File
@@ -1,5 +1,8 @@
using HarmonyLib;
using Hazel;
using Newtonsoft.Json.Utilities;
using System.Text;
using TMPro;
using UnityEngine;
namespace BetterAmongUs.Patches;
@@ -16,6 +19,23 @@ class GamePlayManager
{
AntiCheat.PauseAntiCheat();
}
// Clear unused Better Data
var keysToRemove = new List<string>();
foreach (var betterInfo in PlayerControlExtensions.playerInfo)
{
if (!Main.AllPlayerControls.Any(pc => pc.Data.Puid == betterInfo.Key))
{
keysToRemove.Add(betterInfo.Key);
}
}
foreach (var key in keysToRemove)
{
PlayerControlExtensions.playerInfo.Remove(key);
}
}
[HarmonyPatch(nameof(LobbyBehaviour.Start))]
[HarmonyPostfix]
@@ -26,6 +46,7 @@ class GamePlayManager
if (GameStates.IsInGame)
{
RPC.SyncAllNames(force: true);
RPC.SendBetterCheck();
}
}, 1.5f, "LobbyBehaviourPatch SyncAllNames");
}
@@ -62,12 +83,206 @@ class GamePlayManager
{
[HarmonyPatch(nameof(GameStartManager.Update))]
[HarmonyPrefix]
private static void Prefix(GameStartManager __instance)
private static void Update_Prefix(GameStartManager __instance)
{
if (GameStates.IsDev)
__instance.MinPlayers = 1;
}
[HarmonyPatch(nameof(GameStartManager.Update))]
[HarmonyPostfix]
private static void Update_Postfix(GameStartManager __instance)
{
if (!GameStates.IsHost)
{
__instance.MinPlayers = 1;
__instance.StartButton.gameObject.SetActive(false);
return;
}
__instance.GameStartTextParent.SetActive(false);
__instance.StartButton.gameObject.SetActive(true);
if (__instance.startState == GameStartManager.StartingStates.Countdown)
{
__instance.StartButton.buttonText.text = string.Format("Cancel: {0}", (int)__instance.countDownTimer + 1);
}
else
{
__instance.StartButton.buttonText.text = "Start Game";
}
}
[HarmonyPatch(nameof(GameStartManager.BeginGame))]
[HarmonyPrefix]
private static bool BeginGame_Prefix(GameStartManager __instance)
{
if (__instance.startState == GameStartManager.StartingStates.Countdown)
{
SoundManager.instance.StopSound(__instance.gameStartSound);
__instance.ResetStartState();
return false;
}
if (Input.GetKey(KeyCode.LeftShift))
{
__instance.startState = GameStartManager.StartingStates.Countdown;
__instance.FinallyBegin();
return false;
}
return true;
}
}
[HarmonyPatch(typeof(EndGameManager))]
public class EndGameManagerPatch
{
[HarmonyPatch(nameof(EndGameManager.SetEverythingUp))]
[HarmonyPostfix]
private static void SetEverythingUp_Postfix(EndGameManager __instance)
{
GameObject SummaryObj = UnityEngine.Object.Instantiate(__instance.WinText.gameObject, __instance.WinText.transform.parent.transform);
SummaryObj.name = "SummaryObj (TMP)";
SummaryObj.transform.SetSiblingIndex(0);
Camera localCamera;
if (DestroyableSingleton<HudManager>.InstanceExists)
{
localCamera = DestroyableSingleton<HudManager>.Instance.GetComponentInChildren<Camera>();
}
else
{
localCamera = Camera.main;
}
SummaryObj.transform.position = AspectPosition.ComputeWorldPosition(localCamera, AspectPosition.EdgeAlignments.LeftTop, new Vector3(1f, 0.2f, -5f));
SummaryObj.transform.localScale = new Vector3(0.22f, 0.22f, 0.22f);
TextMeshPro SummaryText = SummaryObj.GetComponent<TextMeshPro>();
if (SummaryText != null)
{
SummaryText.autoSizeTextContainer = false;
SummaryText.enableAutoSizing = false;
SummaryText.lineSpacing = -25f;
SummaryText.alignment = TextAlignmentOptions.TopLeft;
SummaryText.color = Color.white;
NetworkedPlayerInfo[] playersData = GameData.Instance.AllPlayers
.ToArray()
.OrderBy(pd => pd.Disconnected) // Disconnected players last
.ThenBy(pd => pd.IsDead)
.ThenBy(pd => !pd.Role.IsImpostor)
.ToArray(); // Dead players after live players
string winTeam;
string winTag;
string winColor;
switch (EndGameResult.CachedGameOverReason)
{
case GameOverReason.HumansByTask:
winTeam = "Cremates";
winTag = "Tasks Completion";
winColor = "#8cffff";
break;
case GameOverReason.HumansByVote:
winTeam = "Cremates";
winTag = "Imposters Voted Out";
winColor = "#8cffff";
break;
case GameOverReason.ImpostorDisconnect:
winTeam = "Cremates";
winTag = "Impostors Disconnected";
winColor = "#8cffff";
break;
case GameOverReason.ImpostorByKill:
winTeam = "Imposters";
winTag = "Crew Outnumbered";
winColor = "#f00202";
break;
case GameOverReason.ImpostorBySabotage:
winTeam = "Imposters";
winTag = "Sabotage";
winColor = "#f00202";
break;
case GameOverReason.ImpostorByVote:
winTeam = "Imposters";
winTag = "Crew Outnumbered";
winColor = "#f00202";
break;
case GameOverReason.HumansDisconnect:
winTeam = "Imposters";
winTag = "Cremates Disconnected";
winColor = "#f00202";
break;
// H&S
case GameOverReason.HideAndSeek_ByTimer:
winTeam = "Hiders";
winTag = "Time Out";
winColor = "#8cffff";
break;
case GameOverReason.HideAndSeek_ByKills:
winTeam = "Seekers";
winTag = "No Survivors";
winColor = "#f00202";
break;
default:
winTeam = "Unknown";
winTag = "Unknown";
winColor = "#ffffff";
break;
}
string SummaryHeader = "<align=\"center\"><size=150%> Game Summary</size></align>";
SummaryHeader += $"\n\n<size=90%><color={winColor}>{winTeam} Won</color></size>" +
$"\n<size=60%>\nBy {winTag}</size>";
StringBuilder sb = new StringBuilder();
foreach (var data in playersData)
{
var name = $"<color={Utils.Color32ToHex(Palette.PlayerColors[data.DefaultOutfit.ColorId])}>{data.PlayerName}</color>";
string playerTheme(string text) => $"<color={Utils.GetTeamHexColor(data.Role.TeamType)}>{text}</color>";
string roleInfo;
if (data.Role.IsImpostor)
{
roleInfo = $"({playerTheme(Utils.GetRoleName(data.RoleType))}) → {playerTheme($"Kills: {data.BetterData().RoleInfo.Kills}")}";
}
else
{
roleInfo = $"({playerTheme(Utils.GetRoleName(data.RoleType))}) → {playerTheme($"Tasks: {data.Tasks.ToArray().Where(task => task.Complete).Count()}/{data.Tasks.Count}")}";
}
string deathReason;
if (data.Disconnected)
{
deathReason = "『<color=#838383><b>D/C</b></color>』";
}
else if (!data.IsDead)
{
deathReason = "『<color=#80ff00><b>Alive</b></color>』";
;
}
else if (data.IsDead)
{
deathReason = "『<color=#ff0600><b>Dead</b></color>』";
}
else
{
deathReason = "『<color=#838383<b>Unknown</b></color>』";
}
sb.AppendLine($"- {name} {roleInfo} {deathReason}\n");
}
SummaryText.text = $"{SummaryHeader}\n\n<size=58%>{sb}</size>";
}
}
[HarmonyPatch(nameof(EndGameManager.ShowButtons))]
[HarmonyPrefix]
private static bool ShowButtons_Prefix(EndGameManager __instance)
{
__instance.FrontMost.gameObject.SetActive(false);
__instance.Navigation.ShowDefaultNavigation();
return false;
}
}
}
+33 -2
View File
@@ -1,5 +1,4 @@
using HarmonyLib;
using Hazel;
using System.Text;
using TMPro;
using UnityEngine;
@@ -77,7 +76,35 @@ class MeetingHudUpdatePatch
if (!flag)
{
SetPlayerTextInfoMeeting(pva, "<color=#6b6b6b>Disconnected</color>", isInfo: true);
string DisconnectText;
var playerData = GameData.Instance.GetPlayerById(pva.TargetPlayerId);
switch (playerData.BetterData().DisconnectReason)
{
case DisconnectReasons.ExitGame:
DisconnectText = "Left The Game";
break;
case DisconnectReasons.Banned:
if (playerData.BetterData().BannedByAntiCheat)
{
DisconnectText = "Banned By Anti-Cheat>";
}
else
{
DisconnectText = "Banned By Host";
}
break;
case DisconnectReasons.Kicked:
DisconnectText = "Kicked By Host";
break;
case DisconnectReasons.Hacking:
DisconnectText = "Banned By Server";
break;
default:
DisconnectText = "Disconnected";
break;
}
SetPlayerTextInfoMeeting(pva, $"<color=#6b6b6b>{DisconnectText}</color>", isInfo: true);
SetPlayerTextInfoMeeting(pva, "");
pva.transform.Find("votePlayerBase").gameObject.SetActive(false);
pva.transform.Find("deadX_border").gameObject.SetActive(false);
@@ -120,6 +147,10 @@ class MeetingHudUpdatePatch
string RoleHexColor = target.IsImpostorTeam() ? "#ff1919" : "#8cffff";
string Role = $"<color={RoleHexColor}>{target.GetRoleName()}</color>";
if (!target.IsImpostorTeam() && target.myTasks.Count > 0)
{
Role += $" <color=#cbcbcb>({target.myTasks.ToArray().Where(task => task.IsComplete).Count()}/{target.myTasks.Count})</color>";
}
if (!target.IsImpostorTeammate())
{
if (PlayerControl.LocalPlayer.IsAlive() && target != PlayerControl.LocalPlayer)
+34 -11
View File
@@ -71,7 +71,14 @@ class PlayerControlPatch
if (!GameStates.IsInGamePlay)
{
__instance.BetterData().TimesCalledMeeting = 0;
__instance.BetterData().HasNoisemakerNotify = false;
__instance.BetterData().RoleInfo.HasNoisemakerNotify = false;
__instance.BetterData().TimeSinceLastTask = 5f;
__instance.BetterData().LastTaskId = 999;
__instance.BetterData().RoleInfo.Kills = 0;
}
else
{
__instance.BetterData().TimeSinceLastTask += Time.deltaTime;
}
}
@@ -103,6 +110,8 @@ class PlayerControlPatch
string NewName = player.Data.PlayerName;
string hashPuid = Utils.GetHashPuid(player);
string platform = Utils.GetPlatformName(player, useTag: true);
string pattern = @"^[a-zA-Z0-9#]+$";
string hashtagPattern = @"^#[0-9]{4}$";
string friendCode = player.Data.FriendCode;
@@ -112,11 +121,14 @@ class PlayerControlPatch
|| friendCode.Contains(' ')) ? "#00f7ff" : "#ff0000";
if (string.IsNullOrEmpty(friendCode) || friendCode == "")
{
friendCode = "???";
friendCode = "No Friend Code";
friendCodeColor = "#ff0000";
}
if (DataManager.Settings.Gameplay.StreamerMode == true)
{
friendCode = string.Concat('*').Repeat(friendCode.Length);
platform = "Platform Hidden";
}
var sbTag = new StringBuilder();
var sbInfo = new StringBuilder();
@@ -126,12 +138,15 @@ class PlayerControlPatch
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 (!player.isDummy)
{
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)
{
@@ -145,13 +160,14 @@ class PlayerControlPatch
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)
if (((player == PlayerControl.LocalPlayer && GameStates.IsHost && Main.BetterHost.Value)
|| (player != PlayerControl.LocalPlayer && player.BetterData().IsBetterHost && player.IsHost())) && !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=#9e9e9e>{platform}</color>+++");
sbTagTop.Append($"<color=#ffd829>Lv: {player.Data.PlayerLevel.ToString()}</color>+++");
@@ -162,6 +178,10 @@ class PlayerControlPatch
if (player.IsImpostorTeammate() || player == PlayerControl.LocalPlayer || !PlayerControl.LocalPlayer.IsAlive() || DebugMenu.RevealRoles)
{
string Role = $"<color={player.GetTeamHexColor()}>{player.GetRoleName()}</color>";
if (!player.IsImpostorTeam() && player.myTasks.Count > 0)
{
Role += $" <color=#cbcbcb>({player.Data.Tasks.ToArray().Where(task => task.Complete).Count()}/{player.Data.Tasks.Count})</color>";
}
sbTagTop.Append($"{Role}+++");
}
}
@@ -204,7 +224,8 @@ class PlayerControlPatch
player.SetPlayerTextInfo(sbInfoTop.ToString());
player.SetPlayerTextInfo(sbInfoBottom.ToString(), isBottom: true);
player.SetPlayerTextInfo(sbInfo.ToString(), isInfo: true);
} catch (Exception ex)
}
catch (Exception ex)
{
Logger.Error(ex.ToString());
}
@@ -234,6 +255,8 @@ class PlayerControlPatch
HudManager.Instance?.NotifyOfDeath();
Logger.LogPrivate($"{__instance.Data.PlayerName} Has killed {target.Data.PlayerName} as {Utils.GetRoleName(__instance.Data.RoleType)}", "EventLog");
__instance.BetterData().RoleInfo.Kills += 1;
}
[HarmonyPatch(nameof(PlayerControl.Shapeshift))]
[HarmonyPostfix]
+58 -22
View File
@@ -1,6 +1,5 @@
using BetterAmongUs.Patches;
using HarmonyLib;
using Hazel;
using InnerNet;
namespace BetterAmongUs;
@@ -12,6 +11,8 @@ class OnGameJoinedPatch
{
try
{
PlayerControlExtensions.playerInfo.Clear();
PlayerControlPatch.infotime = 0f;
AntiCheat.PauseAntiCheat();
@@ -24,20 +25,6 @@ class OnGameJoinedPatch
host.SetColor(host.CurrentOutfit.ColorId);
}
_ = new LateTask(() =>
{
// Send Better Among Us Check RPC
if (GameStates.IsInGame)
{
var flag = GameStates.IsHost && Main.BetterHost.Value;
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.BetterCheck, SendOption.None, -1);
messageWriter.Write((byte)PlayerControl.LocalPlayer.NetId);
messageWriter.Write(flag);
messageWriter.Write(Main.GetVersionText().Replace(" ", ""));
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
}
}, 1.5f, "OnGameJoinedPatch");
Logger.Log($"Successfully joined {GameCode.IntToGameName(AmongUsClient.Instance.GameId)}", "OnGameJoinedPatch");
}
catch { };
@@ -55,17 +42,54 @@ public static class OnPlayerJoinedPatch
if (GameStates.IsInGame)
{
// Send Better Among Us Check RPC
var flag = GameStates.IsHost && Main.BetterHost.Value;
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, unchecked((byte)CustomRPC.BetterCheck), SendOption.None, -1);
messageWriter.Write((byte)PlayerControl.LocalPlayer.NetId);
messageWriter.Write(flag);
messageWriter.Write(Main.GetVersionText().Replace(" ", ""));
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
RPC.SendBetterCheck();
RPC.SyncAllNames(force: true);
if (Main.BetterHost.Value)
client.Character.RpcSendHostChat(HudManagerPatch.WelcomeMessage, sendToBetterUser: false);
// Auto ban player on ban list
var player = Utils.PlayerFromClientId(client.Id);
if (player != null)
{
string banPlayerListContent = File.ReadAllText(BetterDataManager.banPlayerListFile);
string[] listPlayerArray = banPlayerListContent.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
foreach (string text in listPlayerArray)
{
if (!string.IsNullOrEmpty(player.Data.FriendCode) && text.Contains(player.Data.FriendCode)
|| !string.IsNullOrEmpty(Utils.GetHashPuid(player)) && text.Contains(Utils.GetHashPuid(player)))
{
player.Kick(true, $"{player.Data.PlayerName} has been banned due to being on the ban player list!");
break;
}
}
// Normalize and remove spaces and special characters from names
Func<string, string> normalizeName = name => new string(name.Where(c => char.IsLetterOrDigit(c)).ToArray()).ToLower();
// Read all banned names into a HashSet with normalized names
HashSet<string> bannedNames = new HashSet<string>(
File.ReadLines(BetterDataManager.banNameListFile)
.Select(normalizeName)
.Where(name => !string.IsNullOrWhiteSpace(name))
);
string normalizedPlayerName = normalizeName(player.Data.PlayerName);
// Check if any banned name is a prefix of the player's normalized name
bool isNameBanned = bannedNames.Any(bannedName =>
normalizedPlayerName.StartsWith(bannedName)
);
if (!string.IsNullOrEmpty(normalizedPlayerName) && isNameBanned)
{
player.Kick(false, $"{player.Data.PlayerName} has been kicked due to their name being on the ban name list!");
}
}
}
}, 2.5f, "OnPlayerJoinedPatch", false);
}
@@ -79,11 +103,23 @@ class OnPlayerLeftPatch
HudManager.Instance?.NotifyOfDisconnect(data.Character);
}
}
[HarmonyPatch(typeof(GameData))]
[HarmonyPatch("HandleDisconnect")]
[HarmonyPatch(MethodType.Normal)]
[HarmonyPatch(new Type[] { typeof(PlayerControl), typeof(DisconnectReasons) })]
class GameDataHandleDisconnectPatch
{
public static void Prefix(/*GameData __instance,*/ [HarmonyArgument(0)] PlayerControl player, [HarmonyArgument(1)] DisconnectReasons reason)
{
player.BetterData().DisconnectReason = reason;
}
}
[HarmonyPatch(typeof(GameData), nameof(GameData.ShowNotification))]
class GameDataShowNotificationPatch
{
public static bool Prefix(AmongUsClient __instance, ref string playerName, ref DisconnectReasons reason)
public static bool Prefix(/*GameData __instance,*/ ref string playerName, ref DisconnectReasons reason)
{
string ReasonText;
switch (reason)
+128 -2
View File
@@ -23,6 +23,20 @@ public class RoleManagerPatch
{
if (!Main.BetterRoleAlgorithma.Value) return true;
if (!GameStates.IsHideNSeek)
{
RegularBetterRoleAssignment();
}
else
{
HideAndSeekBetterRoleAssignment();
}
return false;
}
public static void RegularBetterRoleAssignment()
{
Logger.LogHeader($"Better Role Assignment Has Started", "RoleManager");
// Set roles up
@@ -245,8 +259,118 @@ public class RoleManagerPatch
}, 1f, "RoleManager SyncAllNames");
Logger.LogHeader($"Better Role Assignment Has Finished", "RoleManager");
}
return false;
public static void HideAndSeekBetterRoleAssignment()
{
Logger.LogHeader($"Better Role Assignment Has Started", "RoleManager");
foreach (var addplayer in Main.AllPlayerControls.Where(pc => !ImpostorMultiplier.ContainsKey(Utils.GetHashPuid(pc))))
ImpostorMultiplier[Utils.GetHashPuid(addplayer)] = 0;
int NumImpostors = 1;
int NumPlayers = Main.AllPlayerControls.Length;
List<PlayerControl> Impostors = [];
List<PlayerControl> Crewmates = [];
// Set imp from settings
int SetImpostor = GameOptionsManager.Instance.currentHideNSeekGameOptions.ImpostorPlayerID;
if (SetImpostor >= 0)
{
var player = Utils.PlayerFromId(SetImpostor);
if (player != null)
{
Impostors.Add(player);
player.RpcSetRole(RoleTypes.Impostor);
player.roleAssigned = true;
Logger.Log($"Settings Assigned {Utils.GetRoleName(RoleTypes.Impostor)} role to {player.Data.PlayerName}", "RoleManager");
}
}
// Override player role assignment
if (SetPlayerRole.Keys.Any())
{
foreach (var kvp in SetPlayerRole.Where(kvp => kvp.Key != null).OrderBy(kvp => kvp.Key == PlayerControl.LocalPlayer ? 0 : 1))
{
var player = kvp.Key;
var role = kvp.Value;
if (role is RoleTypes.Impostor)
{
if (Impostors.Count < NumImpostors)
{
Impostors.Add(player);
player.RpcSetRole(RoleTypes.Impostor);
player.roleAssigned = true;
Logger.Log($"Override Assigned {Utils.GetRoleName(RoleTypes.Impostor)} role to {player.Data.PlayerName}", "RoleManager");
}
else continue;
}
else if (role is RoleTypes.Engineer)
{
Crewmates.Add(player);
player.RpcSetRole(RoleTypes.Engineer);
player.roleAssigned = true;
Logger.Log($"Override Assigned {Utils.GetRoleName(RoleTypes.Engineer)} role to {player.Data.PlayerName}", "RoleManager");
}
}
}
// Get players in random order
List<PlayerControl> players = Main.AllPlayerControls
.Where(player => !Impostors.Contains(player) && !Crewmates.Contains(player) && player.roleAssigned == false)
.ToList();
int n = players.Count;
while (n > 1)
{
n--;
int k = random.Next(n + 1);
PlayerControl value = players[k];
players[k] = players[n];
players[n] = value;
}
// Assign roles
foreach (PlayerControl pc in players)
{
if (pc == null || pc.roleAssigned == true) continue;
if (Impostors.Count < NumImpostors && RNG() > ImpostorMultiplier[Utils.GetHashPuid(pc)])
{
if (!Impostors.Contains(pc))
{
ImpostorMultiplier[Utils.GetHashPuid(pc)] += 15;
Impostors.Add(pc);
pc.RpcSetRole(RoleTypes.Impostor);
pc.roleAssigned = true;
Logger.Log($"Assigned {Utils.GetRoleName(RoleTypes.Impostor)} role to {pc.Data.PlayerName}", "RoleManager");
}
}
else
{
if (!Crewmates.Contains(pc))
{
ImpostorMultiplier[Utils.GetHashPuid(pc)] = 0;
Crewmates.Add(pc);
pc.RpcSetRole(RoleTypes.Engineer);
pc.roleAssigned = true;
Logger.Log($"Assigned {Utils.GetRoleName(RoleTypes.Engineer)} role to {pc.Data.PlayerName}", "RoleManager");
}
}
}
SetPlayerRole.Clear();
_ = new LateTask(() =>
{
RPC.SyncAllNames(false, true, Main.BetterHost.Value);
}, 1f, "RoleManager SyncAllNames");
Logger.LogHeader($"Better Role Assignment Has Finished", "RoleManager");
}
[HarmonyPatch(nameof(RoleManager.AssignRoleOnDeath))]
@@ -254,7 +378,7 @@ public class RoleManagerPatch
public static bool AssignRoleOnDeath_Prefix(/*RoleManager __instance*/ [HarmonyArgument(0)] PlayerControl player)
{
if (player.Data.RoleType != RoleTypes.CrewmateGhost && player.Data.RoleType != RoleTypes.ImpostorGhost)
player.BetterData().DeadDisplayRole = player.Data.RoleType;
player.BetterData().RoleInfo.DeadDisplayRole = player.Data.RoleType;
if (!Main.BetterRoleAlgorithma.Value) return true;
@@ -285,6 +409,8 @@ public class RoleManagerPatch
foreach (var kvp in ghostRoles)
{
if (player.IsImpostorTeam() && kvp.Key is RoleTypes.GuardianAngel) continue;
if (kvp.Value > 0 && RNG() <= GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(kvp.Key))
{
player.RpcSetRole(kvp.Key);
+2 -3
View File
@@ -1,5 +1,4 @@
using HarmonyLib;
using Rewired;
namespace BetterAmongUs.Patches;
@@ -12,12 +11,12 @@ class RolePatch
[HarmonyPrefix]
public static bool NotifyOfDeath_Prefix(NoisemakerRole __instance)
{
if (__instance.Player.BetterData().HasNoisemakerNotify)
if (__instance.Player.BetterData().RoleInfo.HasNoisemakerNotify)
{
return false;
}
__instance.Player.BetterData().HasNoisemakerNotify = true;
__instance.Player.BetterData().RoleInfo.HasNoisemakerNotify = true;
return true;
}
+5 -5
View File
@@ -28,7 +28,7 @@ public class Main : BasePlugin
public const bool IsHotFix = false;
public const string PluginGuid = "com.d1gq.betteramongus";
public const string PluginVersion = "1.0.2";
public const string ReleaseDate = "08.15.2024"; // mm/dd/yyyy
public const string ReleaseDate = "08.16.2024"; // mm/dd/yyyy
public const string Github = "https://github.com/D1GQ/BetterAmongUs-Public";
public const string Discord = "https://discord.gg/vjYrXpzNAn";
@@ -125,16 +125,16 @@ public class Main : BasePlugin
Harmony.PatchAll();
BetterDataManager.SetUp();
BetterDataManager.LoadCheatData();
BetterDataManager.LoadData();
LoadOptions();
if (File.Exists(Path.Combine($"{Environment.CurrentDirectory}/Among Us_Data/Plugins/x86", "steam_api.dll")))
File.WriteAllText(Path.Combine(Environment.CurrentDirectory, "steam_appid.txt"), "945360");
if (File.Exists(Path.Combine(Environment.CurrentDirectory, "better-log.txt")))
File.WriteAllText(Path.Combine(Environment.CurrentDirectory, "better-previous-log.txt"), File.ReadAllText(Path.Combine(Environment.CurrentDirectory, "better-log.txt")));
if (File.Exists(Path.Combine(BetterDataManager.filePathFolder, "better-log.txt")))
File.WriteAllText(Path.Combine(BetterDataManager.filePathFolder, "better-previous-log.txt"), File.ReadAllText(Path.Combine(BetterDataManager.filePathFolder, "better-log.txt")));
File.WriteAllText(Path.Combine(Environment.CurrentDirectory, "better-log.txt"), "");
File.WriteAllText(Path.Combine(BetterDataManager.filePathFolder, "better-log.txt"), "");
BetterAmongUs.Logger.Log("Better Among Us successfully loaded!");
// Set up debug menu