diff --git a/Modules/AntiCheat.cs b/Modules/AntiCheat.cs index f7c2436..ade2d2d 100644 --- a/Modules/AntiCheat.cs +++ b/Modules/AntiCheat.cs @@ -247,7 +247,7 @@ class AntiCheat if (reader.BytesRemaining > 0) { uint level = reader.ReadPackedUInt32(); - if (level >= BetterGameSettings.DetectedLevelAbove.GetInt()) + if (level > BetterGameSettings.DetectedLevelAbove.GetInt()) { BetterNotificationManager.NotifyCheat(player, $"Invalid Level: {level}"); Logger.LogCheat($"{player.BetterData().RealName} {Enum.GetName((RpcCalls)callId)}: {level >= 200}"); diff --git a/Modules/BetterDataManager.cs b/Modules/BetterDataManager.cs index 93418c6..18c3fb9 100644 --- a/Modules/BetterDataManager.cs +++ b/Modules/BetterDataManager.cs @@ -173,46 +173,67 @@ class BetterDataManager return false; } - public static bool LoadBoolSetting(int id) + public static bool LoadBoolSetting(int id, bool Default = false) { string filePath = SettingsFile; string json = File.ReadAllText(filePath); var jsonData = JsonSerializer.Deserialize>(json) ?? new Dictionary(); - if (jsonData.ContainsKey(id.ToString())) + try { - return bool.Parse(jsonData[id.ToString()]); + if (jsonData.ContainsKey(id.ToString())) + { + return bool.Parse(jsonData[id.ToString()]); + } + } + catch + { + SaveSetting(id, Default.ToString()); } - return false; + return Default; } - public static float LoadFloatSetting(int id) + public static float LoadFloatSetting(int id, float Default = 0f) { string filePath = SettingsFile; string json = File.ReadAllText(filePath); var jsonData = JsonSerializer.Deserialize>(json) ?? new Dictionary(); - if (jsonData.ContainsKey(id.ToString())) + try { - return float.Parse(jsonData[id.ToString()]); + if (jsonData.ContainsKey(id.ToString())) + { + return float.Parse(jsonData[id.ToString()]); + } + } + catch + { + SaveSetting(id, Default.ToString()); } - return -1f; + return Default; } - public static int LoadIntSetting(int id) + public static int LoadIntSetting(int id, int Default = 0) { string filePath = SettingsFile; string json = File.ReadAllText(filePath); var jsonData = JsonSerializer.Deserialize>(json) ?? new Dictionary(); - if (jsonData.ContainsKey(id.ToString())) + try { - return int.Parse(jsonData[id.ToString()]); + if (jsonData.ContainsKey(id.ToString())) + { + return int.Parse(jsonData[id.ToString()]); + } + } + catch + { + SaveSetting(id, Default.ToString()); } - return -1; + return Default; } public static void SaveBanList(string friendCode = "", string hashPUID = "") diff --git a/Modules/BetterHostManager.cs b/Modules/BetterHostManager.cs index 550f3af..d34d4bd 100644 --- a/Modules/BetterHostManager.cs +++ b/Modules/BetterHostManager.cs @@ -206,77 +206,104 @@ class BetterHostManager foreach (PlayerControl target in Main.AllPlayerControls) { - if (target == null || target == PlayerControl.LocalPlayer || target.BetterData().IsBetterUser) continue; + if (target == null || target == PlayerControl.LocalPlayer) continue; string NewName = player.CurrentOutfit.PlayerName; StringBuilder sbTopTag = new StringBuilder(); - StringBuilder sbTopInfo = new StringBuilder(); - if (GameStates.IsLobby) + if (!player.BetterData().IsBetterUser) { - NewName = player.Data.PlayerName; - - if (player.IsHost()) - NewName = player.GetPlayerNameAndColor(); - - if (player.IsDev()) - sbTopTag.Append("(Dev)+++"); - - if (player == PlayerControl.LocalPlayer) - sbTopTag.Append($"Better Host+++"); - else if (player.BetterData().IsBetterUser) - sbTopTag.Append("Better User+++"); - } - else if (GameStates.IsInGamePlay && !GameStates.IsHideNSeek) - { - string Role = $"{player.GetRoleName()}"; - if (!player.IsImpostorTeam() && player.myTasks.Count > 0) + if (GameStates.IsLobby) { - Role += $" ({player.Data.Tasks.ToArray().Where(task => task.Complete).Count()}/{player.Data.Tasks.Count})"; + NewName = player.Data.PlayerName; + + if (player.IsHost()) + NewName = player.GetPlayerNameAndColor(); + + if (player.IsDev()) + sbTopTag.Append("(Dev)+++"); + + if (player == PlayerControl.LocalPlayer) + sbTopTag.Append($"Better Host+++"); + else if (player.BetterData().IsBetterUser) + sbTopTag.Append("Better User+++"); } - if (player.IsImpostorTeam() is false || target.IsImpostorTeam() is false) + else if (GameStates.IsInGamePlay && !GameStates.IsHideNSeek) { - if (target.IsAlive() && player != target) + string Role = $"{player.GetRoleName()}"; + if (!player.IsImpostorTeam() && player.myTasks.Count > 0) { - Role = ""; + Role += $" ({player.Data.Tasks.ToArray().Where(task => task.Complete).Count()}/{player.Data.Tasks.Count})"; + } + if (player.IsImpostorTeam() is false || target.IsImpostorTeam() is false) + { + if (target.IsAlive() && player != target) + { + Role = ""; + } + } + + sbTopTag.Append($"{Role}+++"); + } + else if (GameStates.IsInGamePlay) + { + if (player == target) + { + if (player.IsImpostorTeam()) + { + sbTopTag.Append($"Seeker+++"); + } + else + { + sbTopTag.Append($"Hider+++"); + } } } - sbTopTag.Append($"{Role}+++"); - } - - for (int i = 0; i < sbTopTag.ToString().Split("+++").Length; i++) - { - if (!string.IsNullOrEmpty(sbTopTag.ToString().Split("+++")[i])) + // Put +++ at the end of each tag + static StringBuilder FormatInfo(StringBuilder source) { - if (i < sbTopTag.ToString().Split("+++").Length) + var sb = new StringBuilder(); + if (source.Length > 0) { - sbTopInfo.Append(sbTopTag.ToString().Split("+++")[i]); + string text = source.ToString(); + string[] parts = text.Split("+++"); + for (int i = 0; i < parts.Length; i++) + { + if (!string.IsNullOrEmpty(Utils.RemoveHtmlText(parts[i]))) + { + sb.Append(parts[i]); + if (i != parts.Length - 2) + { + sb.Append(" - "); + } + } + } } - if (i != sbTopTag.ToString().Split("+++").Length - 2) + + return sb; + } + + sbTopTag = FormatInfo(sbTopTag); + + if (sbTopTag.Length > 0) + NewName = $"{sbTopTag}\n{NewName}"; + else + NewName = $"{NewName}"; + + // Don't send rpc if name is the same! + if (player.BetterData().LastNameSetFor.TryGetValue(target.PlayerId, out var lastName)) + { + if (lastName == NewName || !force) { - sbTopInfo.Append(" - "); + return; } } + + player.BetterData().LastNameSetFor[target.PlayerId] = NewName; } - if (sbTopInfo.Length > 0) - NewName = $"{sbTopInfo}\n{NewName}"; - else - NewName = $"{NewName}"; - - // Don't send rpc if name is the same! - if (player.BetterData().LastNameSetFor.TryGetValue(target.PlayerId, out var lastName)) - { - if (lastName == NewName || !force) - { - return; - } - } - - player.BetterData().LastNameSetFor[target.PlayerId] = NewName; - player.RpcSetNamePrivate(NewName, target); Logger.Log($"Set {player.Data.PlayerName} name to {NewName.Replace("\n", "-")} for {target.Data.PlayerName}", "RPC"); } diff --git a/Modules/ExtendedPlayerControl.cs b/Modules/ExtendedPlayerControl.cs index 312eee7..87bceb4 100644 --- a/Modules/ExtendedPlayerControl.cs +++ b/Modules/ExtendedPlayerControl.cs @@ -129,11 +129,6 @@ static class ExtendedPlayerControl } // RPCs - public static void RpcSendHostChat(this PlayerControl player, string text, string title = "(System Message)", bool sendToBetterUser = true) - { - if (player == null) return; - RPC.SendHostChatToPlayer(player, text, title, sendToBetterUser); - } public static void RpcSetNamePrivate(this PlayerControl player, string name, PlayerControl target) { if (player == null || target == null) return; diff --git a/Modules/OptionItems/BetterOptionCheckboxItem.cs b/Modules/OptionItems/BetterOptionCheckboxItem.cs index c638ed2..b8695a0 100644 --- a/Modules/OptionItems/BetterOptionCheckboxItem.cs +++ b/Modules/OptionItems/BetterOptionCheckboxItem.cs @@ -7,12 +7,17 @@ public class BetterOptionCheckboxItem : BetterOptionItem private ToggleOption? ThisOption; private bool? IsChecked; - public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, bool DefaultValue = true, BetterOptionItem Parent = null) + public override bool ShowChildrenCondition() => IsChecked == true; + public override bool SelfShowCondition() => ShowCondition != null ? ShowCondition() : base.SelfShowCondition(); + public Func? ShowCondition = null; + + public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, bool DefaultValue = true, BetterOptionItem? Parent = null, Func? selfShowCondition = null) { Id = id; Tab = gameOptionsMenu; Name = name; IsChecked = DefaultValue; + ShowCondition = selfShowCondition; if (gameOptionsMenu == null) { @@ -21,10 +26,17 @@ public class BetterOptionCheckboxItem : BetterOptionItem } ToggleOption optionBehaviour = UnityEngine.Object.Instantiate(gameOptionsMenu.checkboxOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); - optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f - StaticSpacingNum * SpacingNum, -2f); + optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f, -2f); SetUp(optionBehaviour); optionBehaviour.OnValueChanged = new Action((option) => ValueChanged(id, option)); - SpacingNum += StaticSpacingNumPlus; + + optionBehaviour.LabelBackground.transform.localScale = new Vector3(1.6f, 0.78f); + optionBehaviour.LabelBackground.transform.SetLocalX(-2.4f); + optionBehaviour.TitleText.enableAutoSizing = false; + optionBehaviour.TitleText.transform.SetLocalX(-1.5f); + optionBehaviour.TitleText.alignment = TMPro.TextAlignmentOptions.Right; + optionBehaviour.TitleText.enableWordWrapping = false; + optionBehaviour.TitleText.fontSize = 2.5f; // Set data optionBehaviour.CheckMark.GetComponent().enabled = DefaultValue; @@ -35,6 +47,28 @@ public class BetterOptionCheckboxItem : BetterOptionItem Load(DefaultValue); BetterOptionItems.Add(this); + obj = optionBehaviour.gameObject; + + if (Parent != null) + { + int Index = 1; + var tempParent = Parent; + + while (tempParent.ThisParent != null) + { + tempParent = tempParent.ThisParent; + Index++; + } + + optionBehaviour.LabelBackground.GetComponent().color -= new Color(0.25f, 0.25f, 0.25f, 0f) * Index; + optionBehaviour.LabelBackground.transform.localScale -= new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.position += new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.SetLocalZ(1f); + ThisParent = Parent; + IsChild = true; + Parent.ChildrenList.Add(this); + } + return this; } @@ -44,7 +78,7 @@ public class BetterOptionCheckboxItem : BetterOptionItem { if (ThisOption == null) return; - var Bool = BetterDataManager.LoadBoolSetting(Id); + var Bool = BetterDataManager.LoadBoolSetting(Id, DefaultValue); ThisOption.CheckMark.GetComponent().enabled = Bool; IsChecked = Bool; } @@ -79,5 +113,15 @@ public class BetterOptionCheckboxItem : BetterOptionItem { IsChecked = !IsChecked; BetterDataManager.SaveSetting(Id, IsChecked.ToString()); + + if (IsParent || IsChild) + { + bool Bool = ShowChildrenCondition(); + foreach (var item in ChildrenList) + { + item.obj.SetActive(Bool && item.SelfShowCondition()); + } + UpdatePositions(); + } } } diff --git a/Modules/OptionItems/BetterOptionFloatItem.cs b/Modules/OptionItems/BetterOptionFloatItem.cs index 860e4e8..39f3e5e 100644 --- a/Modules/OptionItems/BetterOptionFloatItem.cs +++ b/Modules/OptionItems/BetterOptionFloatItem.cs @@ -5,14 +5,18 @@ namespace BetterAmongUs; public class BetterOptionFloatItem : BetterOptionItem { + private NumberOption? ThisOption; public float CurrentValue; public FloatRange floatRange = new(0f, 180f); public float Increment = 2.5f; - private NumberOption? ThisOption; private string? PostFix; private string? PreFix; - public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, float[] values, float DefaultValue, string preFix = "", string postFix = "", BetterOptionItem Parent = null) + public override bool ShowChildrenCondition() => CurrentValue > floatRange.min; + public override bool SelfShowCondition() => ShowCondition != null ? ShowCondition() : base.SelfShowCondition(); + public Func? ShowCondition = null; + + public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, float[] values, float DefaultValue, string preFix = "", string postFix = "", BetterOptionItem? Parent = null, Func? selfShowCondition = null) { Id = id; floatRange = new(values[0], values[1]); @@ -20,6 +24,7 @@ public class BetterOptionFloatItem : BetterOptionItem if (DefaultValue < floatRange.min) DefaultValue = floatRange.min; if (DefaultValue > floatRange.max) DefaultValue = floatRange.max; CurrentValue = DefaultValue; + ShowCondition = selfShowCondition; if (gameOptionsMenu == null) { @@ -30,10 +35,9 @@ public class BetterOptionFloatItem : BetterOptionItem if (values.Length is < 3 or > 3) return null; NumberOption optionBehaviour = UnityEngine.Object.Instantiate(gameOptionsMenu.numberOptionOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); - optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f - StaticSpacingNum * SpacingNum, -2f); + optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f, -2f); SetUp(optionBehaviour); optionBehaviour.OnValueChanged = new Action((option) => ValueChanged(id, option)); - SpacingNum += StaticSpacingNumPlus; // Fix Game Crash foreach (RulesCategory rulesCategory in GameManager.Instance.GameSettingsList.AllCategories) @@ -45,6 +49,16 @@ public class BetterOptionFloatItem : BetterOptionItem optionBehaviour.MinusBtn.OnClick.RemoveAllListeners(); optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => Increase())); optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => Decrease())); + optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => ValueChanged(id, optionBehaviour))); + optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => ValueChanged(id, optionBehaviour))); + + optionBehaviour.LabelBackground.transform.localScale = new Vector3(1.6f, 0.78f); + optionBehaviour.LabelBackground.transform.SetLocalX(-2.4f); + optionBehaviour.TitleText.enableAutoSizing = false; + optionBehaviour.TitleText.transform.SetLocalX(-1.5f); + optionBehaviour.TitleText.alignment = TMPro.TextAlignmentOptions.Right; + optionBehaviour.TitleText.enableWordWrapping = false; + optionBehaviour.TitleText.fontSize = 2.5f; // Set data Tab = gameOptionsMenu; @@ -59,6 +73,28 @@ public class BetterOptionFloatItem : BetterOptionItem AdjustButtonsActiveState(); BetterOptionItems.Add(this); + obj = optionBehaviour.gameObject; + + if (Parent != null) + { + int Index = 1; + var tempParent = Parent; + + while (tempParent.ThisParent != null) + { + tempParent = tempParent.ThisParent; + Index++; + } + + optionBehaviour.LabelBackground.GetComponent().color -= new Color(0.25f, 0.25f, 0.25f, 0f) * Index; + optionBehaviour.LabelBackground.transform.localScale -= new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.position += new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.SetLocalZ(1f); + ThisParent = Parent; + IsChild = true; + Parent.ChildrenList.Add(this); + } + return this; } @@ -99,6 +135,10 @@ public class BetterOptionFloatItem : BetterOptionItem { CurrentValue += Increment * times; } + else + { + CurrentValue = floatRange.max; + } AdjustButtonsActiveState(); } @@ -115,6 +155,10 @@ public class BetterOptionFloatItem : BetterOptionItem { CurrentValue -= Increment * times; } + else + { + CurrentValue = floatRange.min; + } AdjustButtonsActiveState(); } @@ -123,7 +167,7 @@ public class BetterOptionFloatItem : BetterOptionItem { if (BetterDataManager.CanLoadSetting(Id)) { - var Float = BetterDataManager.LoadFloatSetting(Id); + var Float = BetterDataManager.LoadFloatSetting(Id, DefaultValue); if (Float > floatRange.max || Float < floatRange.min) { @@ -174,5 +218,14 @@ public class BetterOptionFloatItem : BetterOptionItem public override void ValueChanged(int id, OptionBehaviour optionBehaviour) { + if (IsParent || IsChild) + { + bool Bool = ShowChildrenCondition(); + foreach (var item in ChildrenList) + { + item.obj.SetActive(Bool && item.SelfShowCondition()); + } + UpdatePositions(); + } } } diff --git a/Modules/OptionItems/BetterOptionIntItem.cs b/Modules/OptionItems/BetterOptionIntItem.cs index f0a8dee..2fcfa41 100644 --- a/Modules/OptionItems/BetterOptionIntItem.cs +++ b/Modules/OptionItems/BetterOptionIntItem.cs @@ -4,14 +4,18 @@ namespace BetterAmongUs; public class BetterOptionIntItem : BetterOptionItem { + private NumberOption? ThisOption; public int CurrentValue; public IntRange intRange = new(0, 180); public int Increment = 1; - private NumberOption? ThisOption; private string? PostFix; private string? PreFix; - public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, int[] values, int DefaultValue, string preFix = "", string postFix = "", BetterOptionItem Parent = null) + public override bool ShowChildrenCondition() => CurrentValue > intRange.min; + public override bool SelfShowCondition() => ShowCondition != null ? ShowCondition() : base.SelfShowCondition(); + public Func? ShowCondition = null; + + public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, int[] values, int DefaultValue, string preFix = "", string postFix = "", BetterOptionItem? Parent = null, Func? selfShowCondition = null) { Id = id; intRange = new(values[0], values[1]); @@ -19,6 +23,7 @@ public class BetterOptionIntItem : BetterOptionItem if (DefaultValue < intRange.min) DefaultValue = intRange.min; if (DefaultValue > intRange.max) DefaultValue = intRange.max; CurrentValue = DefaultValue; + ShowCondition = selfShowCondition; if (gameOptionsMenu == null) { @@ -29,10 +34,9 @@ public class BetterOptionIntItem : BetterOptionItem if (values.Length is < 3 or > 3) return null; NumberOption optionBehaviour = UnityEngine.Object.Instantiate(gameOptionsMenu.numberOptionOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); - optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f - StaticSpacingNum * SpacingNum, -2f); + optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f, -2f); SetUp(optionBehaviour); optionBehaviour.OnValueChanged = new Action((option) => ValueChanged(id, option)); - SpacingNum += StaticSpacingNumPlus; // Fix Game Crash foreach (RulesCategory rulesCategory in GameManager.Instance.GameSettingsList.AllCategories) @@ -44,6 +48,16 @@ public class BetterOptionIntItem : BetterOptionItem optionBehaviour.MinusBtn.OnClick.RemoveAllListeners(); optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => Increase())); optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => Decrease())); + optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => ValueChanged(id, optionBehaviour))); + optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => ValueChanged(id, optionBehaviour))); + + optionBehaviour.LabelBackground.transform.localScale = new Vector3(1.6f, 0.78f); + optionBehaviour.LabelBackground.transform.SetLocalX(-2.4f); + optionBehaviour.TitleText.enableAutoSizing = false; + optionBehaviour.TitleText.transform.SetLocalX(-1.5f); + optionBehaviour.TitleText.alignment = TMPro.TextAlignmentOptions.Right; + optionBehaviour.TitleText.enableWordWrapping = false; + optionBehaviour.TitleText.fontSize = 2.5f; // Set data Tab = gameOptionsMenu; @@ -58,6 +72,28 @@ public class BetterOptionIntItem : BetterOptionItem AdjustButtonsActiveState(); BetterOptionItems.Add(this); + obj = optionBehaviour.gameObject; + + if (Parent != null) + { + int Index = 1; + var tempParent = Parent; + + while (tempParent.ThisParent != null) + { + tempParent = tempParent.ThisParent; + Index++; + } + + optionBehaviour.LabelBackground.GetComponent().color -= new Color(0.25f, 0.25f, 0.25f, 0f) * Index; + optionBehaviour.LabelBackground.transform.localScale -= new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.position += new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.SetLocalZ(1f); + ThisParent = Parent; + IsChild = true; + Parent.ChildrenList.Add(this); + } + return this; } @@ -98,6 +134,10 @@ public class BetterOptionIntItem : BetterOptionItem { CurrentValue += Increment * times; } + else + { + CurrentValue = intRange.max; + } AdjustButtonsActiveState(); } @@ -114,6 +154,10 @@ public class BetterOptionIntItem : BetterOptionItem { CurrentValue -= Increment * times; } + else + { + CurrentValue = intRange.min; + } AdjustButtonsActiveState(); } @@ -122,7 +166,7 @@ public class BetterOptionIntItem : BetterOptionItem { if (BetterDataManager.CanLoadSetting(Id)) { - var Int = BetterDataManager.LoadIntSetting(Id); + var Int = BetterDataManager.LoadIntSetting(Id, DefaultValue); if (Int > intRange.max || Int < intRange.min) { @@ -167,11 +211,20 @@ public class BetterOptionIntItem : BetterOptionItem optionBehaviour.data = new BaseGameSetting { Title = StringNames.None, - Type = OptionTypes.Float, + Type = OptionTypes.Int, }; } public override void ValueChanged(int id, OptionBehaviour optionBehaviour) { + if (IsParent || IsChild) + { + bool Bool = ShowChildrenCondition(); + foreach (var item in ChildrenList) + { + item.obj.SetActive(Bool && item.SelfShowCondition()); + } + UpdatePositions(); + } } } diff --git a/Modules/OptionItems/BetterOptionItem.cs b/Modules/OptionItems/BetterOptionItem.cs index 6b8c937..cc57b3b 100644 --- a/Modules/OptionItems/BetterOptionItem.cs +++ b/Modules/OptionItems/BetterOptionItem.cs @@ -1,4 +1,5 @@ -using TMPro; +using BetterAmongUs.Patches; +using TMPro; using UnityEngine; namespace BetterAmongUs; @@ -7,6 +8,8 @@ public class BetterOptionItem { public float StaticSpacingNum => 1f; public float StaticSpacingNumPlus => 0.45f; + public static Dictionary TempPlayerOptionData = []; + public static int TempPlayerOptionDataNum = 0; public static List BetterOptionItems = []; public static float SpacingNum = 0; @@ -16,6 +19,63 @@ public class BetterOptionItem public OptionBehaviour? Option; public string? Name = "None"; public TextMeshPro? TitleText; + public GameObject? obj; + + public BetterOptionItem? ThisParent; + public bool IsChild = false; + public bool IsParent => ChildrenList.Count > 0; + public List ChildrenList = []; + public virtual bool ShowChildrenCondition() => false; + public virtual bool SelfShowCondition() => true; + + public static void UpdatePositions() + { + SpacingNum = 0f; + + foreach (var item in BetterOptionItems) + { + try + { + item.obj.transform.SetLocalY(2f); + + // Need to fix name not setting + if (item.ThisParent != null) + { + _ = new LateTask(() => + { + item.obj.SetActive(item.ThisParent.ShowChildrenCondition() && item.SelfShowCondition() && item.ThisParent.Option.gameObject.active); + }, 0.005f, shoudLog: false); + if (!(item.ThisParent.ShowChildrenCondition() && item.SelfShowCondition() && item.ThisParent.Option.gameObject.active)) + continue; + } + + if (item is BetterOptionPlayerItem player) + { + player.Load(); + } + + SpacingNum += item switch + { + BetterOptionHeaderItem => 0.1f, + BetterOptionDividerItem => 0.15f, + _ => 0f, + }; + + item.obj.transform.SetLocalY(2f - 1f * SpacingNum); + + SpacingNum += item switch + { + BetterOptionHeaderItem => 0.75f, + BetterOptionTitleItem => 0.50f, + _ => 0.45f, + }; + } + catch { } + } + + GameSettingMenuPatch.BetterSettingsTab.scrollBar.SetYBoundsMax(1.5f * SpacingNum / 2); + GameSettingMenuPatch.BetterSettingsTab.scrollBar.ScrollRelative(new(0f, 0f)); + } public void SetUp(OptionBehaviour optionBehaviour) { diff --git a/Modules/OptionItems/BetterOptionPlayerItem.cs b/Modules/OptionItems/BetterOptionPlayerItem.cs new file mode 100644 index 0000000..a270a5c --- /dev/null +++ b/Modules/OptionItems/BetterOptionPlayerItem.cs @@ -0,0 +1,192 @@ +using System.Dynamic; +using UnityEngine; + +namespace BetterAmongUs; + +public class BetterOptionPlayerItem : BetterOptionItem +{ + private NumberOption? ThisOption; + public int CurrentIndex = -1; + + public override bool ShowChildrenCondition() => CurrentIndex > -1; + public override bool SelfShowCondition() => ShowCondition != null ? ShowCondition() : base.SelfShowCondition(); + public Func? ShowCondition = null; + + public BetterOptionItem Create(GameOptionsMenu gameOptionsMenu, string name, BetterOptionItem? Parent = null, Func? selfShowCondition = null) + { + Id = TempPlayerOptionDataNum + 1; + Tab = gameOptionsMenu; + Name = name; + ShowCondition = selfShowCondition; + + if (gameOptionsMenu == null) + { + return this; + } + + NumberOption optionBehaviour = UnityEngine.Object.Instantiate(gameOptionsMenu.numberOptionOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); + optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f, -2f); + SetUp(optionBehaviour); + optionBehaviour.OnValueChanged = new Action((option) => ValueChanged(0, option)); + + // Fix Game Crash + foreach (RulesCategory rulesCategory in GameManager.Instance.GameSettingsList.AllCategories) + { + optionBehaviour.data = rulesCategory.AllGameSettings.ToArray().FirstOrDefault(item => item.Type == OptionTypes.Player); + } + + optionBehaviour.PlusBtn.OnClick.RemoveAllListeners(); + optionBehaviour.MinusBtn.OnClick.RemoveAllListeners(); + optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => Increase())); + optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => Decrease())); + optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => ValueChanged(Id, optionBehaviour))); + optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => ValueChanged(Id, optionBehaviour))); + + optionBehaviour.LabelBackground.transform.localScale = new Vector3(1.6f, 0.78f); + optionBehaviour.LabelBackground.transform.SetLocalX(-2.4f); + optionBehaviour.TitleText.enableAutoSizing = false; + optionBehaviour.TitleText.transform.SetLocalX(-1.5f); + optionBehaviour.TitleText.alignment = TMPro.TextAlignmentOptions.Right; + optionBehaviour.TitleText.enableWordWrapping = false; + optionBehaviour.TitleText.fontSize = 2.5f; + + // Set data + TitleText = optionBehaviour.TitleText; + Option = optionBehaviour; + ThisOption = optionBehaviour; + + Load(); + BetterOptionItems.Add(this); + obj = optionBehaviour.gameObject; + + if (Parent != null) + { + int Index = 1; + var tempParent = Parent; + + while (tempParent.ThisParent != null) + { + tempParent = tempParent.ThisParent; + Index++; + } + + optionBehaviour.LabelBackground.GetComponent().color -= new Color(0.25f, 0.25f, 0.25f, 0f) * Index; + optionBehaviour.LabelBackground.transform.localScale -= new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.position += new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.SetLocalZ(1f); + ThisParent = Parent; + IsChild = true; + Parent.ChildrenList.Add(this); + } + + TempPlayerOptionDataNum++; + + return this; + } + + private void AdjustButtonsActiveState() + { + if (ThisOption == null) return; + + if (CurrentIndex >= 0) + { + ThisOption.ValueText.text = Utils.PlayerFromId(CurrentIndex).GetPlayerNameAndColor(); + } + else + { + ThisOption.ValueText.text = "Random"; + } + + if (CurrentIndex >= Main.AllPlayerControls.Length - 1) + { + ThisOption.PlusBtn.SetInteractable(false); + ThisOption.MinusBtn.SetInteractable(true); + } + else if (CurrentIndex <= -1) + { + ThisOption.PlusBtn.SetInteractable(true); + ThisOption.MinusBtn.SetInteractable(false); + } + else + { + ThisOption.PlusBtn.SetInteractable(true); + ThisOption.MinusBtn.SetInteractable(true); + } + + TempPlayerOptionData[Id] = CurrentIndex; + } + + public void Increase() + { + if (CurrentIndex < Main.AllPlayerControls.Length) + { + CurrentIndex++; + AdjustButtonsActiveState(); + } + } + + public void Decrease() + { + if (CurrentIndex > -1) + { + CurrentIndex--; + AdjustButtonsActiveState(); + } + } + + public int Load() + { + if (TempPlayerOptionData.ContainsKey(Id)) + { + var saveindex = TempPlayerOptionData[Id]; + + if (saveindex != -1 && Utils.PlayerFromId(saveindex) == null) + saveindex = Main.AllPlayerControls.Length - 1; + + CurrentIndex = saveindex; + } + else + { + TempPlayerOptionData[Id] = -1; + CurrentIndex = TempPlayerOptionData[Id]; + } + + AdjustButtonsActiveState(); + + return CurrentIndex; + } + + public override int GetValue() + { + if (SelfShowCondition()) + { + return Load(); + } + else + { + return -1; + } + } + + public override void SetData(OptionBehaviour optionBehaviour) + { + optionBehaviour.data = new BaseGameSetting + { + Title = StringNames.None, + Type = OptionTypes.Int, + }; + } + + public override void ValueChanged(int id, OptionBehaviour optionBehaviour) + { + if (IsParent || IsChild) + { + bool Bool = ShowChildrenCondition(); + foreach (var item in ChildrenList) + { + item.obj.SetActive(Bool && item.SelfShowCondition()); + } + UpdatePositions(); + } + } +} diff --git a/Modules/OptionItems/BetterOptionStringItem.cs b/Modules/OptionItems/BetterOptionStringItem.cs index 450ea60..fa49fbf 100644 --- a/Modules/OptionItems/BetterOptionStringItem.cs +++ b/Modules/OptionItems/BetterOptionStringItem.cs @@ -4,11 +4,15 @@ namespace BetterAmongUs; public class BetterOptionStringItem : BetterOptionItem { + private StringOption? ThisOption; public string[] Values = []; public int CurrentValue; - private StringOption? ThisOption; - public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, string[] strings, int DefaultValue = 0, BetterOptionItem Parent = null) + public override bool ShowChildrenCondition() => CurrentValue > 0; + public override bool SelfShowCondition() => ShowCondition != null ? ShowCondition() : base.SelfShowCondition(); + public Func? ShowCondition = null; + + public BetterOptionItem Create(int id, GameOptionsMenu gameOptionsMenu, string name, string[] strings, int DefaultValue = 0, BetterOptionItem? Parent = null, Func? selfShowCondition = null) { Id = id; Values = strings; @@ -17,6 +21,7 @@ public class BetterOptionStringItem : BetterOptionItem if (DefaultValue < 0) DefaultValue = 0; if (DefaultValue > Values.Length) DefaultValue = Values.Length; CurrentValue = DefaultValue; + ShowCondition = selfShowCondition; if (gameOptionsMenu == null) { @@ -25,10 +30,9 @@ public class BetterOptionStringItem : BetterOptionItem } StringOption optionBehaviour = UnityEngine.Object.Instantiate(gameOptionsMenu.stringOptionOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); - optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f - StaticSpacingNum * SpacingNum, -2f); + optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f, -2f); SetUp(optionBehaviour); optionBehaviour.OnValueChanged = new Action((option) => ValueChanged(id, option)); - SpacingNum += StaticSpacingNumPlus; // Fix Game Crash foreach (RulesCategory rulesCategory in GameManager.Instance.GameSettingsList.AllCategories) @@ -40,6 +44,16 @@ public class BetterOptionStringItem : BetterOptionItem optionBehaviour.MinusBtn.OnClick.RemoveAllListeners(); optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => Increase())); optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => Decrease())); + optionBehaviour.PlusBtn.OnClick.AddListener(new Action(() => ValueChanged(id, optionBehaviour))); + optionBehaviour.MinusBtn.OnClick.AddListener(new Action(() => ValueChanged(id, optionBehaviour))); + + optionBehaviour.LabelBackground.transform.localScale = new Vector3(1.6f, 0.78f); + optionBehaviour.LabelBackground.transform.SetLocalX(-2.4f); + optionBehaviour.TitleText.enableAutoSizing = false; + optionBehaviour.TitleText.transform.SetLocalX(-1.5f); + optionBehaviour.TitleText.alignment = TMPro.TextAlignmentOptions.Right; + optionBehaviour.TitleText.enableWordWrapping = false; + optionBehaviour.TitleText.fontSize = 2.5f; // Set data TitleText = optionBehaviour.TitleText; @@ -50,6 +64,28 @@ public class BetterOptionStringItem : BetterOptionItem AdjustButtonsActiveState(); BetterOptionItems.Add(this); + obj = optionBehaviour.gameObject; + + if (Parent != null) + { + int Index = 1; + var tempParent = Parent; + + while (tempParent.ThisParent != null) + { + tempParent = tempParent.ThisParent; + Index++; + } + + optionBehaviour.LabelBackground.GetComponent().color -= new Color(0.25f, 0.25f, 0.25f, 0f) * Index; + optionBehaviour.LabelBackground.transform.localScale -= new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.position += new Vector3(0.04f, 0f, 0f) * Index; + optionBehaviour.LabelBackground.transform.SetLocalZ(1f); + ThisParent = Parent; + IsChild = true; + Parent.ChildrenList.Add(this); + } + return this; } @@ -103,7 +139,7 @@ public class BetterOptionStringItem : BetterOptionItem { if (BetterDataManager.CanLoadSetting(Id)) { - var Int = BetterDataManager.LoadIntSetting(Id); + var Int = BetterDataManager.LoadIntSetting(Id, DefaultValue); if (Int > Values.Length - 1 || Int < 0) { @@ -142,5 +178,14 @@ public class BetterOptionStringItem : BetterOptionItem public override void ValueChanged(int id, OptionBehaviour optionBehaviour) { + if (IsParent || IsChild) + { + bool Bool = ShowChildrenCondition(); + foreach (var item in ChildrenList) + { + item.obj.SetActive(Bool && item.SelfShowCondition()); + } + UpdatePositions(); + } } } diff --git a/Modules/OptionItems/NoneOption/BetterOptionDividerItem.cs b/Modules/OptionItems/NoneOption/BetterOptionDividerItem.cs index abdf623..26d794e 100644 --- a/Modules/OptionItems/NoneOption/BetterOptionDividerItem.cs +++ b/Modules/OptionItems/NoneOption/BetterOptionDividerItem.cs @@ -11,13 +11,11 @@ public class BetterOptionDividerItem : BetterOptionItem return this; } - SpacingNum += 0.15f; - Tab = gameOptionsMenu; Name = "Divider"; CategoryHeaderMasked categoryHeaderMasked = UnityEngine.Object.Instantiate(gameOptionsMenu.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f; - categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, 2f - StaticSpacingNum * SpacingNum, -2f); + categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, 2f, -2f); UnityEngine.Object.Destroy(categoryHeaderMasked.Background.gameObject); UnityEngine.Object.Destroy(categoryHeaderMasked.Title.gameObject); if (categoryHeaderMasked.Divider != null) @@ -25,7 +23,8 @@ public class BetterOptionDividerItem : BetterOptionItem categoryHeaderMasked.Divider.material.SetInt(PlayerMaterial.MaskLayer, maskLayer); } - SpacingNum += 0.45f; + BetterOptionItems.Add(this); + obj = categoryHeaderMasked.gameObject; return this; } diff --git a/Modules/OptionItems/NoneOption/BetterOptionHeaderItem.cs b/Modules/OptionItems/NoneOption/BetterOptionHeaderItem.cs index 34cae00..2f903f6 100644 --- a/Modules/OptionItems/NoneOption/BetterOptionHeaderItem.cs +++ b/Modules/OptionItems/NoneOption/BetterOptionHeaderItem.cs @@ -11,13 +11,11 @@ public class BetterOptionHeaderItem : BetterOptionItem return this; } - SpacingNum += 0.1f; - Tab = gameOptionsMenu; Name = name; CategoryHeaderMasked categoryHeaderMasked = UnityEngine.Object.Instantiate(gameOptionsMenu.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f; - categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, 2f - StaticSpacingNum * SpacingNum, -2f); + categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, 2f, -2f); categoryHeaderMasked.Title.text = name; categoryHeaderMasked.Background.material.SetInt(PlayerMaterial.MaskLayer, maskLayer); if (categoryHeaderMasked.Divider != null) @@ -27,7 +25,8 @@ public class BetterOptionHeaderItem : BetterOptionItem categoryHeaderMasked.Title.fontMaterial.SetFloat("_StencilComp", 3f); categoryHeaderMasked.Title.fontMaterial.SetFloat("_Stencil", maskLayer); - SpacingNum += 0.75f; + BetterOptionItems.Add(this); + obj = categoryHeaderMasked.gameObject; return this; } diff --git a/Modules/OptionItems/NoneOption/BetterOptionTitleItem.cs b/Modules/OptionItems/NoneOption/BetterOptionTitleItem.cs index 5c712be..7b44c07 100644 --- a/Modules/OptionItems/NoneOption/BetterOptionTitleItem.cs +++ b/Modules/OptionItems/NoneOption/BetterOptionTitleItem.cs @@ -12,9 +12,8 @@ public class BetterOptionTitleItem : BetterOptionItem } ToggleOption optionBehaviour = UnityEngine.Object.Instantiate(gameOptionsMenu.checkboxOrigin, Vector3.zero, Quaternion.identity, gameOptionsMenu.settingsContainer); - optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f - StaticSpacingNum * SpacingNum, -2f); + optionBehaviour.transform.localPosition = new Vector3(0.952f, 2f, -2f); SetUp(optionBehaviour); - SpacingNum += StaticSpacingNumPlus; UnityEngine.Object.Destroy(optionBehaviour.CheckMark.transform.parent.gameObject); UnityEngine.Object.Destroy(optionBehaviour.GetComponent()); @@ -25,6 +24,14 @@ public class BetterOptionTitleItem : BetterOptionItem optionBehaviour.LabelBackground.color = new Color(0.6f, 0.6f, 0.6f, 1f); optionBehaviour.LabelBackground.transform.SetLocalZ(1f); + optionBehaviour.LabelBackground.transform.localScale = new Vector3(1.6f, 1f); + optionBehaviour.LabelBackground.transform.SetLocalX(-2.4f); + optionBehaviour.TitleText.enableAutoSizing = false; + optionBehaviour.TitleText.transform.SetLocalX(-2.4f); + optionBehaviour.TitleText.alignment = TMPro.TextAlignmentOptions.Center; + optionBehaviour.TitleText.enableWordWrapping = false; + optionBehaviour.TitleText.fontSize = 2.5f; + // Set data Tab = gameOptionsMenu; Name = $"{name}"; @@ -32,6 +39,8 @@ public class BetterOptionTitleItem : BetterOptionItem TitleText = optionBehaviour.TitleText; BetterOptionItems.Add(this); + obj = optionBehaviour.gameObject; + return this; } diff --git a/Modules/RPC.cs b/Modules/RPC.cs index 9642569..0348b23 100644 --- a/Modules/RPC.cs +++ b/Modules/RPC.cs @@ -92,6 +92,22 @@ public static class MessageReaderUpdateSystemPatch internal static class RPC { + public static void RpcSyncSettings() + { + if (!AmongUsClient.Instance.AmHost) + { + return; + } + + foreach (var player in Main.AllPlayerControls.Where(pc => pc != PlayerControl.LocalPlayer)) + { + var optionsByteArray = GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameOptionsManager.Instance.CurrentGameOptions, false); + MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(player.NetId, (byte)RpcCalls.SyncSettings, SendOption.None, player.GetClientId()); + messageWriter.WriteBytesAndSize(optionsByteArray); + AmongUsClient.Instance.FinishRpcImmediately(messageWriter); + } + } + public static void SendBetterCheck() { var flag = GameStates.IsHost && Main.BetterHost.Value; @@ -133,51 +149,6 @@ internal static class RPC player.Exiled(); } - public static void SendHostChatToPlayer(PlayerControl player, string text, string? title = "", bool sendToBetterUser = true) - { - if (!GameStates.IsHost) return; - - if (player.BetterData().IsBetterUser) - { - if (sendToBetterUser) - { - MessageWriter messageWriter2 = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, unchecked((byte)CustomRPC.AddChat), SendOption.None, player.GetClientId()); - messageWriter2.Write(text); - messageWriter2.Write(title); - AmongUsClient.Instance.FinishRpcImmediately(messageWriter2); - } - - return; - } - - /* - PlayerControl asPlayer = Main.AllPlayerControls.Where(pc => pc.IsAlive()).OrderBy(pc => pc == PlayerControl.LocalPlayer ? 0 : 1).First(); - - var oldName = asPlayer.CurrentOutfit.PlayerName; - if (title == "") - title = oldName; - - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(asPlayer.NetId, (byte)RpcCalls.SetName, SendOption.None, player.GetClientId()); - writer.Write(asPlayer.Data.NetId); - writer.Write(title); - AmongUsClient.Instance.FinishRpcImmediately(writer); - - MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(asPlayer.NetId, (byte)RpcCalls.SendChat, SendOption.None, player.GetClientId()); - messageWriter.Write(text); - AmongUsClient.Instance.FinishRpcImmediately(messageWriter); - - _ = new LateTask(() => - { - MessageWriter writer2 = AmongUsClient.Instance.StartRpcImmediately(asPlayer.NetId, (byte)RpcCalls.SetName, SendOption.None, player.GetClientId()); - writer2.Write(asPlayer.Data.NetId); - writer2.Write(oldName); - AmongUsClient.Instance.FinishRpcImmediately(writer2); - - SyncAllNames(force: true); - }, 0.08f, shoudLog: false); - */ - } - public static void HandleCustomRPC(PlayerControl player, byte callId, MessageReader oldReader) { if (PlayerControl.LocalPlayer == null || player == null || player == PlayerControl.LocalPlayer || player.Data == null) return; @@ -201,6 +172,8 @@ internal static class RPC player.BetterData().IsBetterUser = SetBetterUser; player.BetterData().IsBetterHost = IsBetterHost; + + SyncAllNames(force: true); } break; case (byte)CustomRPC.AddChat: diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 07c9046..dbea76f 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -289,4 +289,64 @@ public static class Utils return $"{Tag}: {PlatformName}"; } + + public static string GetPlatformName(Platforms platform, bool useTag = false) + { + string Tag = string.Empty; + + string PlatformName; + switch (platform) + { + case Platforms.StandaloneSteamPC: + PlatformName = "Steam"; + Tag = "PC"; + break; + case Platforms.StandaloneEpicPC: + PlatformName = "Epic Games"; + Tag = "PC"; + break; + case Platforms.StandaloneWin10: + PlatformName = "Microsoft Store"; + Tag = "PC"; + break; + case Platforms.StandaloneMac: + PlatformName = "Mac OS"; + Tag = "PC"; + break; + case Platforms.StandaloneItch: + PlatformName = "Itch.io"; + Tag = "PC"; + break; + case Platforms.Xbox: + PlatformName = "Xbox"; + Tag = "Console"; + break; + case Platforms.Playstation: + PlatformName = "Playstation"; + Tag = "Console"; + break; + case Platforms.Switch: + PlatformName = "Switch"; + Tag = "Console"; + break; + case Platforms.Android: + PlatformName = "Android"; + Tag = "Mobile"; + break; + case Platforms.IPhone: + PlatformName = "IPhone"; + Tag = "Mobile"; + break; + case Platforms.Unknown: + PlatformName = "None"; + break; + default: + return string.Empty; + } + + if (useTag == false) + return PlatformName; + + return $"{Tag}: {PlatformName}"; + } } \ No newline at end of file diff --git a/Patches/ChatPatch.cs b/Patches/ChatPatch.cs index 68e577d..22c9a53 100644 --- a/Patches/ChatPatch.cs +++ b/Patches/ChatPatch.cs @@ -125,7 +125,9 @@ class ChatPatch ChatBubble pooledBubble = __instance.GetPooledBubble(); try { - chatText = chatText.Replace("\n", ""); + if (sourcePlayer.BetterData().IsBetterUser && GameStates.IsBetterHostLobby) + chatText = chatText.Replace("\n", ""); + pooledBubble.transform.SetParent(__instance.scroller.Inner); pooledBubble.transform.localScale = Vector3.one; bool flag = sourcePlayer == PlayerControl.LocalPlayer; @@ -173,9 +175,10 @@ class ChatPatch if (sourcePlayer.IsDev()) sbTag.Append("Dev+++"); - if (((sourcePlayer == PlayerControl.LocalPlayer && GameStates.IsHost && Main.BetterHost.Value) || sourcePlayer.BetterData().IsBetterHost) && !GameStates.IsInGamePlay) + if (((sourcePlayer == PlayerControl.LocalPlayer && GameStates.IsHost && Main.BetterHost.Value) + || (sourcePlayer != PlayerControl.LocalPlayer && sourcePlayer.BetterData().IsBetterHost && sourcePlayer.IsHost()))) sbTag.Append("Better Host+++"); - else if ((sourcePlayer == PlayerControl.LocalPlayer || sourcePlayer.BetterData().IsBetterUser) && !GameStates.IsInGamePlay) + else if ((sourcePlayer == PlayerControl.LocalPlayer || sourcePlayer.BetterData().IsBetterUser)) sbTag.Append("Better User+++"); if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.SickoData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.SickoData.ContainsValue(friendCode)) diff --git a/Patches/ClientOptionsPatch.cs b/Patches/ClientOptionsPatch.cs index f811f98..8d94d53 100644 --- a/Patches/ClientOptionsPatch.cs +++ b/Patches/ClientOptionsPatch.cs @@ -10,7 +10,6 @@ public static class OptionsMenuBehaviourPatch { private static ClientOptionItem AntiCheat; private static ClientOptionItem BetterHost; - private static ClientOptionItem BetterRoleAlgorithma; private static ClientOptionItem BetterNotifications; private static ClientOptionItem ChatInGameplay; private static ClientOptionItem LobbyPlayerInfo; @@ -63,11 +62,6 @@ public static class OptionsMenuBehaviourPatch } } - if (BetterRoleAlgorithma == null || BetterRoleAlgorithma.ToggleButton == null) - { - BetterRoleAlgorithma = ClientOptionItem.Create("Better Role Algorithma", Main.BetterRoleAlgorithma, __instance, toggleCheck: () => !toggleCheckInGamePlay("Better Role Algorithma")); - } - if (BetterNotifications == null || BetterNotifications.ToggleButton == null) { BetterNotifications = ClientOptionItem.Create("Better Notifications", Main.BetterNotifications, __instance, BetterNotificationsToggle); diff --git a/Patches/CommandsPatch.cs b/Patches/CommandsPatch.cs index faa81dc..b618e98 100644 --- a/Patches/CommandsPatch.cs +++ b/Patches/CommandsPatch.cs @@ -246,8 +246,9 @@ class CommandsPatch { foreach (PlayerControl player in Main.AllPlayerControls) { + player.RpcExile(); player.roleAssigned = false; - player.RpcSetRole(RoleTypes.Crewmate, true); + player.RpcSetRole(RoleTypes.CrewmateGhost, true); } GameManager.Instance.RpcEndGame(GameOverReason.ImpostorByKill, false); return; @@ -302,11 +303,6 @@ class CommandsPatch case "role" or "setrole": if (HandleIsHost(command) == true) { - if (!Main.BetterRoleAlgorithma.Value) - { - Utils.AddChatPrivate($"{error}\nBetter Role Algorithma in better options must be turned on to use this command"); - return; - } if (command[0][1..].ToLower().Trim() == "role") { var player = PlayerControl.LocalPlayer; diff --git a/Patches/GamePlayManagerPatch.cs b/Patches/GamePlayManagerPatch.cs index 238d58a..d95bb02 100644 --- a/Patches/GamePlayManagerPatch.cs +++ b/Patches/GamePlayManagerPatch.cs @@ -61,6 +61,13 @@ class GamePlayManager } catch { } } + + [HarmonyPatch(nameof(LobbyBehaviour.RpcExtendLobbyTimer))] + [HarmonyPostfix] + private static void RpcExtendLobbyTimer_Postfix(/*LobbyBehaviour __instance*/) + { + GameStartManagerPatch.lobbyTimer += 30f; + } } [HarmonyPatch(typeof(IntroCutscene))] @@ -124,10 +131,23 @@ class GamePlayManager [HarmonyPatch(typeof(GameStartManager))] public class GameStartManagerPatch { + public static float lobbyTimer = 600f; + public static string lobbyTimerDisplay = ""; + [HarmonyPatch(nameof(GameStartManager.Start))] + [HarmonyPostfix] + private static void Start_Postfix(/*GameStartManager __instance*/) + { + lobbyTimer = 600f; + } [HarmonyPatch(nameof(GameStartManager.Update))] [HarmonyPrefix] private static void Update_Prefix(GameStartManager __instance) { + lobbyTimer = Mathf.Max(0f, lobbyTimer -= Time.deltaTime); + int minutes = (int)lobbyTimer / 60; + int seconds = (int)lobbyTimer % 60; + lobbyTimerDisplay = $"{minutes:00}:{seconds:00}"; + __instance.MinPlayers = 1; } [HarmonyPatch(nameof(GameStartManager.Update))] diff --git a/Patches/GameSettingMenuPatch.cs b/Patches/GameSettingMenuPatch.cs index 357bd57..34d0d43 100644 --- a/Patches/GameSettingMenuPatch.cs +++ b/Patches/GameSettingMenuPatch.cs @@ -16,10 +16,20 @@ class BetterGameSettings public static BetterOptionItem? DetectedLevelAbove; public static BetterOptionItem? DetectCheatClients; public static BetterOptionItem? DetectInvalidRPCs; + public static BetterOptionItem? RoleRandomizer; + public static BetterOptionItem? DesyncRoles; public static BetterOptionItem? ExperimentalDetectInvalidSabotage; } +class BetterGameSettingsTemp +{ + public static BetterOptionItem? HideAndSeekImp2; + public static BetterOptionItem? HideAndSeekImp3; + public static BetterOptionItem? HideAndSeekImp4; + public static BetterOptionItem? HideAndSeekImp5; +} + [HarmonyPatch(typeof(GameSettingMenu))] static class GameSettingMenuPatch { @@ -29,8 +39,8 @@ static class GameSettingMenuPatch public static void SetupSettings(bool IsPreload = false) { - BetterOptionItem.SpacingNum = 0; BetterOptionItem.BetterOptionItems.Clear(); + BetterOptionItem.TempPlayerOptionDataNum = 0; TitleList.Clear(); // Anti-Cheat Settings @@ -40,8 +50,8 @@ static class GameSettingMenuPatch if (IsPreload || GameStates.IsHost) { TitleList.Add(new BetterOptionTitleItem().Create(BetterSettingsTab, $"Host Only")); - BetterGameSettings.WhenCheating = new BetterOptionStringItem().Create(100, BetterSettingsTab, "When a player is caught cheating", ["Do Nothing", "Kick", "Ban"], 2); - BetterGameSettings.InvalidFriendCode = new BetterOptionCheckboxItem().Create(200, BetterSettingsTab, "Allow invalid friendCodes", true); + BetterGameSettings.WhenCheating = new BetterOptionStringItem().Create(100, BetterSettingsTab, "When a player is caught cheating", ["Notify", "Kick", "Ban"], 2); + BetterGameSettings.InvalidFriendCode = new BetterOptionCheckboxItem().Create(200, BetterSettingsTab, "Detected invalid FriendCodes", true); BetterGameSettings.UseBanPlayerList = new BetterOptionCheckboxItem().Create(300, BetterSettingsTab, "Use Ban Player List", true); BetterGameSettings.UseBanNameList = new BetterOptionCheckboxItem().Create(400, BetterSettingsTab, "Use Ban Name List", true); BetterGameSettings.UseBanWordList = new BetterOptionCheckboxItem().Create(500, BetterSettingsTab, "Use Ban Word List", true); @@ -49,7 +59,7 @@ static class GameSettingMenuPatch } TitleList.Add(new BetterOptionTitleItem().Create(BetterSettingsTab, $"Detections")); - BetterGameSettings.DetectedLevelAbove = new BetterOptionIntItem().Create(600, BetterSettingsTab, "Detected player level = or >", [100, 5000, 5], 200, "Lv ", ""); + BetterGameSettings.DetectedLevelAbove = new BetterOptionIntItem().Create(600, BetterSettingsTab, "Detected player levels >", [100, 5000, 5], 200, "Lv ", ""); BetterGameSettings.DetectCheatClients = new BetterOptionCheckboxItem().Create(700, BetterSettingsTab, "Detect Cheat Clients", true); BetterGameSettings.DetectInvalidRPCs = new BetterOptionCheckboxItem().Create(800, BetterSettingsTab, "Detect Invalid RPCs", true); @@ -58,6 +68,13 @@ static class GameSettingMenuPatch BetterGameSettings.ExperimentalDetectInvalidSabotage = new BetterOptionCheckboxItem().Create(100000, BetterSettingsTab, "Detect Invalid Sabotages", false); } + if (IsPreload || GameStates.IsHost) + { + TitleList.Add(new BetterOptionHeaderItem().Create(BetterSettingsTab, "Role Algorithm Settings")); + BetterGameSettings.RoleRandomizer = new BetterOptionStringItem().Create(1100, BetterSettingsTab, "Randomizer", ["System.Random", "UnityEngine.Random"], 0); + BetterGameSettings.DesyncRoles = new BetterOptionCheckboxItem().Create(1200, BetterSettingsTab, "Desync Roles To Other Clients", true); + } + // Gameplay Settings { if (IsPreload || GameStates.IsHost) @@ -69,28 +86,41 @@ static class GameSettingMenuPatch else if (IsPreload || GameStates.IsHideNSeek) { new BetterOptionHeaderItem().Create(BetterSettingsTab, "Hide & Seek Settings"); - - if (IsPreload || Main.BetterRoleAlgorithma.Value) + new BetterOptionTitleItem().Create(BetterSettingsTab, $"Imposter"); + BetterGameSettings.HideAndSeekImpNum = new BetterOptionIntItem().Create(1000, BetterSettingsTab, "# Seekers", [1, 5, 1], 1, "", ""); + BetterGameSettingsTemp.HideAndSeekImp2 = new BetterOptionPlayerItem().Create(BetterSettingsTab, "Seeker", BetterGameSettings.HideAndSeekImpNum, new Func(() => { - new BetterOptionTitleItem().Create(BetterSettingsTab, $"Better Role Algorithma"); - BetterOptionItem.SpacingNum += 0.2f; - new BetterOptionTitleItem().Create(BetterSettingsTab, $"Imposter"); - BetterGameSettings.HideAndSeekImpNum = new BetterOptionIntItem().Create(1000, BetterSettingsTab, "# Seekers", [1, 5, 1], 1, "", ""); - } + return BetterGameSettings.HideAndSeekImpNum is BetterOptionIntItem betterOption && betterOption.CurrentValue > 1; + })); + BetterGameSettingsTemp.HideAndSeekImp3 = new BetterOptionPlayerItem().Create(BetterSettingsTab, "Seeker", BetterGameSettings.HideAndSeekImpNum, new Func(() => + { + return BetterGameSettings.HideAndSeekImpNum is BetterOptionIntItem betterOption && betterOption.CurrentValue > 2 + && BetterGameSettingsTemp.HideAndSeekImp2 is BetterOptionPlayerItem betterOption2 && betterOption2.CurrentIndex > -1; + })); + BetterGameSettingsTemp.HideAndSeekImp4 = new BetterOptionPlayerItem().Create(BetterSettingsTab, "Seeker", BetterGameSettings.HideAndSeekImpNum, new Func(() => + { + return BetterGameSettings.HideAndSeekImpNum is BetterOptionIntItem betterOption && betterOption.CurrentValue > 3 + && BetterGameSettingsTemp.HideAndSeekImp2 is BetterOptionPlayerItem betterOption2 && betterOption2.CurrentIndex > -1 + && BetterGameSettingsTemp.HideAndSeekImp3 is BetterOptionPlayerItem betterOption3 && betterOption3.CurrentIndex > -1; + })); + BetterGameSettingsTemp.HideAndSeekImp5 = new BetterOptionPlayerItem().Create(BetterSettingsTab, "Seeker", BetterGameSettings.HideAndSeekImpNum, new Func(() => + { + return BetterGameSettings.HideAndSeekImpNum is BetterOptionIntItem betterOption && betterOption.CurrentValue > 4 + && BetterGameSettingsTemp.HideAndSeekImp2 is BetterOptionPlayerItem betterOption2 && betterOption2.CurrentIndex > -1 + && BetterGameSettingsTemp.HideAndSeekImp3 is BetterOptionPlayerItem betterOption3 && betterOption3.CurrentIndex > -1 + && BetterGameSettingsTemp.HideAndSeekImp4 is BetterOptionPlayerItem betterOption4 && betterOption4.CurrentIndex > -1; + })); } } } /* - new BetterOptionCheckboxItem().Create(0, BetterSettingsTab, "CheckBox Test", true); - new BetterOptionStringItem().Create(1, BetterSettingsTab, "String Test", ["Test 1", "Test 2", "Test 3"]); - new BetterOptionFloatItem().Create(2, BetterSettingsTab, "Float Test 1", [0f, 180f, 2.5f], 0f, ""); - new BetterOptionIntItem().Create(5, BetterSettingsTab, "Int Test", [0, 5, 1], 0, ""); + new BetterOptionCheckboxItem().Create(10000, BetterSettingsTab, "CheckBox Test", true); + new BetterOptionStringItem().Create(10001, BetterSettingsTab, "String Test", ["Test 1", "Test 2", "Test 3"], 0); + new BetterOptionFloatItem().Create(10002, BetterSettingsTab, "Float Test 1", [0f, 180f, 2.5f], 0f, "", ""); + new BetterOptionIntItem().Create(10003, BetterSettingsTab, "Int Test", [0, 5, 1], 0, "", ""); new BetterOptionHeaderItem().Create(BetterSettingsTab, "Test Settings 2"); */ - - if (BetterSettingsTab != null) - BetterSettingsTab.scrollBar.SetYBoundsMax(1.25f * BetterOptionItem.SpacingNum / 2); } private static void Initialize() @@ -101,12 +131,16 @@ static class GameSettingMenuPatch { if (item != null) { + item.obj.SetActive(true); + if (item.TitleText != null) { item.TitleText.text = item.Name; } } } + + BetterOptionItem.UpdatePositions(); }, 0.005f, shoudLog: false); } @@ -159,6 +193,7 @@ static class GameSettingMenuPatch BetterSettingsButton.OnClick.AddListener(new Action(() => { __instance.ChangeTab(3, false); + BetterOptionItem.UpdatePositions(); })); BetterSettingsTab = UnityEngine.Object.Instantiate(__instance.GameSettingsTab, __instance.GameSettingsTab.transform.parent); @@ -275,8 +310,17 @@ static class NumberOptionPatch if (Input.GetKey(KeyCode.LeftControl)) times = 10; - __instance.Value += __instance.Increment * times; + if (__instance.Value + __instance.Increment * times > __instance.ValidRange.max) + { + __instance.Value = __instance.ValidRange.max; + } + else + { + __instance.Value = __instance.ValidRange.Clamp(__instance.Value + __instance.Increment * times); + } __instance.UpdateValue(); + __instance.OnValueChanged.Invoke(__instance); + __instance.AdjustButtonsActiveState(); return false; } @@ -290,56 +334,17 @@ static class NumberOptionPatch if (Input.GetKey(KeyCode.LeftControl)) times = 10; - __instance.Value -= __instance.Increment * times; + if (__instance.Value - __instance.Increment * times < __instance.ValidRange.min) + { + __instance.Value = __instance.ValidRange.min; + } + else + { + __instance.Value = __instance.ValidRange.Clamp(__instance.Value - __instance.Increment * times); + } __instance.UpdateValue(); - return false; - } - - [HarmonyPatch(nameof(NumberOption.UpdateValue))] - [HarmonyPrefix] - public static bool UpdateValue_Prefix(NumberOption __instance) - { - if (__instance.floatOptionName != FloatOptionNames.Invalid) - { - GameOptionsManager.Instance.CurrentGameOptions.SetFloat(__instance.floatOptionName, __instance.GetFloat()); - return false; - } - if (__instance.intOptionName != Int32OptionNames.Invalid) - { - GameOptionsManager.Instance.CurrentGameOptions.SetInt(__instance.intOptionName, __instance.GetInt()); - return false; - } - return false; - } - - [HarmonyPatch(nameof(NumberOption.FixedUpdate))] - [HarmonyPrefix] - public static bool FixedUpdate_Prefix(NumberOption __instance) - { - try - { - if (__instance.MinusBtn != null && __instance.PlusBtn != null) - { - __instance.MinusBtn.SetInteractable(true); - __instance.PlusBtn.SetInteractable(true); - } - - if (__instance.oldValue != __instance.Value) - { - __instance.oldValue = __instance.Value; - - if (__instance.Value > __instance.ValidRange.max || __instance.Value < __instance.ValidRange.min) - { - __instance.ValueText.text = $"{__instance.data.GetValueString(__instance.Value)}"; - } - else - { - __instance.ValueText.text = __instance.data.GetValueString(__instance.Value); - } - } - } - catch { } - + __instance.OnValueChanged.Invoke(__instance); + __instance.AdjustButtonsActiveState(); return false; } } \ No newline at end of file diff --git a/Patches/MatchMakerGameButtonPatch.cs b/Patches/MatchMakerGameButtonPatch.cs new file mode 100644 index 0000000..fe60923 --- /dev/null +++ b/Patches/MatchMakerGameButtonPatch.cs @@ -0,0 +1,16 @@ +using InnerNet; +using HarmonyLib; + +namespace BetterAmongUs; + +[HarmonyPatch(typeof(MatchMakerGameButton))] +class MatchMakerGameButtonPatch +{ + [HarmonyPatch(nameof(MatchMakerGameButton.SetGame))] + [HarmonyPostfix] + private static void SetGame_Postfix(MatchMakerGameButton __instance) + { + __instance.NameText.text = $"{__instance.myListing.HostName}\n"; + __instance.NameText.text += $"{Utils.GetPlatformName(__instance.myListing.Platform)} - {GameCode.IntToGameName(__instance.myListing.GameId)}"; + } +} \ No newline at end of file diff --git a/Patches/PingTrackerPatch.cs b/Patches/PingTrackerPatch.cs index 8d800ce..72dfb31 100644 --- a/Patches/PingTrackerPatch.cs +++ b/Patches/PingTrackerPatch.cs @@ -1,6 +1,7 @@ using HarmonyLib; using System.Text; using UnityEngine; +using static BetterAmongUs.Patches.GamePlayManager; namespace BetterAmongUs.Patches; @@ -23,6 +24,12 @@ public class PingTrackerPatch StringBuilder sb = new StringBuilder(); sb.AppendFormat("PING: {0}\n", GetPingColor(AmongUsClient.Instance.Ping)); + + if (GameStates.IsLobby && GameStates.IsHost && GameStates.IsVanillaServer && !GameStates.IsLocalGame) + { + sb.AppendFormat("Timer: {0}\n", GetTimeColor(GameStartManagerPatch.lobbyTimer)); + } + sb.Append($"BetterAmongUs {Main.GetVersionText(true)}\n"); sb.AppendFormat("{0}\n", Main.Github); @@ -76,4 +83,30 @@ public class PingTrackerPatch return newPing; } + + private static string GetTimeColor(float time) + { + float minutes = (int)time / 60 + 1f; + + string color; + switch (minutes) + { + case float n when n <= 1: + color = "#ff0000"; + break; + case float n when n <= 3.5f: + color = "#ffa200"; + break; + case float n when n <= 5f: + color = "#ffff00"; + break; + default: + color = "#00f04c"; + break; + } + + string newTime = $"{GameStartManagerPatch.lobbyTimerDisplay}"; + + return newTime; + } } diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index dbf63fb..aa5a9b8 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -128,11 +128,8 @@ class PlayerControlPatch } var sbTag = new StringBuilder(); - var sbInfo = new StringBuilder(); var sbTagTop = new StringBuilder(); - var sbInfoTop = new StringBuilder(); var sbTagBottom = new StringBuilder(); - var sbInfoBottom = new StringBuilder(); // Put +++ at the end of each tag if (!player.isDummy) @@ -182,6 +179,20 @@ class PlayerControlPatch sbTagTop.Append($"{Role}+++"); } } + else if (GameStates.IsInGame || GameStates.IsFreePlay) + { + if (player == PlayerControl.LocalPlayer) + { + if (player.IsImpostorTeam()) + { + sbTagTop.Append($"Seeker+++"); + } + else + { + sbTagTop.Append($"Hider+++"); + } + } + } if (player.IsImpostorTeammate() && player != PlayerControl.LocalPlayer) { @@ -194,8 +205,9 @@ class PlayerControlPatch } // Put +++ at the end of each tag - void AppendTagInfo(StringBuilder source, StringBuilder destination) + static StringBuilder FormatInfo(StringBuilder source) { + var sb = new StringBuilder(); if (source.Length > 0) { string text = source.ToString(); @@ -204,23 +216,25 @@ class PlayerControlPatch { if (!string.IsNullOrEmpty(Utils.RemoveHtmlText(parts[i]))) { - destination.Append(parts[i]); + sb.Append(parts[i]); if (i != parts.Length - 2) { - destination.Append(" - "); + sb.Append(" - "); } } } } + + return sb; } - AppendTagInfo(sbTag, sbInfo); - AppendTagInfo(sbTagTop, sbInfoTop); - AppendTagInfo(sbTagBottom, sbInfoBottom); + sbTag = FormatInfo(sbTag); + sbTagTop = FormatInfo(sbTagTop); + sbTagBottom = FormatInfo(sbTagBottom); - player.SetPlayerTextInfo(sbInfoTop.ToString()); - player.SetPlayerTextInfo(sbInfoBottom.ToString(), isBottom: true); - player.SetPlayerTextInfo(sbInfo.ToString(), isInfo: true); + player.SetPlayerTextInfo(sbTagTop.ToString()); + player.SetPlayerTextInfo(sbTagBottom.ToString(), isBottom: true); + player.SetPlayerTextInfo(sbTag.ToString(), isInfo: true); } catch (Exception ex) { diff --git a/Patches/PlayerJoinAndLeftPatch.cs b/Patches/PlayerJoinAndLeftPatch.cs index 17e9a4e..9dc1a53 100644 --- a/Patches/PlayerJoinAndLeftPatch.cs +++ b/Patches/PlayerJoinAndLeftPatch.cs @@ -52,9 +52,6 @@ public static class OnPlayerJoinedPatch RPC.SyncAllNames(force: true); - if (Main.BetterHost.Value) - client.Character.RpcSendHostChat(HudManagerPatch.WelcomeMessage, sendToBetterUser: false); - // Auto ban player on ban list if (BetterGameSettings.UseBanPlayerList.GetBool()) { diff --git a/Patches/RoleManagerPatch.cs b/Patches/RoleManagerPatch.cs index eb4ad5f..7b67c8e 100644 --- a/Patches/RoleManagerPatch.cs +++ b/Patches/RoleManagerPatch.cs @@ -21,8 +21,6 @@ public class RoleManagerPatch [HarmonyPrefix] public static bool RoleManager_Prefix(/*RoleManager __instance*/) { - if (!Main.BetterRoleAlgorithma.Value) return true; - if (!GameStates.IsHideNSeek) { RegularBetterRoleAssignment(); @@ -140,19 +138,22 @@ public class RoleManagerPatch player.RpcSetRole(role); // Desync role to other clients to prevent revealing the true role - if (IsImpostorRole(role) && role is not RoleTypes.Phantom) + if (BetterGameSettings.DesyncRoles.GetBool()) { - List messageWriter = AmongUsClient.Instance.StartRpcDesync(player.NetId, (byte)RpcCalls.SetRole, SendOption.None, player.GetClientId(), clientCheck); - messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Impostor)); - messageWriter.ForEach(mW => mW.Write(false)); - AmongUsClient.Instance.FinishRpcDesync(messageWriter); - } - else if (role is not RoleTypes.Noisemaker) - { - List messageWriter = AmongUsClient.Instance.StartRpcDesync(player.NetId, (byte)RpcCalls.SetRole, SendOption.None, player.GetClientId(), clientCheck); - messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Crewmate)); - messageWriter.ForEach(mW => mW.Write(false)); - AmongUsClient.Instance.FinishRpcDesync(messageWriter); + if (IsImpostorRole(role) && role is not RoleTypes.Phantom) + { + List messageWriter = AmongUsClient.Instance.StartRpcDesync(player.NetId, (byte)RpcCalls.SetRole, SendOption.None, player.GetClientId(), clientCheck); + messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Impostor)); + messageWriter.ForEach(mW => mW.Write(false)); + AmongUsClient.Instance.FinishRpcDesync(messageWriter); + } + else if (role is not RoleTypes.Noisemaker) + { + List messageWriter = AmongUsClient.Instance.StartRpcDesync(player.NetId, (byte)RpcCalls.SetRole, SendOption.None, player.GetClientId(), clientCheck); + messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Crewmate)); + messageWriter.ForEach(mW => mW.Write(false)); + AmongUsClient.Instance.FinishRpcDesync(messageWriter); + } } player.roleAssigned = true; @@ -192,14 +193,19 @@ public class RoleManagerPatch ImpostorRoles[kvp.Key]--; Impostors.Add(pc); pc.RpcSetRole(kvp.Key); + // Desync role to other clients to prevent revealing the true role - if (kvp.Key is not RoleTypes.Phantom) + if (BetterGameSettings.DesyncRoles.GetBool()) { - List messageWriter = AmongUsClient.Instance.StartRpcDesync(pc.NetId, (byte)RpcCalls.SetRole, SendOption.None, pc.GetClientId(), clientCheck); - messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Impostor)); - messageWriter.ForEach(mW => mW.Write(false)); - AmongUsClient.Instance.FinishRpcDesync(messageWriter); + if (kvp.Key is not RoleTypes.Phantom) + { + List messageWriter = AmongUsClient.Instance.StartRpcDesync(pc.NetId, (byte)RpcCalls.SetRole, SendOption.None, pc.GetClientId(), clientCheck); + messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Impostor)); + messageWriter.ForEach(mW => mW.Write(false)); + AmongUsClient.Instance.FinishRpcDesync(messageWriter); + } } + pc.roleAssigned = true; Logger.Log($"Assigned {Utils.GetRoleName(kvp.Key)} role to {pc.Data.PlayerName}", "RoleManager"); break; @@ -226,14 +232,19 @@ public class RoleManagerPatch CrewmateRoles[kvp.Key]--; Crewmates.Add(pc); pc.RpcSetRole(kvp.Key); + // Desync role to other clients to prevent revealing the true role - if (kvp.Key is not RoleTypes.Noisemaker) + if (BetterGameSettings.DesyncRoles.GetBool()) { - List messageWriter = AmongUsClient.Instance.StartRpcDesync(pc.NetId, (byte)RpcCalls.SetRole, SendOption.None, pc.GetClientId(), clientCheck); - messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Crewmate)); - messageWriter.ForEach(mW => mW.Write(false)); - AmongUsClient.Instance.FinishRpcDesync(messageWriter); + if (kvp.Key is not RoleTypes.Noisemaker) + { + List messageWriter = AmongUsClient.Instance.StartRpcDesync(pc.NetId, (byte)RpcCalls.SetRole, SendOption.None, pc.GetClientId(), clientCheck); + messageWriter.ForEach(mW => mW.Write((ushort)RoleTypes.Crewmate)); + messageWriter.ForEach(mW => mW.Write(false)); + AmongUsClient.Instance.FinishRpcDesync(messageWriter); + } } + pc.roleAssigned = true; Logger.Log($"Assigned {Utils.GetRoleName(kvp.Key)} role to {pc.Data.PlayerName}", "RoleManager"); break; @@ -286,10 +297,41 @@ public class RoleManagerPatch Impostors.Add(player); player.RpcSetRole(RoleTypes.Impostor); player.roleAssigned = true; + NumImpostors--; Logger.Log($"Settings Assigned {Utils.GetRoleName(RoleTypes.Impostor)} role to {player.Data.PlayerName}", "RoleManager"); } } + var betterImpostorSettings = new int[] + { + -1, + BetterGameSettingsTemp.HideAndSeekImp2.GetValue(), + BetterGameSettingsTemp.HideAndSeekImp3.GetValue(), + BetterGameSettingsTemp.HideAndSeekImp4.GetValue(), + BetterGameSettingsTemp.HideAndSeekImp5.GetValue() + }; + + for (int i = 1; i < BetterGameSettings.HideAndSeekImpNum.GetInt(); i++) + { + int tempSetImpostor = betterImpostorSettings[i]; + + if (tempSetImpostor >= 0) + { + var player = Utils.PlayerFromId(tempSetImpostor); + if (player != null) + { + if (NumImpostors > 0 && !Impostors.Contains(player)) + { + Impostors.Add(player); + player.RpcSetRole(RoleTypes.Impostor); + player.roleAssigned = true; + NumImpostors--; + Logger.Log($"Settings Assigned {Utils.GetRoleName(RoleTypes.Impostor)} role to {player.Data.PlayerName}", "RoleManager"); + } + } + } + } + // Override player role assignment if (SetPlayerRole.Keys.Any()) { @@ -377,8 +419,6 @@ public class RoleManagerPatch [HarmonyPrefix] public static bool AssignRoleOnDeath_Prefix(/*RoleManager __instance*/ [HarmonyArgument(0)] PlayerControl player) { - if (!Main.BetterRoleAlgorithma.Value) return true; - Dictionary GhostRoles = new() // Role, Amount { { RoleTypes.GuardianAngel, 0 }, @@ -411,11 +451,16 @@ public class RoleManagerPatch if (kvp.Value > 0 && RNG() <= GameOptionsManager.Instance.CurrentGameOptions.RoleOptions.GetChancePerGame(kvp.Key)) { player.RpcSetRole(kvp.Key); + // Desync role to other clients to prevent revealing the true role - List messageWriter = AmongUsClient.Instance.StartRpcDesync(player.NetId, (byte)RpcCalls.SetRole, SendOption.None, player.GetClientId(), clientCheck); - messageWriter.ForEach(mW => mW.Write((ushort)player.Data.Role.DefaultGhostRole)); - messageWriter.ForEach(mW => mW.Write(false)); - AmongUsClient.Instance.FinishRpcDesync(messageWriter); + if (BetterGameSettings.DesyncRoles.GetBool()) + { + List messageWriter = AmongUsClient.Instance.StartRpcDesync(player.NetId, (byte)RpcCalls.SetRole, SendOption.None, player.GetClientId(), clientCheck); + messageWriter.ForEach(mW => mW.Write((ushort)player.Data.Role.DefaultGhostRole)); + messageWriter.ForEach(mW => mW.Write(false)); + AmongUsClient.Instance.FinishRpcDesync(messageWriter); + } + return false; } } @@ -450,5 +495,16 @@ public class RoleManagerPatch return shuffledDictionary; } - private static int RNG() => random.Next(0, 100); + public static int RNG() + { + switch (BetterGameSettings.RoleRandomizer.GetValue()) + { + case 1: + return UnityEngine.Random.Range(0, 100); + + default: + Random Random = new Random(); + return Random.Next(0, 100); + } + } } \ No newline at end of file diff --git a/Patches/VersionShowerPatch.cs b/Patches/VersionShowerPatch.cs index f3a489e..16c03e5 100644 --- a/Patches/VersionShowerPatch.cs +++ b/Patches/VersionShowerPatch.cs @@ -9,6 +9,6 @@ public class VersionShowerPatch [HarmonyPostfix] public static void Postfix(VersionShower __instance) { - __instance.text.text = $"♻BetterAmongUs♻ {Main.GetVersionText()} - " + __instance.text.text; + __instance.text.text = $"♻BetterAmongUs♻ {Main.GetVersionText()} ~ {Utils.GetPlatformName(Main.PlatformData.Platform)} v{Main.AmongUsVersion}"; } } diff --git a/Resources/ModNews/BAU.v1.1.0.txt b/Resources/ModNews/BAU.v1.1.0.txt new file mode 100644 index 0000000..629eab0 --- /dev/null +++ b/Resources/ModNews/BAU.v1.1.0.txt @@ -0,0 +1,47 @@ +#Number:110002 +#Title:Better Among Us v1.1.0 +#SubTitle:Settings Galore! +#ShortTitle:BAU v1.1.0 +#Date:2024-8-24T00:00:00Z +#----------------------------- +We are thrilled to announce the release of BetterAmongUs v1.1.0 +# +BetterAmongUs comes packed with a variety of features designed to improve your gameplay experience: +# +Change Log +# +Client +New: Added new intro on boot up +New: Added ability to skip intro by clicking the left or right Mouse button +New: Added Better Option to have chat always visible +Fixed: All players appearing in the role intro +# +Lobby Settings +New: Added the ability to bypass number restrictions in lobby settings +New: Added Better Settings tab with new settings +New: Game Settings is now the default tab when opening lobby settings panel +New: Lobby Settings panel is now available for Non-Host but only Better Settings is editable +Hide And Seek +New: Added Better Setting to set imposter amount +Requires Better Role Algorithm +# +Anti-Cheat +Added list of Better Settings +1. When a player is caught cheating +2. Allow invalid friendCodes +3. Use Ban Player List +4. Use Ban Name List +5. Use Ban Word List +6. Detected player level = or > +7. Detect Cheat Clients +8. Detect Invalid RPCs +9. Detect Invalid Sabotages // Needs testing! +# +# +Issues & Bugs +# +- If you encounter any issues or have feedback, please report them on our Github Issues Page or Bug Reports channel in the BAU Discord Server. +# +Thank you for your support, and we hope you enjoy the new features of BetterAmongUs! +# +Discord Github diff --git a/main.cs b/main.cs index bbd2247..8db4991 100644 --- a/main.cs +++ b/main.cs @@ -27,8 +27,8 @@ public class Main : BasePlugin public const string HotfixNum = "0"; public const bool IsHotFix = false; public const string PluginGuid = "com.d1gq.betteramongus"; - public const string PluginVersion = "1.1.0"; - public const string ReleaseDate = "08.24.2024"; // mm/dd/yyyy + public const string PluginVersion = "1.1.1"; + public const string ReleaseDate = "08.25.2024"; // mm/dd/yyyy public const string Github = "https://github.com/D1GQ/BetterAmongUs-Public"; public const string Discord = "https://discord.gg/vjYrXpzNAn"; @@ -84,6 +84,8 @@ public class Main : BasePlugin public static string BetterAmongUsVersion => PluginVersion; public static string AmongUsVersion => Application.version; + public static PlatformSpecificData PlatformData => Constants.GetPlatformData(); + public static List SupportedAmongUsVersions = [ "2024.8.13", @@ -143,7 +145,7 @@ public class Main : BasePlugin BetterDataManager.LoadData(); LoadOptions(); - if (File.Exists(Path.Combine($"{Environment.CurrentDirectory}/Among Us_Data/Plugins/x86", "steam_api.dll"))) + if (PlatformData.Platform == Platforms.StandaloneSteamPC) File.WriteAllText(Path.Combine(Environment.CurrentDirectory, "steam_appid.txt"), "945360"); if (File.Exists(Path.Combine(BetterDataManager.filePathFolder, "better-log.txt"))) @@ -164,7 +166,7 @@ public class Main : BasePlugin string SupportedVersions = string.Empty; foreach (string text in SupportedAmongUsVersions.ToArray()) SupportedVersions += $"{text} "; - BetterAmongUs.Logger.Log($"BetterAmongUs {BetterAmongUsVersion}-{ReleaseDate} - [{AmongUsVersion} --> {SupportedVersions.Substring(0, SupportedVersions.Length - 1)}]"); + BetterAmongUs.Logger.Log($"BetterAmongUs {BetterAmongUsVersion}-{ReleaseDate} - [{AmongUsVersion} --> {SupportedVersions.Substring(0, SupportedVersions.Length - 1)}] {Utils.GetPlatformName(PlatformData.Platform)}"); } catch (Exception ex) { @@ -174,7 +176,6 @@ public class Main : BasePlugin public static ConfigEntry AntiCheat { get; private set; } public static ConfigEntry BetterHost { get; private set; } - public static ConfigEntry BetterRoleAlgorithma { get; private set; } public static ConfigEntry BetterNotifications { get; private set; } public static ConfigEntry ChatInGameplay { get; private set; } public static ConfigEntry LobbyPlayerInfo { get; private set; } @@ -186,7 +187,6 @@ public class Main : BasePlugin { AntiCheat = Config.Bind("Better Options", "AntiCheat", true); BetterHost = Config.Bind("Better Options", "BetterHost", false); - BetterRoleAlgorithma = Config.Bind("Better Options", "BetterRoleAlgorithma", true); BetterNotifications = Config.Bind("Better Options", "BetterNotifications", true); ChatInGameplay = Config.Bind("Better Options", "ChatInGameplay", true); LobbyPlayerInfo = Config.Bind("Better Options", "LobbyPlayerInfo", true);