Add outfit presets

This commit is contained in:
D1GQ committed 2025-10-20 22:01:23 -05:00
1 parent 161a65556f
commit a26655f08f
19 files changed
+297 -45

No files matched your search

+3 -1
View File
@@ -3,11 +3,12 @@ using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BetterAmongUs.Data;
using BetterAmongUs.Data.Json;
using BetterAmongUs.Helpers;
using BetterAmongUs.Items;
using BetterAmongUs.Items.Attributes;
using BetterAmongUs.Modules;
using BetterAmongUs.Network;
using BetterAmongUs.Network.Configs;
using BetterAmongUs.Patches.Gameplay.UI.Settings;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
@@ -100,6 +101,7 @@ internal class BAUPlugin : BasePlugin
GameSettingMenuPatch.SetupSettings(true);
FileChecker.Initialize();
InstanceAttribute.RegisterAll();
OutfitData.Init();
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")));
+1 -1
View File
@@ -12,7 +12,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.10.14" PrivateAssets="all" />
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.10.14" />
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+2 -1
View File
@@ -1,4 +1,5 @@
using BetterAmongUs.Helpers;
using BetterAmongUs.Data.Json;
using BetterAmongUs.Helpers;
namespace BetterAmongUs.Data;
@@ -2,7 +2,7 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data;
namespace BetterAmongUs.Data.Json;
internal abstract class AbstractJsonFile
{
@@ -22,10 +22,14 @@ internal abstract class AbstractJsonFile
if (_hasInit) return;
_hasInit = true;
if (!CheckFile() || !Load())
if (!CheckFile())
{
Save();
return;
}
Load();
Save();
}
protected virtual bool Load()
@@ -1,7 +1,7 @@
using BetterAmongUs.Items.Structs;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data;
namespace BetterAmongUs.Data.Json;
internal sealed class BetterDataFile : AbstractJsonFile
{
@@ -12,6 +12,7 @@ internal sealed class BetterDataFile : AbstractJsonFile
var success = base.Load();
if (success)
{
SelectedOutfitPreset = Math.Clamp(SelectedOutfitPreset, 0, 5);
AllCheatData = [.. CheatData, .. SickoData, .. AUMData, .. KNData];
}
return success;
@@ -41,6 +42,12 @@ internal sealed class BetterDataFile : AbstractJsonFile
internal HashSet<UserInfo> AllCheatData { get; set; } = [];
[JsonPropertyName("selectedOutfitPreset")]
public int SelectedOutfitPreset { get; set; } = 0;
[JsonPropertyName("outfitData")]
public HashSet<OutfitData> OutfitData { get; set; } = [new(), new(), new(), new(), new(), new()];
[JsonPropertyName("cheatData")]
public HashSet<UserInfo> CheatData { get; set; } = [];
@@ -3,7 +3,7 @@ using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data;
namespace BetterAmongUs.Data.Json;
internal sealed class BetterGameSettingsFile : AbstractJsonFile
{
+97
View File
@@ -0,0 +1,97 @@
using AmongUs.Data;
namespace BetterAmongUs.Data.Json;
[Serializable]
internal class OutfitData
{
public string HatId = HatData.EmptyId;
public string PetId = PetData.EmptyId;
public string SkinId = SkinData.EmptyId;
public string VisorId = VisorData.EmptyId;
public string NamePlateId = NamePlateData.EmptyId;
internal static OutfitData GetOutfitData() => BetterDataManager.BetterDataFile.OutfitData.ElementAt(BetterDataManager.BetterDataFile.SelectedOutfitPreset);
internal static OutfitData GetOutfitData(int index) => BetterDataManager.BetterDataFile.OutfitData.ElementAt(index);
private static bool ignoreChange;
internal static void Init()
{
FindPreset();
var Save = () =>
{
if (ignoreChange) return;
GetOutfitData().LoadToData();
BetterDataManager.BetterDataFile.Save();
};
DataManager.Player.Customization.OnHatChanged += Save;
DataManager.Player.Customization.OnPetChanged += Save;
DataManager.Player.Customization.OnSkinChanged += Save;
DataManager.Player.Customization.OnVisorChanged += Save;
DataManager.Player.Customization.OnNamePlateChanged += Save;
}
internal static void FindPreset()
{
var collection = BetterDataManager.BetterDataFile.OutfitData;
int i = 0;
foreach (var data in collection)
{
if (data.HatId == DataManager.Player.Customization.Hat &&
data.PetId == DataManager.Player.Customization.Pet &&
data.SkinId == DataManager.Player.Customization.Skin &&
data.VisorId == DataManager.Player.Customization.Visor &&
data.NamePlateId == DataManager.Player.Customization.NamePlate)
{
BetterDataManager.BetterDataFile.SelectedOutfitPreset = i;
BetterDataManager.BetterDataFile.Save();
return;
}
i++;
}
BetterDataManager.BetterDataFile.SelectedOutfitPreset = 0;
BetterDataManager.BetterDataFile.Save();
}
private void Validate()
{
if (!HatManager.Instance.GetUnlockedHats().Any(item => item.ProductId == HatId))
HatId = HatData.EmptyId;
if (!HatManager.Instance.GetUnlockedPets().Any(item => item.ProductId == PetId))
PetId = PetData.EmptyId;
if (!HatManager.Instance.GetUnlockedSkins().Any(item => item.ProductId == SkinId))
SkinId = SkinData.EmptyId;
if (!HatManager.Instance.GetUnlockedVisors().Any(item => item.ProductId == VisorId))
VisorId = VisorData.EmptyId;
if (!HatManager.Instance.GetUnlockedNamePlates().Any(item => item.ProductId == NamePlateId))
NamePlateId = NamePlateData.EmptyId;
}
internal void Load(Action callback)
{
Validate();
ignoreChange = true;
DataManager.Player.Customization.Hat = HatId;
DataManager.Player.Customization.Pet = PetId;
DataManager.Player.Customization.Skin = SkinId;
DataManager.Player.Customization.Visor = VisorId;
DataManager.Player.Customization.NamePlate = NamePlateId;
ignoreChange = false;
callback.Invoke();
BetterDataManager.BetterDataFile.Save();
}
internal void LoadToData()
{
HatId = DataManager.Player.Customization.Hat;
PetId = DataManager.Player.Customization.Pet;
SkinId = DataManager.Player.Customization.Skin;
VisorId = DataManager.Player.Customization.Visor;
NamePlateId = DataManager.Player.Customization.NamePlate;
}
}
+4 -1
View File
@@ -1,7 +1,10 @@
namespace BetterAmongUs.Data.Replay.Events;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
public interface IReplayEvent
{
[JsonIgnore]
string Id { get; }
void Play();
}
+1 -1
View File
@@ -7,7 +7,7 @@ internal class Replay
{
public int MapId;
public List<PlayerReplayData> PlayerData = [];
public (float timeStamp, IReplayEvent) Events;
public Dictionary<float, List<IReplayEvent>> Events = [];
public void Load()
{
+1 -1
View File
@@ -1,7 +1,7 @@
using AmongUs.GameOptions;
using BetterAmongUs.Items;
using BetterAmongUs.Managers;
using BetterAmongUs.Modules;
using BetterAmongUs.Network.Configs;
using Il2CppInterop.Runtime.Attributes;
using InnerNet;
using UnityEngine;
+12
View File
@@ -102,4 +102,16 @@ internal static class ObjectHelper
color ??= Color.green;
sprite.color = (sprite.color * 0.6f) + ((Color)color * 0.5f);
}
internal static void SetLayers(this GameObject go, string layerName)
{
int layer = LayerMask.NameToLayer(layerName);
if (layer == -1) return;
Transform[] allChildren = go.GetComponentsInChildren<Transform>(true);
foreach (Transform child in allChildren)
{
child.gameObject.layer = layer;
}
}
}
+1 -1
View File
@@ -3,10 +3,10 @@ using Il2CppInterop.Runtime.Attributes;
using System.Collections;
using System.Text.Json;
using BetterAmongUs.Helpers;
using BetterAmongUs.Items;
using UnityEngine;
using UnityEngine.Networking;
using System.Reflection;
using BetterAmongUs.Network.Configs;
namespace BetterAmongUs.Modules;
@@ -1,7 +1,7 @@
using BetterAmongUs.Helpers;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Items;
namespace BetterAmongUs.Network.Configs;
[method: JsonConstructor]
internal class BannedUserData(string name = "", string puid = "", string friendCode = "", string reason = "")
@@ -30,7 +30,7 @@ internal class BannedUserData(string name = "", string puid = "", string friendC
if (EOSManager.Instance)
{
var data = AllBannedUsers?.FirstOrDefault(user => user.Puid == Utils.GetHashStr(EOSManager.Instance.ProductUserId) || user.FriendCode == Utils.GetHashStr(EOSManager.Instance.FriendCode));
var data = AllBannedUsers?.FirstOrDefault(user => user.Puid == EOSManager.Instance.ProductUserId.GetHashStr() || user.FriendCode == EOSManager.Instance.FriendCode.GetHashStr());
if (data != null)
{
bannedData = data;
@@ -43,6 +43,6 @@ internal class BannedUserData(string name = "", string puid = "", string friendC
return false;
}
internal static bool CheckPlayerBan(NetworkedPlayerInfo data) => AllBannedUsers?.FirstOrDefault(user => user.Puid == data.GetHashPuid() || user.FriendCode == data.GetHashFriendcode()) != null;
internal static bool CheckPuidBan(string puid) => AllBannedUsers?.FirstOrDefault(user => user.Puid == Utils.GetHashStr(puid)) != null;
internal static bool CheckFriendCodeBan(string friendcode) => AllBannedUsers?.FirstOrDefault(user => user.FriendCode == Utils.GetHashStr(friendcode)) != null;
internal static bool CheckPuidBan(string puid) => AllBannedUsers?.FirstOrDefault(user => user.Puid == puid.GetHashStr()) != null;
internal static bool CheckFriendCodeBan(string friendcode) => AllBannedUsers?.FirstOrDefault(user => user.FriendCode == friendcode.GetHashStr()) != null;
}
@@ -1,7 +1,7 @@
using BetterAmongUs.Helpers;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Items;
namespace BetterAmongUs.Network.Configs;
[Flags]
internal enum MultiPermissionFlags : ushort
@@ -47,7 +47,7 @@ internal class UserData(string name = "", string puid = "", string friendCode =
{
if (EOSManager.Instance)
{
var data = AllUsers?.FirstOrDefault(user => user.Puid == Utils.GetHashStr(EOSManager.Instance.ProductUserId) || user.FriendCode == Utils.GetHashStr(EOSManager.Instance.FriendCode));
var data = AllUsers?.FirstOrDefault(user => user.Puid == EOSManager.Instance.ProductUserId.GetHashStr() || user.FriendCode == EOSManager.Instance.FriendCode.GetHashStr());
if (data != null)
{
Logger.Log($"Found local UserData({data.Name})");
@@ -62,8 +62,8 @@ internal class UserData(string name = "", string puid = "", string friendCode =
}
}
internal static UserData? GetPlayerUserData(NetworkedPlayerInfo data) => AllUsers?.FirstOrDefault(user => user.Puid == data.GetHashPuid() || user.FriendCode == data.GetHashFriendcode()) ?? AllUsers.First();
internal static UserData? GetPlayerUserDataFromPuid(string puid) => AllUsers?.FirstOrDefault(user => user.Puid == Utils.GetHashStr(puid)) ?? AllUsers.First();
internal static UserData? GetPlayerUserDataFromFriendCode(string friendcode) => AllUsers?.FirstOrDefault(user => user.FriendCode == Utils.GetHashStr(friendcode)) ?? AllUsers.First();
internal static UserData? GetPlayerUserDataFromPuid(string puid) => AllUsers?.FirstOrDefault(user => user.Puid == puid.GetHashStr()) ?? AllUsers.First();
internal static UserData? GetPlayerUserDataFromFriendCode(string friendcode) => AllUsers?.FirstOrDefault(user => user.FriendCode == friendcode.GetHashStr()) ?? AllUsers.First();
private bool HasPermission(MultiPermissionFlags permissionFlags)
{
@@ -82,7 +82,7 @@ internal class UserData(string name = "", string puid = "", string friendCode =
internal bool IsSponsorTier1() => IsSponsor();
internal bool IsSponsor() => HasPermission(MultiPermissionFlags.Contributor_1 | MultiPermissionFlags.Contributor_2 | MultiPermissionFlags.Contributor_3 | MultiPermissionFlags.Dev);
internal bool HasAll() => (Permissions & (ushort)MultiPermissionFlags.All) == (ushort)MultiPermissionFlags.All;
internal bool IsVerified() => Puid == Utils.GetHashStr(EOSManager.Instance.ProductUserId) && FriendCode == Utils.GetHashStr(EOSManager.Instance.FriendCode);
internal bool IsVerified(NetworkedPlayerInfo data) => Puid == Utils.GetHashStr(data?.Puid ?? string.Empty) && FriendCode == Utils.GetHashStr(data?.FriendCode ?? string.Empty);
internal bool IsVerified(PlayerControl player) => Puid == Utils.GetHashStr(player?.Data?.Puid ?? string.Empty) && FriendCode == Utils.GetHashStr(player?.Data?.FriendCode ?? string.Empty);
internal bool IsVerified() => Puid == EOSManager.Instance.ProductUserId.GetHashStr() && FriendCode == EOSManager.Instance.FriendCode.GetHashStr();
internal bool IsVerified(NetworkedPlayerInfo data) => Puid == (data?.Puid ?? string.Empty).GetHashStr() && FriendCode == (data?.FriendCode ?? string.Empty).GetHashStr();
internal bool IsVerified(PlayerControl player) => Puid == (player?.Data?.Puid ?? string.Empty).GetHashStr() && FriendCode == (player?.Data?.FriendCode ?? string.Empty).GetHashStr();
}
-3
View File
@@ -4,9 +4,6 @@ using UnityEngine.Networking;
namespace BetterAmongUs.Network;
/// <summary>
/// Class representing a file from GitHub (for custom hats).
/// </summary>
internal class GitHubFile
{
/// <summary>
+1 -1
View File
@@ -1,9 +1,9 @@
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Data;
using BetterAmongUs.Helpers;
using BetterAmongUs.Items;
using BetterAmongUs.Managers;
using BetterAmongUs.Modules;
using BetterAmongUs.Network.Configs;
using BetterAmongUs.Patches.Gameplay.UI.Chat;
using BetterAmongUs.Patches.Gameplay.UI.Settings;
using HarmonyLib;
+9 -1
View File
@@ -1,6 +1,6 @@
using BetterAmongUs.Helpers;
using BetterAmongUs.Items;
using BetterAmongUs.Modules;
using BetterAmongUs.Network.Configs;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;
@@ -11,6 +11,7 @@ namespace BetterAmongUs.Patches.Client;
internal static class MainMenuPatch
{
private static SpriteRenderer? sprite;
internal static PassiveButton? ButtonPrefab;
[HarmonyPatch(nameof(MainMenuManager.LateUpdate))]
[HarmonyPostfix]
@@ -72,5 +73,12 @@ internal static class MainMenuPatch
logo.GetComponent<SpriteRenderer>().sprite = Utils.LoadSprite("BetterAmongUs.Resources.Images.BetterAmongUs-Logo.png", 1f);
__instance.transform.Find("MainUI/AspectScaler/BackgroundTexture")?.gameObject?.SetSpriteColors(sprite => ObjectHelper.AddColor(sprite));
if (ButtonPrefab == null)
{
ButtonPrefab = UnityEngine.Object.Instantiate(__instance.inventoryButton);
ButtonPrefab.gameObject.SetActive(false);
UnityEngine.Object.DontDestroyOnLoad(ButtonPrefab);
}
}
}
+23 -18
View File
@@ -1,5 +1,7 @@
using BetterAmongUs.Helpers;
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Helpers;
using HarmonyLib;
using System.Collections;
using UnityEngine;
namespace BetterAmongUs.Patches.Gameplay.UI;
@@ -7,26 +9,29 @@ namespace BetterAmongUs.Patches.Gameplay.UI;
[HarmonyPatch]
internal static class IntroCutscenePatch
{
[HarmonyPatch(typeof(IntroCutscene._ShowRole_d__41), nameof(IntroCutscene._ShowRole_d__41.MoveNext))]
[HarmonyPatch(typeof(IntroCutscene), nameof(IntroCutscene.CoBegin))]
[HarmonyPostfix]
private static void ShowRole_MoveNext_Postfix(IntroCutscene._ShowRole_d__41 __instance)
private static void ShowRole_MoveNext_Postfix(IntroCutscene __instance)
{
try
__instance.StartCoroutine(CoWaitForShowRole(__instance));
}
private static IEnumerator CoWaitForShowRole(IntroCutscene __instance)
{
while (!__instance.YouAreText.gameObject.active)
{
var introCutscene = __instance.__4__this;
Color RoleColor = Utils.HexToColor32(PlayerControl.LocalPlayer.Data.RoleType.GetRoleHex());
introCutscene.ImpostorText.gameObject.SetActive(false);
introCutscene.TeamTitle.gameObject.SetActive(false);
introCutscene.BackgroundBar.material.color = RoleColor;
introCutscene.BackgroundBar.transform.SetLocalZ(-15);
introCutscene.transform.Find("BackgroundLayer").transform.SetLocalZ(-16);
introCutscene.YouAreText.color = RoleColor;
introCutscene.RoleText.color = RoleColor;
introCutscene.RoleBlurbText.color = RoleColor;
}
catch (Exception ex)
{
Logger.Error(ex);
yield return null;
}
var introCutscene = __instance;
Color RoleColor = Utils.HexToColor32(PlayerControl.LocalPlayer.Data.RoleType.GetRoleHex());
introCutscene.ImpostorText.gameObject.SetActive(false);
introCutscene.TeamTitle.gameObject.SetActive(false);
introCutscene.BackgroundBar.material.color = RoleColor;
introCutscene.BackgroundBar.transform.SetLocalZ(-15);
introCutscene.transform.Find("BackgroundLayer").transform.SetLocalZ(-16);
introCutscene.YouAreText.color = RoleColor;
introCutscene.RoleText.color = RoleColor;
introCutscene.RoleBlurbText.color = RoleColor;
}
}
+116
View File
@@ -0,0 +1,116 @@
using BetterAmongUs.Data;
using BetterAmongUs.Data.Json;
using BetterAmongUs.Helpers;
using BetterAmongUs.Patches.Client;
using HarmonyLib;
using TMPro;
using UnityEngine;
namespace BetterAmongUs.Patches.Gameplay.UI;
[HarmonyPatch(typeof(PlayerTab))]
internal static class PlayerTabPatch
{
private static List<PassiveButton> presetButtons = [];
private static float cooldown = 0f;
[HarmonyPatch(nameof(PlayerTab.OnEnable))]
[HarmonyPrefix]
private static void OnEnable_Postfix(PlayerTab __instance)
{
foreach (var button in presetButtons.ToArray())
{
if (button == null) continue;
UnityEngine.Object.Destroy(button.gameObject);
}
presetButtons.Clear();
for (int i = 0; i <= 5; i++)
{
int currentI = i;
var name = currentI == 0 ? "Among Us Preset" : $"Preset {i}";
var button = __instance.CreateButton(name, new Vector3(2.5f, 1.55f - currentI * 0.45f, 0f), () =>
{
if (cooldown > 0f || BetterDataManager.BetterDataFile.SelectedOutfitPreset == currentI) return;
cooldown = 0.5f;
BetterDataManager.BetterDataFile.SelectedOutfitPreset = currentI;
foreach (var button in presetButtons)
{
if (button == null) continue;
button.SetPassiveButtonHoverStateInactive();
}
var data = OutfitData.GetOutfitData(currentI);
data.Load(() =>
{
if (LoadPlayerOutfit(data))
{
__instance.PlayerPreview.UpdateFromLocalPlayer(PlayerMaterial.MaskType.None);
}
else
{
__instance.PlayerPreview.UpdateFromDataManager(PlayerMaterial.MaskType.None);
}
});
});
presetButtons.Add(button);
}
}
private static bool LoadPlayerOutfit(OutfitData data)
{
var player = PlayerControl.LocalPlayer;
if (player != null)
{
player.RpcSetHat(data.HatId);
player.RpcSetPet(data.PetId);
player.RpcSetSkin(data.SkinId);
player.RpcSetVisor(data.VisorId);
player.RpcSetNamePlate(data.NamePlateId);
return true;
}
return false;
}
private static PassiveButton CreateButton(this PlayerTab __instance, string name, Vector3 pos, Action callback)
{
var button = UnityEngine.Object.Instantiate(MainMenuPatch.ButtonPrefab, __instance.transform);
button.gameObject.SetActive(true);
button.gameObject.SetLayers("UI");
button.transform.localPosition = pos;
button.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
button.OnClick = new();
button.OnClick.AddListener(callback);
button.DestroyTextTranslators();
var text = button.GetComponentInChildren<TextMeshPro>();
text?.SetText(name);
return button;
}
[HarmonyPatch(nameof(PlayerTab.Update))]
[HarmonyPrefix]
private static void Updatee_Postfix(PlayerTab __instance)
{
if (cooldown > 0f)
{
cooldown -= Time.deltaTime;
}
else
{
cooldown = 0f;
}
for (int i = 0; i < presetButtons.Count; i++)
{
PassiveButton? button = presetButtons[i];
if (button == null) continue;
if (i == BetterDataManager.BetterDataFile.SelectedOutfitPreset)
{
button.SetPassiveButtonHoverStateActive();
}
}
}
}