mirror of
https://github.com/D1GQ/BetterAmongUs.git
synced 2026-10-20 01:46:19 +00:00
add DisableSabotagesForDead and remove private only lobbies
This commit is contained in:
1 parent
919a82648f
commit
13a5564c04
8 files changed
+87
-191
No files matched your search
@@ -73,11 +73,6 @@ internal static class BAUConfigs
|
||||
/// </summary>
|
||||
internal static BAUConfigEntry<string> CommandPrefix { get; } = new("Mod", "CommandPrefix", "/");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration entry for private only lobby setting.
|
||||
/// </summary>
|
||||
internal static BAUConfigEntry<bool> PrivateOnlyLobby { get; } = new("Mod", "PrivateOnlyLobby", false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration entry for favorite color setting.
|
||||
/// </summary>
|
||||
@@ -94,10 +89,10 @@ internal static class BAUConfigs
|
||||
internal static void LoadConfigs()
|
||||
{
|
||||
BAUModdedSupportEvents.InvokeAll_OnBAUConfigEntriesLoaded([
|
||||
PrivateOnlyLobby, AntiCheat, SendBetterRpc,
|
||||
BetterNotifications, ForceOwnLanguage, ChatDarkMode,
|
||||
ChatInGameplay, LobbyPlayerInfo, DisableLobbyTheme,
|
||||
UnlockFPS, ShowFPS, MinimapIcons, VentColorGroups, CommandPrefix,
|
||||
AntiCheat, SendBetterRpc, BetterNotifications,
|
||||
ForceOwnLanguage, ChatDarkMode, ChatInGameplay, LobbyPlayerInfo,
|
||||
DisableLobbyTheme, UnlockFPS, ShowFPS,
|
||||
MinimapIcons, VentColorGroups, CommandPrefix,
|
||||
FavoriteColor, SettingsPreset
|
||||
]);
|
||||
|
||||
|
||||
@@ -462,7 +462,18 @@ internal static class NetworkManager
|
||||
|
||||
BetterAntiCheat.HandleCheatRPCBeforeCheck(player, callId, reader);
|
||||
|
||||
if (BetterAntiCheat.CheckCancelRPC(player, callId, reader) != true)
|
||||
if (GameState.IsHost)
|
||||
{
|
||||
var tempReader = MessageReader.Get(reader);
|
||||
if (RPCHandler.HandleRPC(callId, player, tempReader, HandlerFlag.BetterHost) == false)
|
||||
{
|
||||
tempReader.Recycle();
|
||||
return false;
|
||||
}
|
||||
tempReader.Recycle();
|
||||
}
|
||||
|
||||
if (BetterAntiCheat.CheckCancelRPC(player, callId, reader) == false)
|
||||
{
|
||||
if (!player.IsLocalPlayer()) Logger_.LogCheat($"RPC canceled by Anti-Cheat: {Enum.GetName((RpcCalls)callId)}{Enum.GetName((CustomRPC)callId)} - {callId}");
|
||||
return false;
|
||||
@@ -474,10 +485,32 @@ internal static class NetworkManager
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(MessageReader))]
|
||||
|
||||
[HarmonyPatch]
|
||||
internal static class MessageReaderUpdateSystemPatch
|
||||
{
|
||||
internal static bool Prefix([HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
|
||||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(byte))]
|
||||
[HarmonyPrefix]
|
||||
internal static bool ShipStatus_UpdateSystemLocal_Prefix(SystemTypes systemType, PlayerControl player, byte amount)
|
||||
{
|
||||
MessageWriter messageWriter = MessageWriter.Get(0);
|
||||
messageWriter.Write(amount);
|
||||
MessageReader messageReader = MessageReader.Get(messageWriter.ToByteArray(false));
|
||||
messageWriter.Recycle();
|
||||
|
||||
if (BetterAntiCheat.RpcUpdateSystemCheck(player, systemType, messageReader) != true)
|
||||
{
|
||||
messageReader.Recycle();
|
||||
return false;
|
||||
}
|
||||
messageReader.Recycle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(MessageReader))]
|
||||
[HarmonyPrefix]
|
||||
internal static bool ShipStatus_UpdateSystem_Prefix(SystemTypes systemType, PlayerControl player, MessageReader msgReader)
|
||||
{
|
||||
player.BetterData().AntiCheatInfo.RPCSentPS++;
|
||||
if (player.BetterData().AntiCheatInfo.RPCSentPS >= ExtendedAntiCheatInfo.MAX_RPC_SENT)
|
||||
@@ -485,7 +518,7 @@ internal static class NetworkManager
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BetterAntiCheat.RpcUpdateSystemCheck(player, systemType, reader) != true) return false;
|
||||
if (BetterAntiCheat.RpcUpdateSystemCheck(player, systemType, msgReader) != true) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -266,24 +266,24 @@ internal static class BetterAntiCheat
|
||||
/// <returns>True if the sabotage should be allowed, false otherwise.</returns>
|
||||
internal static bool RpcUpdateSystemCheck(PlayerControl player, SystemTypes systemType, MessageReader oldReader)
|
||||
{
|
||||
if (Utils.SystemTypeIsSabotage(systemType) || systemType is SystemTypes.Doors)
|
||||
{
|
||||
if (GameState.IsPrivateOnlyLobby && BetterGameSettings.DisableSabotages.GetBool()) return false;
|
||||
}
|
||||
|
||||
MessageReader reader = MessageReader.Get(oldReader);
|
||||
|
||||
RegisterRPCHandlerAttribute.GetClassInstance<UpdateSystemHandler>().CatchedSystemType = systemType;
|
||||
bool notCanceled = RPCHandler.HandleRPC((byte)RpcCalls.UpdateSystem, player, reader, HandlerFlag.AntiCheatCancel);
|
||||
if (!notCanceled)
|
||||
if (!RPCHandler.HandleRPC((byte)RpcCalls.UpdateSystem, player, reader, HandlerFlag.AntiCheatCancel))
|
||||
{
|
||||
var tempReader = MessageReader.Get(reader);
|
||||
Logger_.LogCheat($"RPC canceled by Anti-Cheat: {Enum.GetName(typeof(SystemTypes), (int)systemType)} - {tempReader.ReadByte()}");
|
||||
tempReader.Recycle();
|
||||
reader.Recycle();
|
||||
return false;
|
||||
}
|
||||
|
||||
reader.Recycle();
|
||||
return notCanceled;
|
||||
|
||||
MessageReader reader2 = MessageReader.Get(oldReader);
|
||||
if (!RPCHandler.HandleRPC((byte)RpcCalls.UpdateSystem, player, reader2, HandlerFlag.BetterHost))
|
||||
{
|
||||
reader2.Recycle();
|
||||
return false;
|
||||
}
|
||||
reader2.Recycle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BetterAmongUs.Attributes;
|
||||
using BetterAmongUs.Helpers;
|
||||
using BetterAmongUs.Patches.Gameplay.UI.Settings;
|
||||
using Hazel;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -51,9 +52,8 @@ internal sealed class UpdateSystemHandler : RPCHandler
|
||||
|
||||
internal override bool HandleAntiCheatCancel(PlayerControl? sender, MessageReader reader)
|
||||
{
|
||||
if (GameState.IsHost && sender.IsHost()) return true;
|
||||
if (sender.IsHost()) return true;
|
||||
|
||||
MessageReader oldReader = MessageReader.Get(reader);
|
||||
byte count = reader.ReadByte();
|
||||
|
||||
if (ShipStatus.Instance.Systems.TryGetValue(CatchedSystemType, out ISystemType system))
|
||||
@@ -62,12 +62,31 @@ internal sealed class UpdateSystemHandler : RPCHandler
|
||||
|
||||
if (systemHandlers.TryGetValue(systemKey, out var handler))
|
||||
{
|
||||
oldReader.Recycle();
|
||||
return handler.Invoke(sender, system, oldReader, count);
|
||||
return handler.Invoke(sender, system, reader, count);
|
||||
}
|
||||
}
|
||||
|
||||
oldReader.Recycle();
|
||||
return true;
|
||||
}
|
||||
|
||||
internal override bool BetterHandle(PlayerControl? sender, MessageReader reader)
|
||||
{
|
||||
// Prevent dead impostors from sabotaging if setting is enabled
|
||||
if (CatchedSystemType is SystemTypes.Sabotage or SystemTypes.Electrical or SystemTypes.LifeSupp or
|
||||
SystemTypes.Reactor or SystemTypes.Laboratory or SystemTypes.HeliSabotage or
|
||||
SystemTypes.Comms or SystemTypes.MushroomMixupSabotage)
|
||||
{
|
||||
if (BetterGameSettings.DisableSabotages.GetBool())
|
||||
return false;
|
||||
|
||||
if (BetterGameSettings.DisableSabotagesForDead.GetBool())
|
||||
{
|
||||
if (!sender.IsAlive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using AmongUs.GameOptions;
|
||||
using BetterAmongUs.Data.Config;
|
||||
|
||||
namespace BetterAmongUs.Modules;
|
||||
|
||||
@@ -321,12 +320,6 @@ internal static class GameState
|
||||
/// </summary>
|
||||
internal static bool IsHost => AmongUsClient.Instance != null && AmongUsClient.Instance.AmHost;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the lobby is private-only (requires specific settings).
|
||||
/// </summary>
|
||||
internal static bool IsPrivateOnlyLobby => (BAUConfigs.PrivateOnlyLobby.Value ||
|
||||
(AmongUsClient.Instance != null && AmongUsClient.Instance.AmLocalHost)) && IsHost;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the local player can move.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
using BetterAmongUs.Data.Config;
|
||||
using BetterAmongUs.Helpers;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.Modules.Support;
|
||||
using HarmonyLib;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BetterAmongUs.Patches.Client;
|
||||
|
||||
[HarmonyPatch]
|
||||
internal static class PrivateLobbyPatch
|
||||
{
|
||||
private static GameObject? toggle;
|
||||
private static readonly List<PassiveButton>? buttons = [];
|
||||
private static TextMeshPro? toggleText;
|
||||
|
||||
[HarmonyPatch(typeof(CreateGameOptions), nameof(CreateGameOptions.Show))]
|
||||
[HarmonyPostfix]
|
||||
private static void CreateGameOptions_Show_Postfix(CreateGameOptions __instance)
|
||||
{
|
||||
// Check if other mods have disabled private lobby feature
|
||||
if (BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_PrivateLobby))
|
||||
{
|
||||
BAUConfigs.PrivateOnlyLobby.Value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only create toggle UI once
|
||||
if (toggle != null)
|
||||
return;
|
||||
|
||||
buttons.Clear();
|
||||
|
||||
// Clone April Fools toggle as template for private lobby toggle
|
||||
toggle = UnityEngine.Object.Instantiate(__instance.AprilFoolsToggle, __instance.contentObjects.First().transform.parent);
|
||||
if (toggle != null)
|
||||
{
|
||||
toggle.name = "PrivateOnlyLobby";
|
||||
|
||||
// Get the ON and OFF buttons from the toggle
|
||||
buttons.Add(toggle.transform.Find("AprilOn").GetComponent<PassiveButton>());
|
||||
buttons.Add(toggle.transform.Find("AprilOff").GetComponent<PassiveButton>());
|
||||
if (buttons.Count < 2)
|
||||
return;
|
||||
|
||||
toggle.gameObject.SetActive(true);
|
||||
|
||||
// Set up ON button click handler
|
||||
var onButton = buttons[0];
|
||||
if (onButton != null)
|
||||
{
|
||||
onButton.gameObject.SetActive(false);
|
||||
onButton.OnClick = new();
|
||||
onButton.OnClick.AddListener(() => TogglePrivateOnlyLobby(true));
|
||||
}
|
||||
|
||||
// Set up OFF button click handler
|
||||
var offButton = buttons[1];
|
||||
if (offButton != null)
|
||||
{
|
||||
offButton.gameObject.SetActive(false);
|
||||
offButton.OnClick = new();
|
||||
offButton.OnClick.AddListener(() => TogglePrivateOnlyLobby(false));
|
||||
}
|
||||
|
||||
// Position toggle at top-right of create game screen
|
||||
var aspect = toggle.gameObject.AddComponent<AspectPosition>();
|
||||
aspect.Alignment = AspectPosition.EdgeAlignments.Top;
|
||||
aspect.DistanceFromEdge = new Vector3(0.4f, 1.62f, 0);
|
||||
aspect.AdjustPosition();
|
||||
|
||||
// Update toggle text label
|
||||
var modeText = toggle.transform.Find("BlackSquare/ModeText");
|
||||
if (modeText != null)
|
||||
{
|
||||
var text = modeText.GetComponent<TextMeshPro>();
|
||||
if (text != null)
|
||||
{
|
||||
text.DestroyTextTranslators();
|
||||
text.text = "Private Only Lobby";
|
||||
toggleText = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize toggle state from saved configuration
|
||||
TogglePrivateOnlyLobby(BAUConfigs.PrivateOnlyLobby.Value);
|
||||
}
|
||||
|
||||
private static void TogglePrivateOnlyLobby(bool modeOn)
|
||||
{
|
||||
if (buttons.Count < 2)
|
||||
return;
|
||||
|
||||
// Show both buttons first
|
||||
buttons[0].gameObject.SetActive(true);
|
||||
buttons[1].gameObject.SetActive(true);
|
||||
|
||||
// Deselect both buttons
|
||||
buttons[0].SelectButton(false);
|
||||
buttons[1].SelectButton(false);
|
||||
|
||||
// Select appropriate button based on mode
|
||||
if (modeOn)
|
||||
{
|
||||
buttons[0].SelectButton(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
buttons[1].SelectButton(true);
|
||||
}
|
||||
|
||||
// Save setting to configuration
|
||||
BAUConfigs.PrivateOnlyLobby.Value = modeOn;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(LobbyInfoPane), nameof(LobbyInfoPane.Update))]
|
||||
[HarmonyPostfix]
|
||||
private static void LobbyInfoPane_Update_Postfix(LobbyInfoPane __instance)
|
||||
{
|
||||
// Enforce private lobby setting if enabled by host
|
||||
if (BAUConfigs.PrivateOnlyLobby.Value && !GameState.IsLocalGame && GameState.IsHost)
|
||||
{
|
||||
// Ensure game stays private
|
||||
if (AmongUsClient.Instance.IsGamePublic)
|
||||
{
|
||||
AmongUsClient.Instance.ChangeGamePublic(false);
|
||||
}
|
||||
|
||||
// Disable and visually indicate that public lobby button is locked
|
||||
var button = __instance.HostPrivateButton.GetComponent<PassiveButton>();
|
||||
if (button != null)
|
||||
{
|
||||
button.enabled = false;
|
||||
|
||||
// Change inactive sprite to cyan color to indicate locked state
|
||||
var inactive = __instance.HostPrivateButton.transform.Find("Inactive");
|
||||
if (inactive != null)
|
||||
{
|
||||
var sprite = inactive.GetComponent<SpriteRenderer>();
|
||||
if (sprite != null)
|
||||
{
|
||||
sprite.color = new Color(0.35f, 1f, 1f, 1f); // Corrected colour assignment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,11 @@ internal sealed class BetterGameSettings
|
||||
internal static OptionIntItem? KickLevelBelow;
|
||||
internal static OptionCheckboxItem? DetectCheatClients;
|
||||
internal static OptionCheckboxItem? DetectInvalidRPCs;
|
||||
|
||||
internal static OptionStringItem? RoleRandomizer;
|
||||
internal static OptionCheckboxItem? DesyncRoles;
|
||||
internal static OptionCheckboxItem? DisableSabotagesForDead;
|
||||
|
||||
internal static OptionCheckboxItem? CancelInvalidSabotage;
|
||||
internal static OptionCheckboxItem? CensorDetectionReason;
|
||||
internal static OptionCheckboxItem? DisableSabotages;
|
||||
@@ -92,17 +95,19 @@ internal static class GameSettingsPatch
|
||||
|
||||
// Gameplay Settings section
|
||||
{
|
||||
// Show only for hosts in private lobbies
|
||||
if (IsPreload || GameState.IsHost && GameState.IsPrivateOnlyLobby)
|
||||
// Show only for hosts
|
||||
if (IsPreload || GameState.IsHost)
|
||||
{
|
||||
// Normal game mode settings
|
||||
if (IsPreload || !GameState.IsHideNSeek)
|
||||
{
|
||||
OptionHeaderItem.Create(BetterSettingsTab, "BetterSetting.MainHeader.Gameplay");
|
||||
BetterGameSettings.DisableSabotages = OptionCheckboxItem.Create(1500, BetterSettingsTab, "BetterSetting.Setting.DisableSabotages", false);
|
||||
BetterGameSettings.DisableSabotagesForDead = OptionCheckboxItem.Create(1600, BetterSettingsTab, "BetterSetting.Setting.DisableSabotagesForDead", false);
|
||||
}
|
||||
|
||||
// Hide & Seek specific settings with dynamic impostor selection
|
||||
else if (IsPreload || GameState.IsHideNSeek)
|
||||
if (IsPreload || GameState.IsHideNSeek)
|
||||
{
|
||||
OptionHeaderItem.Create(BetterSettingsTab, "BetterSetting.MainHeader.HideNSeek");
|
||||
OptionTitleItem.Create(BetterSettingsTab, $"<color={RoleTypes.Impostor.GetRoleHex()}>{Translator.GetString(StringNames.ImpostorsCategory)}</color>");
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
"BetterSetting.Setting.DetectInvalidRPCs": "Detect invalid RPCs",
|
||||
"BetterSetting.Setting.RoleRandomizer": "Randomizer",
|
||||
"BetterSetting.Setting.DesyncRoles": "Desync roles to other clients",
|
||||
"BetterSetting.Setting.DisableSabotagesForDead": "Disable sabotages for dead",
|
||||
"BetterSetting.Setting.DisableSabotages": "Disable sabotages",
|
||||
"BetterSetting.Setting.RemovePetOnDeath": "Remove pet on death",
|
||||
"BetterSetting.Setting.HideAndSeekImpNum": "# Seekers",
|
||||
|
||||
Reference in new issue
Block a user