mirror of
https://github.com/D1GQ/BetterAmongUs.git
synced 2026-10-19 15:51:52 +00:00
22 files changed
+795
-125
No files matched your search
@@ -25,7 +25,4 @@
|
||||
<!-- Embed all files in the Resources folder -->
|
||||
<EmbeddedResource Include="Resources\**\*" />
|
||||
</ItemGroup>
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="copy "$(TargetDir)BetterAmongUs.dll" "C:\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us - Mods\Among Us - BetterAmongUs\BepInEx\plugins"" />
|
||||
</Target>
|
||||
</Project>
|
||||
+59
-32
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user