Decompiled source of BetterVanilla v1.1.10
BetterVanilla.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using AmongUs.Data; using AmongUs.GameOptions; using AmongUsDevKit.LibraryRuntime; using BepInEx; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Utils; using BetterVanilla.Components; using BetterVanilla.Components.BaseComponents; using BetterVanilla.Components.Menu; using BetterVanilla.Components.Menu.Outfits; using BetterVanilla.Components.Menu.Settings; using BetterVanilla.Core; using BetterVanilla.Core.Attributes; using BetterVanilla.Core.Data; using BetterVanilla.Core.Data.Legacy; using BetterVanilla.Core.Extensions; using BetterVanilla.Core.Helpers; using BetterVanilla.Core.Options; using Cpp2IL.Core.Extensions; using HarmonyLib; using Hazel; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.InteropTypes.Fields; using Il2CppSystem; using Il2CppSystem.Collections; using Il2CppSystem.Collections.Generic; using InnerNet; using Innersloth.Assets; using Microsoft.CodeAnalysis; using MonoMod.Utils; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("BetterVanilla.Mono")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Enhanced Among Us Vanilla experience")] [assembly: AssemblyFileVersion("1.1.10.0")] [assembly: AssemblyInformationalVersion("1.1.10+4cb6b6ae300f2f9f8c8148ae17b86d8a7f22a57d")] [assembly: AssemblyProduct("BetterVanilla.Mono")] [assembly: AssemblyTitle("BetterVanilla.Mono")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.10.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BetterVanilla { [BepInPlugin("bettervanilla.eno.pm", "BetterVanilla", "1.1.10")] public class BetterVanillaPlugin : BasePlugin { public override void Load() { MainInterop.__m_K5zv8eLaRFhl0AIeb8k3Rn1N44spwTNr0u(); Ls.SetLogSource(((BasePlugin)this).Log); ((BasePlugin)this).AddComponent<BetterVanillaManager>(); } } } namespace BetterVanilla.Compiler { internal static class GeneratedProps { public const string Guid = "bettervanilla.eno.pm"; public const string Name = "BetterVanilla"; public const string Version = "1.1.10"; } } namespace BetterVanilla.Core { public sealed class BetterRoleAssignments { private const int BaseWeight = 100; private const int PenaltyForNonPreferredTeam = 15; private const int BonusForForcedAssignment = 200; private readonly IGameOptions _currentOptions; private readonly int _numImpostors; private readonly List<PlayerControl> _allPlayers = new List<PlayerControl>(); private readonly List<PlayerControl> _remainingPlayers = new List<PlayerControl>(); private readonly Dictionary<int, TeamPreferences> _playerPreferences = new Dictionary<int, TeamPreferences>(); private readonly Dictionary<int, TeamPreferences> _playerForcedAssignments = new Dictionary<int, TeamPreferences>(); private readonly List<RoleTypes> _allCrewmateRoles = new List<RoleTypes>(); private readonly List<RoleTypes> _allImpostorRoles = new List<RoleTypes>(); public BetterRoleAssignments() { Enumerator<PlayerControl> enumerator = PlayerControl.AllPlayerControls.GetEnumerator(); while (enumerator.MoveNext()) { PlayerControl current = enumerator.Current; if (Object.op_Implicit((Object)(object)current) && Object.op_Implicit((Object)(object)current.Data) && !current.Data.Disconnected && !current.Data.IsDead) { _allPlayers.Add(current); } } _currentOptions = GameOptionsManager.Instance.CurrentGameOptions; _numImpostors = IGameOptionsExtensions.GetAdjustedNumImpostors(GameOptionsManager.Instance.CurrentGameOptions, _allPlayers.Count); _remainingPlayers.AddRange(_allPlayers); SetupRoles(); } public void SetTeamPreference(int playerId, TeamPreferences preference) { _playerPreferences[playerId] = preference; } public void SetTeamPreferences(Dictionary<int, TeamPreferences> preferences) { foreach (KeyValuePair<int, TeamPreferences> preference in preferences) { SetTeamPreference(preference.Key, preference.Value); } } public void SetForcedAssignment(int playerId, TeamPreferences preference) { _playerForcedAssignments[playerId] = preference; } public void SetForcedAssignments(Dictionary<int, TeamPreferences> preferences) { foreach (KeyValuePair<int, TeamPreferences> preference in preferences) { SetForcedAssignment(preference.Key, preference.Value); } } private void SetupRoles() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Invalid comparison between Unknown and I4 //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) IRoleOptionsCollection roleOptions = _currentOptions.RoleOptions; foreach (RoleBehaviour item in (Il2CppArrayBase<RoleBehaviour>)(object)DestroyableSingleton<RoleManager>.Instance.AllRoles) { RoleTeamTypes teamType = item.TeamType; RoleTypes role = item.Role; int numPerGame = roleOptions.GetNumPerGame(role); int chancePerGame = roleOptions.GetChancePerGame(role); if (chancePerGame == 0 || numPerGame == 0) { continue; } bool flag = chancePerGame < 100; for (int i = 0; i < numPerGame; i++) { if (!flag || HashRandom.Next(101) < chancePerGame) { if ((int)teamType == 0) { _allCrewmateRoles.Add(role); } else if ((int)teamType == 1) { _allImpostorRoles.Add(role); } } } } } private Dictionary<byte, int> CalculateWeights(RoleTeamTypes team, bool ignorePlayerPreferences = false) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Dictionary<byte, int> dictionary = new Dictionary<byte, int>(); TeamPreferences teamPreferences = ConvertRoleTeamTypeToTeamPreference(team); TeamPreferences? opposite = GetOpposite(teamPreferences); foreach (PlayerControl remainingPlayer in _remainingPlayers) { TeamPreferences forcedAssignmentForPlayer = GetForcedAssignmentForPlayer(remainingPlayer); byte playerId = remainingPlayer.PlayerId; TeamPreferences preferenceForPlayer = GetPreferenceForPlayer(remainingPlayer); int num = 100; if (!ignorePlayerPreferences && preferenceForPlayer != TeamPreferences.Both && preferenceForPlayer != teamPreferences) { num -= 15; } if (forcedAssignmentForPlayer != TeamPreferences.Both) { num = ((forcedAssignmentForPlayer != opposite) ? 200 : 0); } if (num > 0) { dictionary[playerId] = num; } } return dictionary; } private List<PlayerControl> PickRandomPlayersBasedOnWeights(Dictionary<byte, int> weights, int amount) { List<PlayerControl> list = new List<PlayerControl>(); Dictionary<byte, int> dictionary = Enumerable.ToDictionary(weights, (KeyValuePair<byte, int> entry) => entry.Key, (KeyValuePair<byte, int> entry) => entry.Value); for (int i = 0; i < amount; i++) { if (dictionary.Count == 0) { break; } int num = Enumerable.Sum(dictionary.Values); int num2 = Random.Range(0, num); byte selectedPlayerId = 0; foreach (byte key in dictionary.Keys) { if (num2 < dictionary[key]) { selectedPlayerId = key; break; } num2 -= dictionary[key]; } PlayerControl item = Enumerable.First(_remainingPlayers, (PlayerControl x) => x.PlayerId == selectedPlayerId); list.Add(item); _remainingPlayers.Remove(item); dictionary.Remove(selectedPlayerId); } return list; } private List<PlayerControl> GetTeam(RoleTeamTypes teamType, int teamSize) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Dictionary<byte, int> weights = CalculateWeights(teamType, !BetterVanillaManager.Instance.HostOptions.AllowTeamPreference.GetBool()); return PickRandomPlayersBasedOnWeights(weights, teamSize); } private static Dictionary<PlayerControl, RoleTypes> GetRolesAssignation(List<PlayerControl> players, List<RoleTypes> roles, RoleTypes defaultRole) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) Dictionary<PlayerControl, RoleTypes> dictionary = new Dictionary<PlayerControl, RoleTypes>(); foreach (PlayerControl player in players) { RoleTypes value = ((roles.Count > 0) ? roles.PickOneRandom() : defaultRole); dictionary.Add(player, value); } return dictionary; } public void StartAssignation() { int teamSize = Mathf.Max(1, _numImpostors); List<PlayerControl> team = GetTeam((RoleTeamTypes)1, teamSize); int count = _remainingPlayers.Count; List<PlayerControl> team2 = GetTeam((RoleTeamTypes)0, count); Dictionary<PlayerControl, RoleTypes> dictionary = new Dictionary<PlayerControl, RoleTypes>(); Extensions.AddRange<PlayerControl, RoleTypes>(dictionary, GetRolesAssignation(team, _allImpostorRoles, (RoleTypes)1)); Extensions.AddRange<PlayerControl, RoleTypes>(dictionary, GetRolesAssignation(team2, _allCrewmateRoles, (RoleTypes)0)); SendRolesAssignation(dictionary); } private static void SendRolesAssignation(Dictionary<PlayerControl, RoleTypes> playerRoles) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) foreach (var (val3, val4) in playerRoles) { val3.RpcSetRole(val4, false); } } private TeamPreferences GetPreferenceForPlayer(PlayerControl player) { return CollectionExtensions.GetValueOrDefault(_playerPreferences, ((InnerNetObject)player).OwnerId, TeamPreferences.Both); } private TeamPreferences GetForcedAssignmentForPlayer(PlayerControl player) { return CollectionExtensions.GetValueOrDefault(_playerForcedAssignments, ((InnerNetObject)player).OwnerId, TeamPreferences.Both); } private static TeamPreferences ConvertRoleTeamTypeToTeamPreference(RoleTeamTypes teamType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 if ((int)teamType != 0) { if ((int)teamType == 1) { return TeamPreferences.Impostor; } throw new ArgumentOutOfRangeException("teamType", "Unable to find Preference correspondence for " + ((object)(RoleTeamTypes)(ref teamType)).ToString()); } return TeamPreferences.Crewmate; } private static TeamPreferences? GetOpposite(TeamPreferences preference) { return preference switch { TeamPreferences.Crewmate => TeamPreferences.Impostor, TeamPreferences.Impostor => TeamPreferences.Crewmate, _ => null, }; } } public sealed class ChatCommandsManager { private const string CommandPrefix = "/"; private readonly Dictionary<string, Func<List<string>, bool>> _commands = new Dictionary<string, Func<List<string>, bool>> { { "kick", KickCommandHandler }, { "ban", BanCommandHandler }, { "tp", TpCommandHandler }, { "w", WhisperCommandHandler }, { "r", ReplyCommandHandler } }; private static string LastPrivateMessageSenderName { get; set; } public bool IsChatCommand(string message) { return message.StartsWith("/"); } public bool ExecuteCommand(string message) { int length = "/".Length; List<string> list = Enumerable.ToList(message.Substring(length, message.Length - length).Split(" ")); if (_commands.TryGetValue(list[0].ToLowerInvariant().Trim(), out var value)) { list.RemoveAt(0); value(list); return true; } return false; } public static void HandlePrivateMessageRpc(PlayerControl sender, MessageReader reader) { int targetOwnerId = reader.ReadInt32(); PlayerControl val = Enumerable.FirstOrDefault((IEnumerable<PlayerControl>)PlayerControl.AllPlayerControls.ToArray(), (Func<PlayerControl, bool>)((PlayerControl x) => ((InnerNetObject)x).OwnerId == targetOwnerId && (Object)(object)x.Data != (Object)null)); if (!((Object)(object)val == (Object)null) && ((InnerNetObject)val).OwnerId == ((InnerNetObject)PlayerControl.LocalPlayer).OwnerId) { LastPrivateMessageSenderName = sender.Data.PlayerName; string chatText = reader.ReadString(); DestroyableSingleton<HudManager>.Instance.Chat.AddPrivateChat(sender, val, chatText); } } private static bool KickCommandHandler(List<string> arguments) { if (arguments.Count == 0) { return false; } string playerName = string.Join(" ", arguments); PlayerControl val = Enumerable.FirstOrDefault((IEnumerable<PlayerControl>)PlayerControl.AllPlayerControls.ToArray(), (Func<PlayerControl, bool>)((PlayerControl x) => x.Data.PlayerName.Equals(playerName))); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)AmongUsClient.Instance) || !((InnerNetClient)AmongUsClient.Instance).CanBan()) { return false; } ClientData client = ((InnerNetClient)AmongUsClient.Instance).GetClient(((InnerNetObject)val).OwnerId); if (client == null) { return false; } ((InnerNetClient)AmongUsClient.Instance).KickPlayer(client.Id, false); return true; } private static bool BanCommandHandler(List<string> arguments) { if (arguments.Count == 0) { return false; } string playerName = string.Join(" ", arguments); PlayerControl val = Enumerable.FirstOrDefault((IEnumerable<PlayerControl>)PlayerControl.AllPlayerControls.ToArray(), (Func<PlayerControl, bool>)((PlayerControl x) => x.Data.PlayerName.Equals(playerName))); if ((Object)(object)val == (Object)null || (Object)(object)AmongUsClient.Instance == (Object)null || !((InnerNetClient)AmongUsClient.Instance).CanBan()) { return false; } ClientData client = ((InnerNetClient)AmongUsClient.Instance).GetClient(((InnerNetObject)val).OwnerId); if (client == null) { return false; } ((InnerNetClient)AmongUsClient.Instance).KickPlayer(client.Id, true); return true; } private static bool TpCommandHandler(List<string> arguments) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (arguments.Count == 0 || !LocalConditions.AmDead() || Object.op_Implicit((Object)(object)MeetingHud.Instance)) { return false; } string playerName = string.Join(" ", arguments); PlayerControl val = Enumerable.FirstOrDefault((IEnumerable<PlayerControl>)PlayerControl.AllPlayerControls.ToArray(), (Func<PlayerControl, bool>)((PlayerControl x) => x.Data.PlayerName.Equals(playerName))); if (!Object.op_Implicit((Object)(object)val)) { return false; } ((Component)PlayerControl.LocalPlayer).transform.position = ((Component)val).transform.position; return true; } private static bool WhisperCommandHandler(List<string> arguments) { if (arguments.Count == 0) { return false; } string rawMessage = string.Join(" ", arguments); PlayerControl val = Enumerable.MinBy(Enumerable.Where((IEnumerable<PlayerControl>)PlayerControl.AllPlayerControls.ToArray(), (PlayerControl x) => rawMessage.ToLowerInvariant().StartsWith(x.Data.PlayerName.ToLowerInvariant())), delegate(PlayerControl x) { string text2 = rawMessage; int length = x.Data.PlayerName.Length; return text2.Substring(length, text2.Length - length).Length; }); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)AmongUsClient.Instance)) { return false; } string text = rawMessage; int num = val.Data.PlayerName.Length + 1; string message = text.Substring(num, text.Length - num); PlayerControl.LocalPlayer.RpcSendPrivateMessage(val, message); return true; } private static bool ReplyCommandHandler(List<string> arguments) { if (arguments.Count == 0 || LastPrivateMessageSenderName == string.Empty) { return false; } return WhisperCommandHandler(Enumerable.ToList((LastPrivateMessageSenderName + " " + string.Join(" ", arguments)).Split(" "))); } } public sealed class CheatersManager { public readonly Dictionary<byte, string> SickoUsers = new Dictionary<byte, string>(); public readonly Dictionary<byte, string> AumUsers = new Dictionary<byte, string>(); public bool IsCheating(BetterPlayerControl player) { return IsCheating(player.Player); } public bool IsCheating(PlayerControl player) { byte playerId = player.PlayerId; if (!SickoUsers.ContainsKey(playerId)) { return AumUsers.ContainsKey(playerId); } return true; } public void HandleRpc(PlayerControl sender, byte callId, MessageReader reader) { HandleSicko(sender, callId, reader); HandleAum(sender, callId, reader); } private void HandleSicko(PlayerControl player, byte callId, MessageReader reader) { if (callId == 164 && reader.BytesRemaining == 0 && !IsCheating(player)) { player.ReportPlayer((ReportReasons)2); SickoUsers.Add(player.PlayerId, player.FriendCode); } } private void HandleAum(PlayerControl player, byte callId, MessageReader reader) { if (callId != 85 && callId != 101) { return; } if (callId == 101) { try { string text = reader.ReadString(); if (player.Data.PlayerName != text) { throw new Exception(); } } catch { return; } } if (!IsCheating(player)) { AumUsers.Add(player.PlayerId, player.FriendCode); } } } public sealed class DatabaseManager { public readonly LocalData Data; private readonly string _filePath; public DatabaseManager() { string directoryName = Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)); if (directoryName == null) { throw new Exception("Unable to locate appData directory"); } string text = Path.Combine(directoryName, "LocalLow", Application.companyName, Application.productName, "BetterVanilla"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } _filePath = Path.Combine(text, "db.dat"); if (!File.Exists(_filePath)) { Data = new LocalData(); } else { Data = JsonSerializer.Deserialize<LocalData>(File.ReadAllText(_filePath)); } CheckAndMigrateLegacyDatabase(text); } public void Save() { File.WriteAllText(_filePath, JsonSerializer.Serialize(Data)); } private void CheckAndMigrateLegacyDatabase(string directoryPath) { string path = Path.Combine(directoryPath, "player.dat"); string path2 = Path.Combine(directoryPath, "outfits.dat"); string path3 = Path.Combine(directoryPath, "settings.dat"); if (File.Exists(path)) { LegacyPlayerDatabase legacyPlayerDatabase = JsonSerializer.Deserialize<LegacyPlayerDatabase>(Encoding.UTF8.GetString(File.ReadAllBytes(path))); Data.PlayerExp = legacyPlayerDatabase.PlayerExp; Data.PlayerLevel = legacyPlayerDatabase.PlayerLevel; foreach (string featureCode in legacyPlayerDatabase.FeatureCodes) { Data.FeatureCodes.Add(featureCode); } Save(); File.Delete(path); } if (File.Exists(path2)) { foreach (LegacyDressingOutfit outfit in JsonSerializer.Deserialize<LegacyOutfitsDatabase>(Encoding.UTF8.GetString(File.ReadAllBytes(path2))).Outfits) { Data.Outfits.Add(new LocalOutfitData { Hat = outfit.Hat, Skin = outfit.Skin, Visor = outfit.Visor, Pet = outfit.Pet, Nameplate = outfit.Nameplate }); } Save(); File.Delete(path2); } if (File.Exists(path3)) { File.Delete(path3); } } } public sealed class FeaturesManager { private readonly HashSet<string> _availableHashes = new HashSet<string>(); private readonly HashSet<string> _hashedCodes = new HashSet<string>(); public FeaturesRegistry Registry { get; private set; } public FeaturesManager() { foreach (string featureCode in BetterVanillaManager.Instance.Database.Data.FeatureCodes) { _hashedCodes.Add(StringUtils.CalculateSHA256(featureCode)); } } public void RegisterHash(string hash) { _availableHashes.Add(hash); } public void Initialize(string githubRepository, string branchName, string filePath) { MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)BetterVanillaManager.Instance, CoStart(githubRepository, branchName, filePath)); } private IEnumerator CoStart(string githubRepository, string branchName, string filePath) { UnityWebRequest www = new UnityWebRequest(); www.SetMethod((UnityWebRequestMethod)0); www.SetUrl($"https://raw.githubusercontent.com/{githubRepository}/refs/heads/{branchName}/{filePath}"); www.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); UnityWebRequestAsyncOperation operation = www.SendWebRequest(); while (!((AsyncOperation)operation).isDone) { yield return null; } if (www.isNetworkError || www.isHttpError) { Ls.LogError((object)www.error); yield break; } Registry = JsonSerializer.Deserialize<FeaturesRegistry>(www.downloadHandler.text); www.downloadHandler.Dispose(); www.Dispose(); if (Registry == null) { Ls.LogError((object)"No features registry found"); } } public void RegisterCode(string featureCode) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown string text = StringUtils.CalculateSHA256(featureCode); bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(31, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Trying to register code: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(featureCode); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" => ["); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("]"); } Ls.LogInfo(val); if (!_availableHashes.Contains(text) || !IsUnlockable(text)) { return; } if (!BetterVanillaManager.Instance.Database.Data.FeatureCodes.Add(featureCode)) { val = new BepInExErrorLogInterpolatedStringHandler(15, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Removing hash: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); } Ls.LogInfo(val); BetterVanillaManager.Instance.Database.Data.FeatureCodes.Remove(featureCode); _hashedCodes.Remove(text); } else { val = new BepInExErrorLogInterpolatedStringHandler(12, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Added hash: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); } Ls.LogInfo(val); _hashedCodes.Add(text); } BetterVanillaManager.Instance.Database.Save(); } private bool IsUnlockable(string hash) { EOSManager instance = DestroyableSingleton<EOSManager>.Instance; if (Registry == null || !Object.op_Implicit((Object)(object)instance) || string.IsNullOrEmpty(instance.FriendCode)) { return false; } if (!Registry.FeatureHashPermissions.TryGetValue(hash, out var value)) { return false; } if (!value.Contains(instance.FriendCode)) { return false; } return true; } public bool IsUnlocked(string hash) { if (_hashedCodes.Contains(hash)) { return IsUnlockable(hash); } return false; } public bool IsLocked(string hash) { return !IsUnlocked(hash); } } public static class GameEventManager { public static event Action MeetingStarted; public static event Action<PlayerControl> MeetingEnded; public static event Action GameStarted; public static event Action GameEnded; public static event Action<PlayerControl> PlayerJoined; public static event Action<PlayerControl> PlayerReady; public static void TriggerMeetingStarted() { GameEventManager.MeetingStarted?.Invoke(); } public static void TriggerMeetingEnded(PlayerControl exiledPlayer) { GameEventManager.MeetingEnded?.Invoke(exiledPlayer); } public static void TriggerGameStarted() { GameEventManager.GameStarted?.Invoke(); } public static void TriggerGameEnded() { GameEventManager.GameEnded?.Invoke(); } public static void TriggerPlayerJoined(PlayerControl player) { GameEventManager.PlayerJoined?.Invoke(player); } public static void TriggerPlayerReady(PlayerControl player) { GameEventManager.PlayerReady?.Invoke(player); } } public sealed class HostOptionsHolder { private readonly HostCategory _category; public readonly BoolHostOption AllowDeadVoteDisplay; public readonly BoolHostOption AllowTeamPreference; public readonly FloatHostOption PolusReactorCountdown; public HostOptionsHolder() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown _category = new HostCategory("Better Vanilla"); AllowDeadVoteDisplay = _category.CreateBool("DeadVoteDisplayAllowed", "Allow realtime vote display", defaultValue: true); AllowTeamPreference = _category.CreateBool("TeamPreferenceAllowed", "Allow Team Preferences", defaultValue: true); PolusReactorCountdown = _category.CreateFloat("PolusReactorCountdown", "Polus Reactor Countdown", 60f, 0.5f, new FloatRange(15f, 120f), "0.0", zeroIsInfinity: false, (NumberSuffixes)2); } public void ShareAllOptions() { if (!((InnerNetClient)AmongUsClient.Instance).AmHost) { return; } foreach (BaseHostOption allOption in _category.AllOptions) { PlayerControl.LocalPlayer.RpcShareHostOption(allOption); } } } public sealed class LegacyBetterRoleAssignments { private const int TicketsPerPlayer = 20; private const int TicketsPenaltyForNonPreferredTeam = 15; private readonly IGameOptions _currentOptions; private readonly int _numImpostors; private readonly List<PlayerControl> _allPlayers = new List<PlayerControl>(); private readonly List<PlayerControl> _remainingPlayers = new List<PlayerControl>(); private readonly Dictionary<byte, TeamPreferences> _playerPreferences = new Dictionary<byte, TeamPreferences>(); private readonly Dictionary<byte, TeamPreferences> _playerForcedAssignments = new Dictionary<byte, TeamPreferences>(); private readonly List<RoleTypes> _allCrewmateRoles = new List<RoleTypes>(); private readonly List<RoleTypes> _allImpostorRoles = new List<RoleTypes>(); public LegacyBetterRoleAssignments() { Enumerator<PlayerControl> enumerator = PlayerControl.AllPlayerControls.GetEnumerator(); while (enumerator.MoveNext()) { PlayerControl current = enumerator.Current; if (Object.op_Implicit((Object)(object)current) && Object.op_Implicit((Object)(object)current.Data) && !current.Data.Disconnected && !current.Data.IsDead) { _allPlayers.Add(current); } } _currentOptions = GameOptionsManager.Instance.CurrentGameOptions; _numImpostors = IGameOptionsExtensions.GetAdjustedNumImpostors(GameOptionsManager.Instance.CurrentGameOptions, _allPlayers.Count); _remainingPlayers.AddRange(_allPlayers); SetupRoles(); } public void SetTeamPreference(byte playerId, TeamPreferences preference) { _playerPreferences[playerId] = preference; } public void SetTeamPreferences(Dictionary<byte, TeamPreferences> preferences) { foreach (KeyValuePair<byte, TeamPreferences> preference in preferences) { SetTeamPreference(preference.Key, preference.Value); } } public void SetForcedAssignment(byte playerId, TeamPreferences preference) { _playerForcedAssignments[playerId] = preference; } public void SetForcedAssignments(Dictionary<byte, TeamPreferences> preferences) { foreach (KeyValuePair<byte, TeamPreferences> preference in preferences) { SetForcedAssignment(preference.Key, preference.Value); } } private void SetupRoles() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Invalid comparison between Unknown and I4 //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) IRoleOptionsCollection roleOptions = _currentOptions.RoleOptions; foreach (RoleBehaviour item in (Il2CppArrayBase<RoleBehaviour>)(object)DestroyableSingleton<RoleManager>.Instance.AllRoles) { RoleTeamTypes teamType = item.TeamType; RoleTypes role = item.Role; int numPerGame = roleOptions.GetNumPerGame(role); int chancePerGame = roleOptions.GetChancePerGame(role); if (chancePerGame == 0 || numPerGame == 0) { continue; } bool flag = chancePerGame < 100; for (int i = 0; i < numPerGame; i++) { if (!flag || HashRandom.Next(101) < chancePerGame) { if ((int)teamType == 0) { _allCrewmateRoles.Add(role); } else if ((int)teamType == 1) { _allImpostorRoles.Add(role); } } } } } private List<byte> CreateDraw(RoleTeamTypes team, bool ignorePlayerPreferences = false) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) List<byte> list = new List<byte>(); TeamPreferences teamPreferences = ConvertRoleTeamTypeToTeamPreference(team); TeamPreferences? opposite = GetOpposite(teamPreferences); foreach (PlayerControl remainingPlayer in _remainingPlayers) { TeamPreferences forcedAssignmentForPlayer = GetForcedAssignmentForPlayer(remainingPlayer); byte playerId = remainingPlayer.PlayerId; int num = 20; TeamPreferences preferenceForPlayer = GetPreferenceForPlayer(remainingPlayer); if (!ignorePlayerPreferences && preferenceForPlayer != TeamPreferences.Both && preferenceForPlayer != teamPreferences) { num -= 15; } if (forcedAssignmentForPlayer == TeamPreferences.Both || forcedAssignmentForPlayer != opposite) { for (int i = 0; i < num; i++) { list.Add(playerId); } } } return list; } private TeamPreferences GetPreferenceForPlayer(PlayerControl player) { return CollectionExtensions.GetValueOrDefault(_playerPreferences, player.PlayerId, TeamPreferences.Both); } private TeamPreferences GetForcedAssignmentForPlayer(PlayerControl player) { return CollectionExtensions.GetValueOrDefault(_playerForcedAssignments, player.PlayerId, TeamPreferences.Both); } private static TeamPreferences ConvertRoleTeamTypeToTeamPreference(RoleTeamTypes teamType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 if ((int)teamType != 0) { if ((int)teamType == 1) { return TeamPreferences.Impostor; } throw new ArgumentOutOfRangeException("teamType", "Unable to find Preference correspondence for " + ((object)(RoleTeamTypes)(ref teamType)).ToString()); } return TeamPreferences.Crewmate; } private static TeamPreferences? GetOpposite(TeamPreferences preference) { return preference switch { TeamPreferences.Crewmate => TeamPreferences.Impostor, TeamPreferences.Impostor => TeamPreferences.Crewmate, _ => null, }; } private List<PlayerControl> PickRandomPlayersFromDraw(List<byte> draw, int amount) { List<PlayerControl> list = new List<PlayerControl>(); for (int i = 0; i < amount; i++) { if (draw.Count == 0) { return list; } byte playerId = draw.PickOneRandom(); PlayerControl item = Enumerable.First(_remainingPlayers, (PlayerControl x) => x.PlayerId == playerId); list.Add(item); _remainingPlayers.Remove(item); while (draw.Contains(playerId)) { draw.Remove(playerId); } } return list; } private List<PlayerControl> GetTeam(RoleTeamTypes teamType, int teamSize) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) List<byte> draw = CreateDraw(teamType, !BetterVanillaManager.Instance.HostOptions.AllowTeamPreference.GetBool()); return PickRandomPlayersFromDraw(draw, teamSize); } private static Dictionary<PlayerControl, RoleTypes> GetRolesAssignation(List<PlayerControl> players, List<RoleTypes> roles, RoleTypes defaultRole) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) Dictionary<PlayerControl, RoleTypes> dictionary = new Dictionary<PlayerControl, RoleTypes>(); foreach (PlayerControl player in players) { RoleTypes value = ((roles.Count > 0) ? roles.PickOneRandom() : defaultRole); dictionary.Add(player, value); } return dictionary; } public void StartAssignation() { int teamSize = Mathf.Max(1, _numImpostors); List<PlayerControl> team = GetTeam((RoleTeamTypes)1, teamSize); int count = _remainingPlayers.Count; List<PlayerControl> team2 = GetTeam((RoleTeamTypes)0, count); Dictionary<PlayerControl, RoleTypes> dictionary = new Dictionary<PlayerControl, RoleTypes>(); Extensions.AddRange<PlayerControl, RoleTypes>(dictionary, GetRolesAssignation(team, _allImpostorRoles, (RoleTypes)1)); Extensions.AddRange<PlayerControl, RoleTypes>(dictionary, GetRolesAssignation(team2, _allCrewmateRoles, (RoleTypes)0)); SendRolesAssignation(dictionary); } private static void SendRolesAssignation(Dictionary<PlayerControl, RoleTypes> playerRoles) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) foreach (var (val3, val4) in playerRoles) { val3.RpcSetRole(val4, false); } } } public static class LocalConditions { private static readonly List<Modes> AllowedRevealMapModes = new List<Modes>(2) { (Modes)1, (Modes)3 }; public static LocalOptionsHolder Options => BetterVanillaManager.Instance.LocalOptions; public static bool ShouldAutoPlayAgain() { return Options.AutoPlayAgain.Value; } public static bool ShouldShowRolesAndTasks() { return Options.DisplayRolesAndTasksAfterDeath.Value; } public static bool ShouldShowRolesAndTasks(PlayerControl playerControl) { if (ShouldShowRolesAndTasks() && IsGameStarted()) { if (!((Object)(object)PlayerControl.LocalPlayer == (Object)(object)playerControl)) { return AmDead(); } return true; } return false; } public static bool AmDead() { if (Options.DisableAmDeadCheck.IsLocked() || !BetterVanillaManager.Instance.LocalOptions.DisableAmDeadCheck.Value) { if (Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer) && Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer.Data)) { return PlayerControl.LocalPlayer.Data.IsDead; } return false; } return true; } public static bool AmImpostor() { if (Options.DisableAmImpostorCheck.IsLocked() || !Options.DisableAmImpostorCheck.Value) { if (Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer) && Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer.Data) && Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer.Data.Role)) { return PlayerControl.LocalPlayer.Data.Role.IsImpostor; } return false; } return false; } public static bool AmAlive() { return !AmDead(); } public static bool IsGameStarted() { if (Object.op_Implicit((Object)(object)AmongUsClient.Instance)) { if (!((InnerNetClient)AmongUsClient.Instance).IsGameStarted) { return DestroyableSingleton<TutorialManager>.InstanceExists; } return true; } return false; } public static bool IsIncrementMultiplierKeyPressed() { if (!Input.GetKey((KeyCode)304)) { return Input.GetKey((KeyCode)303); } return true; } public static bool ShouldRevealPlayerPositionsInMap(Modes currentMapMode) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (AllowedRevealMapModes.Contains(currentMapMode) && Options.DisplayPlayersInMapAfterDeath.Value && !Object.op_Implicit((Object)(object)MeetingHud.Instance) && AmDead()) { return !AmImpostor(); } return false; } public static bool ShouldRevealVotes() { if (Options.DisplayVotesAfterDeath.Value) { return AmDead(); } return false; } public static bool ShouldRevealVoteColors() { if (Options.DisplayVoteColorsAfterDeath.Value) { return AmDead(); } return false; } public static bool IsForcedTeamAssignmentAllowed() { return !Options.ForcedTeamAssignment.IsLocked(); } public static bool CanZoom() { if (Object.op_Implicit((Object)(object)BetterVanillaManager.Instance.ZoomBehaviour) && AmDead()) { return !AmImpostor(); } return false; } public static bool ShouldDisableGameStartRequirement() { if (!Options.DisableGameStartRequirement.IsLocked()) { return Options.DisableGameStartRequirement.Value; } return false; } public static bool ShouldDisableGameEndRequirement() { if (!Options.DisableEndGameChecks.IsLocked()) { return Options.DisableEndGameChecks.Value; } return false; } public static bool ShouldUnlockModdedCosmetics() { if (!Options.AllowModdedCosmetics.IsLocked()) { return Options.AllowModdedCosmetics.Value; } return false; } public static bool ShouldRevealVentPositionsInMap() { return Options.DisplayVentsInMap.Value; } } public sealed class LocalOptionsHolder { public readonly BoolLocalOption DisplayVentsInMap; public readonly BoolLocalOption DisplayRolesAndTasksAfterDeath; public readonly BoolLocalOption DisplayPlayersInMapAfterDeath; public readonly BoolLocalOption DisplayVotesAfterDeath; public readonly BoolLocalOption DisplayVoteColorsAfterDeath; public readonly BoolLocalOption AutoPlayAgain; public readonly StringLocalOption TeamPreference; public readonly BoolLocalOption AllowModdedCosmetics; public readonly BoolLocalOption DisableAmDeadCheck; public readonly BoolLocalOption DisableAmImpostorCheck; public readonly BoolLocalOption DisableEndGameChecks; public readonly BoolLocalOption DisableGameStartRequirement; public readonly StringLocalOption ForcedTeamAssignment; public LocalOptionsHolder() { LocalCategory localCategory = new LocalCategory("Local Settings"); DisplayVentsInMap = localCategory.CreateBool("DisplayVentsInMap", "Display vents in map", defaultValue: true); DisplayRolesAndTasksAfterDeath = localCategory.CreateBool("DisplayRolesAndTasksAfterDeath", "Display roles and tasks after death", defaultValue: true); DisplayPlayersInMapAfterDeath = localCategory.CreateBool("DisplayPlayersInMapAfterDeath", "Display players in map after death", defaultValue: true); DisplayVotesAfterDeath = localCategory.CreateBool("DisplayVotesAfterDeath", "Display votes after death", defaultValue: true); DisplayVoteColorsAfterDeath = localCategory.CreateBool("DisplayVoteColorsAfterDeath", "Display vote colors after death", defaultValue: true); AutoPlayAgain = localCategory.CreateBool("AutoPlayAgain", "Auto Play Again", defaultValue: true); TeamPreference = localCategory.CreateEnum("TeamPreference", "Team Assignment Preference", TeamPreferences.Both); AllowModdedCosmetics = localCategory.CreateBool("AllowModdedCosmetics", "Display Modded Cosmetics", defaultValue: false); DisableAmDeadCheck = localCategory.CreateBool("DisableAmDeadCheck", "Disable Am Dead Check", defaultValue: false); DisableAmImpostorCheck = localCategory.CreateBool("DisableAmImpostorCheck", "Disable Am Impostor Check", defaultValue: false); DisableEndGameChecks = localCategory.CreateBool("DisableEndGameChecks", "Disable All End Game Checks", defaultValue: false); DisableGameStartRequirement = localCategory.CreateBool("DisableGameStartRequirement", "Disable Start Game Player Requirement", defaultValue: false); ForcedTeamAssignment = localCategory.CreateEnum("ForcedTeamAssignment", "Forced Team Assignment", TeamPreferences.Both); AllowModdedCosmetics.LockWithPassword("A617504DA5A04943DE0CF0C85FF2DA7B7C387C6B6D2950E1DF8CB8D0E4D69FCE"); DisableAmDeadCheck.LockWithPassword("A21B151BDA9AD098622868D3B7EBB5B0BB819EBD7C25B6504BDAAE9FF1FF8C0F"); DisableAmImpostorCheck.LockWithPassword("B640EC50173A2DAC2056F2926027D3BBDDEFB9A1468627A36164D4101519DDAA"); DisableEndGameChecks.LockWithPassword("81133C46C6DAACD12259989C7D8D385BE47AF65385F9C3D5BFAFEDD2A5C44FD0"); DisableGameStartRequirement.LockWithPassword("98F47935FFDEEDC0F716F87A5C332AA77222DF4EAF4FF61E1989EE95B1671B77"); ForcedTeamAssignment.LockWithPassword("FE3C8AB240748CE91A143E7E61CA6C3D0996D55C23F8F3A7BC42A47BB26B7514"); TeamPreference.ValueChanged += OnTeamPreferenceValueChanged; ForcedTeamAssignment.ValueChanged += OnForcedTeamAssignmentValueChanged; } private void OnTeamPreferenceValueChanged() { if (Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer) && Object.op_Implicit((Object)(object)AmongUsClient.Instance)) { PlayerControl.LocalPlayer.RpcSetTeamPreference(TeamPreference.ParseValue(TeamPreferences.Both)); } } private void OnForcedTeamAssignmentValueChanged() { if (Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer) && Object.op_Implicit((Object)(object)AmongUsClient.Instance)) { PlayerControl.LocalPlayer.RpcSetForcedTeamAssignment(ForcedTeamAssignment.ParseValue(TeamPreferences.Both)); } } } public static class Ls { private static ManualLogSource Logger { get; set; } public static void SetLogSource(ManualLogSource logSource) { Logger = logSource; } public static void LogError(object data) { Logger.LogError(data); } public static void LogError(BepInExErrorLogInterpolatedStringHandler logHandler) { Logger.LogError(logHandler); } public static void LogWarning(object data) { Logger.LogWarning(data); } public static void LogWarning(BepInExErrorLogInterpolatedStringHandler logHandler) { Logger.LogWarning((object)logHandler); } public static void LogMessage(object data) { Logger.LogMessage(data); } public static void LogMessage(BepInExErrorLogInterpolatedStringHandler logHandler) { Logger.LogMessage((object)logHandler); } public static void LogInfo(object data) { Logger.LogInfo(data); } public static void LogInfo(BepInExErrorLogInterpolatedStringHandler logHandler) { Logger.LogInfo((object)logHandler); } public static void LogDebug(object data) { Logger.LogDebug(data); } public static void LogDebug(BepInExErrorLogInterpolatedStringHandler logHandler) { Logger.LogDebug((object)logHandler); } } public sealed class PassiveButtonsBlocker { private static readonly List<PassiveButtonsBlocker> AllBlockers = new List<PassiveButtonsBlocker>(); private bool _blocked; public static bool ShouldBlock() { return Enumerable.Any(AllBlockers, (PassiveButtonsBlocker x) => x._blocked); } public PassiveButtonsBlocker() { _blocked = false; AllBlockers.Add(this); } public void Block() { _blocked = true; } public void Unblock() { _blocked = false; } } public sealed class XpManager { private readonly float _baseXpPerLevel; private readonly float _exponent; public readonly uint MaxLevel; public uint OldLevel { get; private set; } public uint OldXpAmount { get; private set; } public uint GrantedXp { get; private set; } public uint NewXp { get; private set; } public uint NewLevel { get; private set; } public uint XpRequiredToLevelUp { get; private set; } public uint XpRequiredToLevelUpNextLevel { get; private set; } public bool LevelledUp { get; private set; } public XpManager() { _baseXpPerLevel = 100f; _exponent = 0.56f; MaxLevel = 200u; } public uint CalculateLevel(uint xp) { return Math.Min((uint)Math.Floor((float)Math.Pow((float)xp / _baseXpPerLevel, _exponent)), MaxLevel); } private uint CalculateXpForLevel(uint level) { if (level > MaxLevel) { return 0u; } return (uint)((double)_baseXpPerLevel * Math.Pow(level, 1.0 / (double)_exponent)); } public void SetupCache(XpGrantResult xpGrantResult) { uint playerExp = BetterVanillaManager.Instance.Database.Data.PlayerExp; uint num = CalculateLevel(playerExp); uint num2 = CalculateXpForLevel(num); OldXpAmount = playerExp - num2; OldLevel = num; GrantedXp = xpGrantResult.GrantedXp; NewXp = OldXpAmount + GrantedXp; NewLevel = ((OldLevel == MaxLevel) ? OldLevel : (OldLevel + 1)); XpRequiredToLevelUp = CalculateXpForLevel(NewLevel) - num2; XpRequiredToLevelUpNextLevel = CalculateXpForLevel(NewLevel + 1) - num2; LevelledUp = OldXpAmount + GrantedXp >= XpRequiredToLevelUp; } public void ApplyCache() { DatabaseManager database = BetterVanillaManager.Instance.Database; database.Data.PlayerExp += GrantedXp; database.Data.PlayerLevel = CalculateLevel(database.Data.PlayerExp); database.Save(); } public void ClearCache() { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(1, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("XpManager"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("ClearCache"); } Ls.LogMessage(val); OldLevel = 0u; OldXpAmount = 0u; GrantedXp = 0u; NewXp = 0u; NewLevel = 0u; XpRequiredToLevelUp = 0u; XpRequiredToLevelUpNextLevel = 0u; LevelledUp = false; } } } namespace BetterVanilla.Core.Patches { [HarmonyPatch(typeof(ChatController))] internal static class ChatControllerPatches { [HarmonyPrefix] [HarmonyPatch("SendFreeChat")] private static bool SendFreeChatPrefix(ChatController __instance) { string text = __instance.freeChatField.Text; if (BetterVanillaManager.Instance.ChatCommands.IsChatCommand(text)) { if (BetterVanillaManager.Instance.ChatCommands.ExecuteCommand(text)) { ((AbstractChatInputField)__instance.freeChatField).Clear(); } else { __instance.AddChatWarning("Unknown command: " + text); } return false; } ChatController.Logger.Debug(Object.op_Implicit("SendFreeChat () :: Sending message: '" + text + "'"), (Object)null); PlayerControl.LocalPlayer.RpcSendChat(text); return false; } } [HarmonyPatch(typeof(EndGameManager))] internal static class EndGameManagerPatches { [HarmonyPostfix] [HarmonyPatch("ShowButtons")] private static void ShowButtonsPostfix(EndGameManager __instance) { BetterVanillaManager instance = BetterVanillaManager.Instance; instance.AllTeamPreferences.Clear(); instance.AllForcedTeamAssignments.Clear(); instance.Menu.Close(); __instance.Navigation.SetupPlayAgain(); } } [HarmonyPatch(typeof(GameOptionsMenu))] internal static class GameOptionsMenuPatches { [HarmonyPrefix] [HarmonyPatch("CreateSettings")] private static bool CreateSettingsPrefix(GameOptionsMenu __instance) { __instance.CreateBetterSettings(); return false; } [HarmonyPrefix] [HarmonyPatch("ValueChanged")] private static bool ValueChangedPrefix(GameOptionsMenu __instance, OptionBehaviour option) { return __instance.CustomValueChanged(option); } } [HarmonyPatch(typeof(GameStartManager))] internal static class GameStartManagerPatches { private static int PlayersCount { get; set; } [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix() { BetterVanillaManager.Instance.Cheaters.SickoUsers.Clear(); BetterVanillaManager.Instance.Cheaters.AumUsers.Clear(); } [HarmonyPostfix] [HarmonyPatch("ReallyBegin")] private static void ReallyBeginPostfix() { PlayersCount = PlayerControl.AllPlayerControls.Count; } [HarmonyPrefix] [HarmonyPatch("Update")] private static bool UpdatePrefix(GameStartManager __instance) { if (!Object.op_Implicit((Object)(object)GameData.Instance) || !Object.op_Implicit((Object)(object)GameManager.Instance)) { return false; } if (!Object.op_Implicit((Object)(object)AmongUsClient.Instance) || !((InnerNetClient)AmongUsClient.Instance).AmHost) { return true; } if (__instance.LastPlayerCount != PlayersCount) { PlayersCount = __instance.LastPlayerCount; } int minPlayers = __instance.MinPlayers; __instance.MinPlayers = (LocalConditions.ShouldDisableGameStartRequirement() ? 1 : 4); if (minPlayers != __instance.MinPlayers) { int lastPlayerCount = __instance.LastPlayerCount; __instance.LastPlayerCount = lastPlayerCount - 1; } return true; } } [HarmonyPatch(typeof(HudManager))] internal static class HudManagerPatches { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(HudManager __instance) { ((Component)__instance).gameObject.AddComponent<ZoomBehaviourManager>(); ((Component)__instance).gameObject.AddComponent<TaskFinisherBehaviour>(); } } [HarmonyPatch(typeof(LobbyViewSettingsPane))] internal static class LobbyViewSettingsPanePatches { [HarmonyPrefix] [HarmonyPatch("DrawNormalTab")] private static bool DrawNormalTabPrefix(LobbyViewSettingsPane __instance) { __instance.DrawBetterNormalTab(); return false; } } [HarmonyPatch(typeof(LogicGameFlowNormal))] internal static class LogicGameFlowNormalPatches { [HarmonyPrefix] [HarmonyPatch("CheckEndCriteria")] [HarmonyPatch("IsGameOverDueToDeath")] private static bool ShouldCheckForEndGame() { return !LocalConditions.ShouldDisableGameEndRequirement(); } } [HarmonyPatch(typeof(LogicOptionsNormal))] internal static class LogicOptionsNormalPatches { [HarmonyPostfix] [HarmonyPatch("GetAnonymousVotes")] private static void GetAnonymousVotesPostfix(ref bool __result) { if (__result && LocalConditions.ShouldRevealVoteColors()) { __result = false; } } } [HarmonyPatch(typeof(MapBehaviour))] internal static class MapBehaviourPatches { [HarmonyPostfix] [HarmonyPatch("FixedUpdate")] private static void FixedUpdatePostfix(MapBehaviour __instance) { __instance.BetterFixedUpdate(); } [HarmonyPrefix] [HarmonyPatch("Show")] private static void ShowPrefix(MapBehaviour __instance, MapOptions opts) { __instance.BetterShow(opts); } } [HarmonyPatch(typeof(MapRoom))] internal static class MapRoomPatches { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(MapRoom __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)__instance.special)) { Vector3 localPosition = ((Component)__instance.special).transform.localPosition; localPosition.z = -3f; ((Component)__instance.special).transform.localPosition = localPosition; } if (Object.op_Implicit((Object)(object)__instance.door)) { Vector3 localPosition2 = ((Component)__instance.door).transform.localPosition; localPosition2.z = -3f; ((Component)__instance.door).transform.localPosition = localPosition2; } } } [HarmonyPatch(typeof(MeetingHud))] internal static class MeetingHudPatches { [HarmonyPostfix] [HarmonyPatch("CastVote")] private static void CastVotePostfix(MeetingHud __instance, byte srcPlayerId, byte suspectPlayerId) { __instance.BetterCastVote(srcPlayerId, suspectPlayerId); } [HarmonyPostfix] [HarmonyPatch("Update")] private static void UpdatePostfix(MeetingHud __instance) { __instance.BetterUpdate(); } [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(MeetingHud __instance) { __instance.BetterStart(); } } [HarmonyPatch(typeof(NetworkedPlayerInfo))] internal static class NetworkedPlayerInfoPatches { [HarmonyPostfix] [HarmonyPatch("Deserialize")] private static void DeserializePostfix(NetworkedPlayerInfo __instance) { __instance.RegisterFriendCode(); } } [HarmonyPatch(typeof(NumberOption))] internal static class NumberOptionPatches { [HarmonyPrefix] [HarmonyPatch("Initialize")] private static bool InitializePrefix(NumberOption __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if ((int)((OptionBehaviour)__instance).Title == 0 && (int)__instance.floatOptionName == 0) { return (int)__instance.intOptionName > 0; } return true; } [HarmonyPrefix] [HarmonyPatch("UpdateValue")] private static bool UpdateValuePrefix(NumberOption __instance) { return ((OptionBehaviour)(object)__instance).CustomUpdateValue(); } [HarmonyPrefix] [HarmonyPatch("Increase")] private static bool IncreasePrefix(NumberOption __instance) { __instance.BetterIncrease(); return false; } [HarmonyPrefix] [HarmonyPatch("Decrease")] private static bool DecreasePrefix(NumberOption __instance) { __instance.BetterDecrease(); return false; } } [HarmonyPatch(typeof(PassiveButtonManager))] internal static class PassiveButtonManagerPatches { [HarmonyPrefix] [HarmonyPatch("Update")] private static bool UpdatePrefix() { return !PassiveButtonsBlocker.ShouldBlock(); } } [HarmonyPatch(typeof(PlayerControl))] internal static class PlayerControlPatches { [HarmonyPostfix] [HarmonyPatch("HandleRpc")] private static void HandleRpcPostfix(PlayerControl __instance, byte callId, MessageReader reader) { if (callId == 252) { __instance.HandleCustomRpc(reader); } else { BetterVanillaManager.Instance.Cheaters.HandleRpc(__instance, callId, reader); } } [HarmonyPostfix] [HarmonyPatch("Awake")] private static void AwakePostfix(PlayerControl __instance) { if (!__instance.notRealPlayer) { GameEventManager.TriggerPlayerJoined(__instance); } } [HarmonyPrefix] [HarmonyPatch("Start")] private static bool StartPrefix(PlayerControl __instance) { MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)__instance, __instance.CoBetterStart()); return false; } [HarmonyPostfix] [HarmonyPatch("StartMeeting")] private static void StartMeetingPostfix(PlayerControl __instance) { GameEventManager.TriggerMeetingStarted(); } } [HarmonyPatch(typeof(PlayerPurchasesData))] internal static class PlayerPurchasesDataPatches { [HarmonyPostfix] [HarmonyPatch("GetPurchase")] private static void GetPurchasePostfix(ref bool __result) { if (LocalConditions.ShouldUnlockModdedCosmetics()) { __result = true; } } } [HarmonyPatch(typeof(PlayerVoteArea))] internal static class PlayerVoteAreaPatches { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(PlayerVoteArea __instance) { ((Component)__instance).gameObject.AddComponent<BetterPlayerVoteArea>(); } } [HarmonyPatch(typeof(ProgressionScreen))] internal static class ProgressionScreenPatches { [HarmonyPrefix] [HarmonyPatch(typeof(_DoAnimations_d__14), "MoveNext")] private static bool _DoAnimations_d__14MoveNextPrefix(_DoAnimations_d__14 __instance) { ProgressionScreen _4__this = __instance.__4__this; MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)_4__this, _4__this.CoDoAnimations(__instance.xpGainedResult)); return false; } } [HarmonyPatch(typeof(ReactorSystemType))] internal static class ReactorSystemTypePatches { [HarmonyPrefix] [HarmonyPatch("UpdateSystem")] private static bool UpdateSystemPrefix(ReactorSystemType __instance, PlayerControl player, MessageReader msgReader) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 byte b = msgReader.ReadByte(); int num = b & 3; if (b == 128 && !__instance.IsActive) { __instance.Countdown = (((int)ShipStatus.Instance.Type != 2) ? __instance.ReactorDuration : BetterVanillaManager.Instance.HostOptions.PolusReactorCountdown.GetFloat()); __instance.UserConsolePairs.Clear(); } else if (b == 16) { __instance.Countdown = 10000f; } else if (Extensions.HasAnyBit(b, (byte)64)) { __instance.UserConsolePairs.Add(new Tuple<byte, byte>(player.PlayerId, (byte)num)); if (__instance.UserCount >= 2) { __instance.Countdown = 10000f; } } else if (Extensions.HasAnyBit(b, (byte)32)) { __instance.UserConsolePairs.Remove(new Tuple<byte, byte>(player.PlayerId, (byte)num)); } __instance.IsDirty = true; return false; } } [HarmonyPatch(typeof(RoleManager))] internal static class RoleManagerPatches { [HarmonyPrefix] [HarmonyPatch("SelectRoles")] private static bool SelectRolesPrefix(RoleManager __instance) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)GameOptionsManager.Instance.currentGameMode != 1) { return true; } BetterVanillaManager instance = BetterVanillaManager.Instance; if (instance.HostOptions.AllowTeamPreference.GetBool()) { instance.AllTeamPreferences[((InnerNetObject)PlayerControl.LocalPlayer).OwnerId] = instance.LocalOptions.TeamPreference.ParseValue(TeamPreferences.Both); } if (LocalConditions.IsForcedTeamAssignmentAllowed()) { instance.AllForcedTeamAssignments[((InnerNetObject)PlayerControl.LocalPlayer).OwnerId] = instance.LocalOptions.ForcedTeamAssignment.ParseValue(TeamPreferences.Both); } BetterRoleAssignments betterRoleAssignments = new BetterRoleAssignments(); betterRoleAssignments.SetTeamPreferences(instance.AllTeamPreferences); betterRoleAssignments.SetForcedAssignments(instance.AllForcedTeamAssignments); betterRoleAssignments.StartAssignation(); return false; } } [HarmonyPatch(typeof(ShipStatus))] internal static class ShipStatusPatches { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(ShipStatus __instance) { GameEventManager.TriggerGameStarted(); } [HarmonyPrefix] [HarmonyPatch("OnDestroy")] private static void OnDestroyPrefix(ShipStatus __instance) { GameEventManager.TriggerGameEnded(); } } [HarmonyPatch(typeof(ToggleOption))] internal static class ToggleOptionPatches { [HarmonyPrefix] [HarmonyPatch("Initialize")] private static bool InitializePrefix(ToggleOption __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if ((int)((OptionBehaviour)__instance).Title != 0) { return (int)__instance.boolOptionName > 0; } return false; } [HarmonyPrefix] [HarmonyPatch("UpdateValue")] private static bool UpdateValuePrefix(ToggleOption __instance) { return ((OptionBehaviour)(object)__instance).CustomUpdateValue(); } } } namespace BetterVanilla.Core.Options { public abstract class BaseCategory { public readonly string Name; protected BaseCategory(string name) { Name = name; base..ctor(); } } public abstract class BaseHostOption : BaseOption { public static readonly List<BaseHostOption> AllOptions = new List<BaseHostOption>(); public BaseGameSetting GameSetting { get; private set; } public OptionBehaviour Behaviour { get; private set; } public ViewSettingsInfoPanel ViewBehaviour { get; private set; } protected BaseHostOption(string name, string title) : base(name, title) { AllOptions.Add(this); } public virtual float GetFloat() { throw new NotImplementedException(); } public virtual int GetInt() { throw new NotImplementedException(); } public virtual bool GetBool() { throw new NotImplementedException(); } protected TGameSetting InitGameSetting<TGameSetting>(OptionTypes optionType) where TGameSetting : BaseGameSetting { //IL_0035: Unknown result type (might be due to invalid IL or missing references) TGameSetting val = ScriptableObject.CreateInstance<TGameSetting>(); ((Object)(object)val).hideFlags = (HideFlags)52; ((Object)(object)val).name = "BetterVanillaCustomSetting"; ((BaseGameSetting)val).Title = (StringNames)0; ((BaseGameSetting)val).Type = optionType; GameSetting = (BaseGameSetting)(object)val; return val; } public virtual void OnBehaviourCreated(OptionBehaviour behaviour) { Behaviour = behaviour; } public virtual void OnViewBehaviourCreated(ViewSettingsInfoPanel viewBehaviour) { ViewBehaviour = viewBehaviour; } protected virtual void OnValueChanged() { if (Object.op_Implicit((Object)(object)AmongUsClient.Instance) && ((InnerNetClient)AmongUsClient.Instance).AmHost && Object.op_Implicit((Object)(object)PlayerControl.LocalPlayer)) { PlayerControl.LocalPlayer.RpcShareHostOption(this); } UpdateBehaviourValue(); } public abstract void UpdateValueFromBehaviour(); protected abstract void UpdateBehaviourValue(); } public abstract class BaseLocalOption : BaseOption { public static readonly List<BaseLocalOption> AllOptions = new List<BaseLocalOption>(); private string _lockHash; public BaseSettingBehaviour Behaviour { get; private set; } public event Action ValueChanged; protected BaseLocalOption(string name, string title) : base(name, title) { AllOptions.Add(this); } public virtual void OnBehaviourCreated(BaseSettingBehaviour behaviour) { Behaviour = behaviour; } public void LockWithPassword(string hash) { BetterVanillaManager.Instance.Features.RegisterHash(hash); _lockHash = hash; } public bool IsLocked() { if (!string.IsNullOrEmpty(_lockHash)) { return BetterVanillaManager.Instance.Features.IsLocked(_lockHash); } return false; } protected virtual void OnValueChanged() { Behaviour?.UpdateFromOption(); this.ValueChanged?.Invoke(); } } public abstract class BaseOption { public readonly string Name; public string Title { get; protected set; } protected BaseOption(string name, string title) { Name = name; Title = title; } public void WriteIn(MessageWriter writer) { writer.Write(Name); WriteValue(writer); } public abstract void WriteValue(MessageWriter messageWriter); public abstract void ReadValue(MessageReader messageReader); public abstract string GetValueString(); protected bool LoadValueFromDatabase(bool defaultValue) { return BetterVanillaManager.Instance.Database.Data.CurrentPreset.GetValueOrDefault(Name, defaultValue); } protected string LoadValueFromDatabase(string defaultValue) { return BetterVanillaManager.Instance.Database.Data.CurrentPreset.GetValueOrDefault(Name, defaultValue); } protected int LoadValueFromDatabase(int defaultValue) { return BetterVanillaManager.Instance.Database.Data.CurrentPreset.GetValueOrDefault(Name, defaultValue); } protected float LoadValueFromDatabase(float defaultValue) { return BetterVanillaManager.Instance.Database.Data.CurrentPreset.GetValueOrDefault(Name, defaultValue); } protected TEnum LoadValueFromDatabase<TEnum>(TEnum defaultValue) where TEnum : struct { return BetterVanillaManager.Instance.Database.Data.CurrentPreset.GetValueOrDefault(Name, defaultValue); } protected void SaveValueInDatabase(bool value) { BetterVanillaManager.Instance.Database.Data.CurrentPreset.BoolStore[Name] = value; BetterVanillaManager.Instance.Database.Save(); } protected void SaveValueInDatabase(string value) { BetterVanillaManager.Instance.Database.Data.CurrentPreset.StringStore[Name] = value; BetterVanillaManager.Instance.Database.Save(); } protected void SaveValueInDatabase(int value) { BetterVanillaManager.Instance.Database.Data.CurrentPreset.IntStore[Name] = value; BetterVanillaManager.Instance.Database.Save(); } protected void SaveValueInDatabase(float value) { BetterVanillaManager.Instance.Database.Data.CurrentPreset.FloatStore[Name] = value; BetterVanillaManager.Instance.Database.Save(); } protected void SaveValueInDatabase<TEnum>(TEnum value) where TEnum : struct { BetterVanillaManager.Instance.Database.Data.CurrentPreset.StringStore[Name] = value.ToString(); BetterVanillaManager.Instance.Database.Save(); } } public class BoolHostOption : BaseHostOption { private bool _value; private bool Value { get { return _value; } set { if (value != _value) { _value = value; OnValueChanged(); } } } public BoolHostOption(string name, string title, bool defaultValue) : base(name, title) { InitGameSetting<CheckboxGameSetting>((OptionTypes)1).OptionName = (BoolOptionNames)0; _value = LoadValueFromDatabase(defaultValue); } public override bool GetBool() { return Value; } public override void OnBehaviourCreated(OptionBehaviour behaviour) { base.OnBehaviourCreated(behaviour); OptionBehaviour obj = ((behaviour is ToggleOption) ? behaviour : null) ?? throw new ArgumentException("behaviour must be ToggleOption", "behaviour"); ((TMP_Text)((ToggleOption)obj).TitleText).SetText(base.Title, true); ((Renderer)((ToggleOption)obj).CheckMark).enabled = Value; } public override void UpdateValueFromBehaviour() { Value = base.Behaviour.GetBool(); } protected override void UpdateBehaviourValue() { if (Object.op_Implicit((Object)(object)base.Behaviour)) { ToggleOption obj = ((Il2CppObjectBase)base.Behaviour).TryCast<ToggleOption>(); if (!Object.op_Implicit((Object)(object)obj)) { throw new ArgumentException("behaviour must be ToggleOption"); } ((Renderer)obj.CheckMark).enabled = Value; } if (Object.op_Implicit((Object)(object)base.ViewBehaviour)) { base.ViewBehaviour.CustomSetInfoCheckbox(61, this); } } public override void WriteValue(MessageWriter messageWriter) { messageWriter.Write(Value); } public override void ReadValue(MessageReader messageReader) { Value = messageReader.ReadBoolean(); } public override string GetValueString() { return DestroyableSingleton<TranslationController>.Instance.GetString((StringNames)(Value ? 111 : 112), (Il2CppReferenceArray<Object>)null); } protected override void OnValueChanged() { base.OnValueChanged(); SaveValueInDatabase(Value); } } public sealed class BoolLocalOption : BaseLocalOption { private bool _value; public bool Value { get { return _value; } set { if (value != _value) { _value = value; OnValueChanged(); } } } public BoolLocalOption(string name, string title, bool defaultValue) : base(name, title) { _value = LoadValueFromDatabase(defaultValue); } public override void WriteValue(MessageWriter messageWriter) { messageWriter.Write(Value); } public override void ReadValue(MessageReader messageReader) { Value = messageReader.ReadBoolean(); } public override string GetValueString() { return DestroyableSingleton<TranslationController>.Instance.GetString((StringNames)(Value ? 111 : 112), (Il2CppReferenceArray<Object>)null); } protected override void OnValueChanged() { base.OnValueChanged(); SaveValueInDatabase(Value); } } public class FloatHostOption : BaseHostOption { private float _value; private readonly FloatGameSetting _settings; private float Value { get { return _value; } set { if (!Mathf.Approximately(value, _value)) { _value = value; OnValueChanged(); } } } public FloatHostOption(string name, string title, float defaultValue, float increment, FloatRange validRange, string formatString, bool zeroIsInfinity, NumberSuffixes suffixType) : base(name, title) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) _settings = InitGameSetting<FloatGameSetting>((OptionTypes)4); _settings.Value = (_value = LoadValueFromDatabase(defaultValue)); _settings.OptionName = (FloatOptionNames)0; _settings.Increment = increment; _settings.ValidRange = validRange; _settings.FormatString = formatString; _settings.ZeroIsInfinity = zeroIsInfinity; _settings.SuffixType = suffixType; } public override float GetFloat() { return Value; } public override void OnBehaviourCreated(OptionBehaviour behaviour) { base.OnBehaviourCreated(behaviour); OptionBehaviour obj = ((behaviour is NumberOption) ? behaviour : null) ?? throw new ArgumentException("behaviour must be NumberOption", "behaviour"); ((TMP_Text)((NumberOption)obj).TitleText).SetText(base.Title, true); ((NumberOption)obj).Value = Value; ((NumberOption)obj).AdjustButtonsActiveState(); } public override void UpdateValueFromBehaviour() { Value = base.Behaviour.GetFloat(); } protected override void UpdateBehaviourValue() { if (Object.op_Implicit((Object)(object)base.Behaviour)) { NumberOption obj = ((Il2CppObjectBase)base.Behaviour).TryCast<NumberOption>(); if (!Object.op_Implicit((Object)(object)obj)) { throw new ArgumentException("behaviour must be NumberOption"); } obj.Value = Value; obj.AdjustButtonsActiveState(); } if (Object.op_Implicit((Object)(object)base.ViewBehaviour)) { base.ViewBehaviour?.CustomSetInfo(61, this); } } public override void WriteValue(MessageWriter messageWriter) { messageWriter.Write(Value); } public override void ReadValue(MessageReader messageReader) { Value = messageReader.ReadSingle(); } public override string GetValueString() { return base.GameSetting.GetValueString(Value); } protected override void OnValueChanged() { base.OnValueChanged(); SaveValueInDatabase(Value); } } public sealed class FloatLocalOption : BaseLocalOption { private float _value; public readonly float Increment; public readonly FloatRange ValidRange; public readonly string Prefix; public readonly string Suffix; public float Value { get { return _value; } set { float num = value; if (num > ValidRange.max) { num = ValidRange.max; } else if (num < ValidRange.min) { num = ValidRange.min; } if (!Mathf.Approximately(num, _value)) { _value = num; OnValueChanged(); } } } public FloatLocalOption(string name, string title, float defaultValue, float increment, FloatRange validRange, string prefix, string suffix) : base(name, title) { Increment = increment; ValidRange = validRange; Prefix = prefix; Suffix = suffix; _value = LoadValueFromDatabase(defaultValue); } public override void WriteValue(MessageWriter messageWriter) { messageWriter.Write(Value); } public override void ReadValue(MessageReader messageReader) { Value = messageReader.ReadSingle(); } public override string GetValueString() { return $"{Prefix}{Value}{Suffix}"; } protected override void OnValueChanged() { base.OnValueChanged(); SaveValueInDatabase(Value); } } public sealed class HostCategory : BaseCategory { public static readonly List<HostCategory> AllCategories = new List<HostCategory>(); public readonly RulesCategory GameOptionsMenuCategory; public readonly List<BaseHostOption> AllOptions = new List<BaseHostOption>(); public HostCategory(string name) : base(name) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown GameOptionsMenuCategory = new RulesCategory { CategoryName = (StringNames)0, AllGameSettings = new List<BaseGameSetting>() }; AllCategories.Add(this); } private void RegisterInCategory(BaseHostOption option) { AllOptions.Add(option); GameOptionsMenuCategory.AllGameSettings.Add(option.GameSetting); } public BoolHostOption CreateBool(string name, string title, bool defaultValue) { BoolHostOption boolHostOption = new BoolHostOption(name, title, defaultValue); RegisterInCategory(boolHostOption); return boolHostOption; } public IntHostOption CreateInt(string name, string title, int defaultValue, int increment, IntRange validRange, string formatString, bool zeroIsInfinity, NumberSuffixes suffixType) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) IntHostOption intHostOption = new IntHostOption(name, title, defaultValue, increment, validRange, formatString, zeroIsInfinity, suffixType); RegisterInCategory(intHostOption); return intHostOption; } public FloatHostOption CreateFloat(string name, string title, float defaultValue, float increment, FloatRange validRange, string formatString, bool zeroIsInfinity, NumberSuffixes suffixType) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) FloatHostOption floatHostOption = new FloatHostOption(name, title, defaultValue, increment, validRange, formatString, zeroIsInfinity, suffixType); RegisterInCategory(floatHostOption); return floatHostOption; } } public class IntHostOption : BaseHostOption { private int _value; private int Value { get { return _value; } set { if (value != _value) { _value = value; OnValueChanged(); } } } public IntHostOption(string name, string title, int defaultValue, int increment, IntRange validRange, string formatString, bool zeroIsInfinity, NumberSuffixes suffixType) : base(name, title) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) IntGameSetting obj = InitGameSetting<IntGameSetting>((OptionTypes)5); obj.Value = (_value = LoadValueFromDatabase(defaultValue)); obj.OptionName = (Int32OptionNames)0; obj.Increment = increment; obj.ValidRange = validRange; obj.FormatString = formatString; obj.ZeroIsInfinity = zeroIsInfinity; obj.SuffixType = suffixType; } public override int GetInt() { return Value; } public override void OnBehaviourCreated(OptionBehaviour behaviour) { base.OnBehaviourCreated(behaviour); OptionBehaviour obj = ((behaviour is NumberOption) ? behaviour : null) ?? throw new ArgumentException("behaviour must be NumberOption", "behaviour"); ((TMP_Text)((NumberOption)obj).TitleText).SetText(base.Title, true); ((NumberOption)obj).Value = Value; ((NumberOption)obj).AdjustButtonsActiveState(); } public override void UpdateValueFromBehaviour() { Value = base.Behaviour.GetInt(); } protected override void UpdateBehaviourValue() { if (Object.op_Implicit((Object)(object)base.Behaviour)) { NumberOption obj = ((Il2CppObjectBase)base.Behaviour).TryCast<NumberOption>(); if (!Object.op_Implicit((Object)(object)obj)) { throw new ArgumentException("behaviour must be NumberOption"); } obj.Value = Value; obj.AdjustButtonsActiveState(); } if (Object.op_Implicit((Object)(object)base.ViewBehaviour)) { base.ViewBehaviour?.CustomSetInfo(61, this); } } public override void WriteValue(MessageWriter messageWriter) { messageWriter.Write(Value); } public override void ReadValue(MessageReader messageReader) { Value = messageReader.ReadInt32(); } public override string GetValueString() { return base.GameSetting.GetValueString((float)Value); } protected override void OnValueChanged() { base.OnValueChanged(); SaveValueInDatabase(Value); } } public sealed class IntLocalOption : BaseLocalOption { private int _value; public readonly int Increment; public readonly IntRange ValidRange; public readonly string Prefix; public readonly string Suffix; public int Value { get { return _value; } set { int num = value; if (num > ValidRange.max) { num = ValidRange.max; } else if (num < ValidRange.min) { num = ValidRange.min; } if (!Mathf.Approximately((float)num, (float)_value)) { _value = num; OnValueChanged(); } } } public IntLocalOption(string name, string title, int defaultValue, int increment, IntRange validRange, string prefix, string suffix) : base(name, title) { Increment = increment; ValidRange = validRange; Prefix = prefix; Suffix = suffix; _value = LoadValueFromDatabase(defaultValue); } public override void WriteValue(MessageWriter messageWriter) { messageWriter.Write(Value); } public override void ReadValue(MessageReader messageReader) { Value = messageReader.ReadInt32(); } public override string GetValueString() { return $"{Prefix}{Value}{Suffix}"; } protected override void OnValueChanged() { base.OnValueChanged(); SaveValueInDatabase(Value); } } public sealed class LocalCategory : BaseCategory { public static readonly List<LocalCategory> AllCategories = new List<LocalCategory>(); public readonly List<BaseLocalOption> AllOptions = new List<BaseLocalOption>(); public LocalCategory(string name) : base(name) { AllCategories.Add(this); } private void RegisterInCategory(BaseLocalOption option) { AllOptions.Add(option); } public BoolLocalOption CreateBool(string name, string title, bool defaultValue) { BoolLocalOption boolLocalOption = new BoolLocalOption(name, title, defaultValue); RegisterInCategory(boolLocalOption); return boolLocalOption; } public IntLocalOption CreateInt(string name, string title, int defaultValue, int increment, IntRange validRange, string prefix = "", string suffix = "") { IntLocalOption intLocalOption = new IntLocalOption(name, title, defaultValue, increment, validRange, prefix, suffix); RegisterInCategory(intLocalOption); return intLocalOption; } public FloatLocalOption CreateFloat(string name, string title, float defaultValue, float increment, FloatRange validRange, string prefix = "", string suffix = "") { FloatLocalOption floatLocalOption = new FloatLocalOption(name, title, defaultValue, increment, validRange, prefix, suffix); RegisterInCategory(floatLocalOption); return floatLocalOption; } public StringLocalOption CreateEnum<TEnum>(string name, string title, TEnum defaultValue) where TEnum : struct { Type typeFromHandle = typeof(TEnum); if (!typeFromHandle.IsEnum) { throw new ArgumentException("Type must be an enum", typeFromHandle.FullName); } Array values = Enum.GetValues(typeFromHandle); List<string> list = new List<string>(); List<string> list2 = new List<string>(); string text = defaultValue.ToString(); foreach (TEnum item in values) { string text2 = item.ToString(); if (text2 == null) { throw new Exception($"Unable to stringify enum key {item} in {typeFromHandle.FullName}"); } FieldInfo? field = typeFromHandle.GetField(text2); if (field == null) { throw new Exception("Unable to find field " + text2 + " in " + typeFromHandle.FullName); } NamedFieldAttribute customAttribute = field.GetCustomAttribute<NamedFieldAttribute>(); string text3 = ((customAttribute == null) ? text2 : customAttribute.Name); list.Add(text3); list2.Add(text2); if (text2 == text) { text = text3; } } StringLocalOption stringLocalOption = new StringLocalOption(name, title, text, list, list2); RegisterInCategory(stringLocalOption); return stringLocalOption; } } public class StringLocalOption : BaseLocalOption { private int _index; private readonly List<string> _realValues; public readonly List<string> Values; public int Index { get { return _index; } set { if (value != _index && value >= 0 && value < Values.Count) { _index = value; OnValueChanged(); } } } public string Value => Values[_index]; public string RealValue => _realValues[_index]; private int FindIndex(string value) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown int num = Values.IndexOf(value); if (num < 0 || num >= Values.Count) { bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(38, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to find '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' in Values in "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("StringLocalOption"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" named "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Name); } Ls.LogWarning(val); num = 0; } return num; } public StringLocalOption(string name, string title, string defaultValue, List<string> values, List<string> realValues) : base(name, title) { _realValues = realValues; Values = values; _index = LoadValueFromDatabase(FindIndex(defaultValue)); } public override void WriteValue(MessageWriter messageWriter) { messageWriter.Write(Index); } public override void ReadValue(MessageReader messageReader) { Index = messageReader.ReadInt32(); } public override string GetValueString() { return Value; } public TEnum ParseValue<TEnum>(TEnum defaultValue) where TEnum : struct { Type typeFromHandle = typeof(TEnum); if (!typeFromHandle.IsEnum) { throw new ArgumentException("Type myst be enum", typeFromHandle.Name); } if (!Enum.TryParse<TEnum>(RealValue, out var result)) { return defaultValue; } return result; } protected override void OnValueChanged() { base.OnValueChanged(); SaveValueInDatabase(Index); } } } namespace BetterVanilla.Core.Helpers { public static class AssetBundleUtils { public static AssetBundle LoadFromExecutingAssembly(string assetBundleName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); return AssetBundle.LoadFromMemory(Il2CppStructArray<byte>.op_Implicit(StreamExtensions.ReadBytes(executingAssembly.GetManifestResourceStream(assetBundleName) ?? throw new Exception("Unable to find resource: " + assetBundleName + " in assembly " + executingAssembly.FullName)))); } } public static class ColorUtils { public static readonly Color CheaterColor = Palette.ImpostorRed; public static readonly Color HostColor = Color.magenta; public static readonly Color ImpostorColor = Palette.ImpostorRed; private static readonly Color NoTasksDoneColor = new Color(0.76f, 0.16f, 0.52f, 1f); private static readonly Color AllTasksDoneColor = new Color(0.34f, 1f, 0.69f, 1f); public static Color TaskCountColor(int done, int total) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) float num = (float)done / (float)total; return Color.Lerp(NoTasksDoneColor, AllTasksDoneColor, num); } private static byte ToByte(float f) { f = Mathf.Clamp01(f); return (byte)(f * 255f); } public static string ColoredString(Color c, string s) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) return $"<color=#{ToByte(c.r):X2}{ToByte(c.g):X2}{ToByte(c.b):X2}{ToByte(c.a):X2}>{s}</color>"; } public static string ToHex(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) int value = Mathf.RoundToInt(color.r * 255f); int value2 = Mathf.RoundToInt(color.g * 255f); int value3 = Mathf.RoundToInt(color.b * 255f); int value4 = Mathf.RoundToInt(color.a * 255f); return $"#{value:X2}{value2:X2}{value3:X2}{value4:X2}"; } public static Color FromHex(string hexColor) { //IL_01b9: Unknown result type (might be due to invalid IL or missing references) if (hexColor.StartsWith("#")) { hexColor = hexColor.Replace("#", string.Empty); } int num = 0; int num2 = 0; int num3 = 0; int num4 = 255; switch (hexColor.Length) { case 8: num = int.Parse(MemoryExtensions.AsSpan(hexColor, 0, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); num2 = int.Parse(MemoryExtensions.AsSpan(hexColor, 2, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); num3 = int.Parse(MemoryExtensions.AsSpan(hexColor, 4, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); num4 = int.Parse(MemoryExtensions.AsSpan(hexColor, 6, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); break; case 6: num = int.Parse(MemoryExtensions.AsSpan(hexColor, 0, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); num2 = int.Parse(MemoryExtensions.AsSpan(hexColor, 2, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); num3 = int.Parse(MemoryExtensions.AsSpan(hexColor, 4, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); break; case 3: num = int.Parse(hexColor[0].ToString() + hexColor[0], NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); num2 = int.Parse(hexColor[1].ToString() + hexColor[1], NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); num3 = int.Parse(hexColor[2].ToString() + hexColor[2], NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); break; } return new Color((float)num / 255f, (float)num2 / 255f, (float)num3 / 255f, (float)num4 / 255f); } } public static class CoroutineUtils { public static IEnumerator CoAssertWithTimeout(Func<bool> assertion, Action onTimeout, float timeoutInSeconds) { bool failed = true; for (float timer = 0f; timer < timeoutInSeconds; timer += Time.deltaTime) { if (assertion()) { failed = false; break; } yield return null; } if (failed) { onTimeout?.Invoke(); } } public static IEnumerator RandomWait(float min = 1f, float max = 10f) { float num = Random.RandomRange(1f, 10f); yield return (object)new WaitForSeconds(num); } } public static class StringUtils { public static string CalculateSHA256(string text) { byte[] bytes = Encoding.UTF8.GetBytes(text); using SHA256 sHA = SHA256.Create(); return BitConverter.ToString(sHA.ComputeHash(bytes)).Replace("-", ""); } } } namespace BetterVanilla.Core.Extensions { public static class AssetBundleExtensions { public static T LoadAsset<T>(this AssetBundle assetBundle, string name) where T : Object { return ((Il2CppObjectBase)assetBundle.LoadAsset(name, Il2CppType.Of<T>())).Cast<T>(); } public static T LoadComponent<T>(this AssetBundle assetBundle, string name) where T : MonoBehaviour { return assetBundle.LoadAsset<GameObject>(name).GetComponent<T>(); } } public static class CategoryHeaderMaskedExtensions { private static readonly int StencilComp = Shader.PropertyToID("_StencilComp"); private static readonly int Stencil = Shader.PropertyToID("_Stencil"); public static void CustomSetHeader(this CategoryHeaderMasked headerMasked, int maskLayer, HostCategory category) { ((TMP_Text)headerMasked.Title).SetText(category.Name, true); ((Renderer)headerMasked.Background).material.SetInt(PlayerMaterial.MaskLayer, maskLayer); if (Object.op_Implicit((Object)(object)headerMasked.Divider)) { ((Renderer)headerMasked.Divider).material.SetInt(PlayerMaterial.MaskLayer, maskLayer); } ((TMP_Text)headerMasked.Title).fontMaterial.SetFloat(StencilComp, 3f); ((TMP_Text)headerMasked.Title).fontMaterial.SetFloat(Stencil, (float)maskLayer); } } public static class ChatBubbleExtensions { public static void SetPrivateChatBubbleName(this ChatBubble bubble, NetworkedPlayerInfo senderInfo, NetworkedPlayerInfo receiverInfo, bool isDead, bool didVote, Color nameColor) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) string text = ((PlayerControl.LocalPlayer.Data.PlayerName == receiverInfo.PlayerName) ? "me" : receiverInfo.PlayerName); string text2 = senderInfo.PlayerName + " " + ColorUtils.ColoredString(Color.gray, "[to " + text + "]"); bubble.SetName(text2, isDead, didVote, nameColor); } } public static class ChatControllerExtensions { public static void AddPrivateChat(this ChatController controller, PlayerControl sender, PlayerControl receiver, string chatText) { //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)sender) || !Object.op_Implicit((Object)(object)receiver)) { return; } NetworkedPlayerInfo data = sender.Data; NetworkedPlayerInfo data2 = receiver.Data; if ((Object)(object)data2 == (Object)null || (Object)(object)data == (Object)null) { return; } ChatBubble pooledBubble = controller.GetPooledBubble(); try { Transform transform = ((Component)pooledBubble).transform; transform.SetParent(controller.scroller.Inner); transform.localScale = Vector3.one; bool num = (Object)(object)sender == (Object)(object)PlayerControl.LocalPlayer; if (num) { pooledBubble.SetRight(); } else { pooledBubble.SetLeft(); } bool didVote = Object.op_Implicit((Object)(object)MeetingHud.Instance) && MeetingHud.Instance.DidVote(sender.PlayerId); pooledBubble.SetCosmetics(data); int colorId = data.Outfits[(PlayerOutfitType)0].ColorId; ChatBubbleExtensions.SetPrivateChatBubbleName(nameColor: Color32.op_Implicit((colorId < ((Il2CppArrayBase<Color32>)(object)Palette.PlayerColors).Count) ? ((Il2CppArrayBase<Color32>)(object)Palette.PlayerColors)[colorId] : ((Il2CppArrayBase<Color32>)(object)Palette.PlayerColors)[0]), bubble: pooledBubble, senderInfo: data, receiverInfo: data2, isDead: data.IsDead, didVote: didVote); pooledBubble.SetText(chatText); pooledBubble.AlignChildren(); controller.AlignAllBubbles(); if (!controller.IsOpenOrOpening && controller.notificationRoutine == null) { controller.notificationRoutine = ((MonoBehaviour)controller).StartCoroutine(controller.BounceDot()); } if (!num) { SoundManager.Instance.PlaySound(controller.messageSound, false, 1f, (AudioMixerGroup)null).pitch = (float)(0.5 + (double)(int)sender.PlayerId / 15.0); } } catch (Exception ex) { bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(45, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ChatControllerPatches.AddPrivateChat: failed "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } Ls.LogWarning(val); ((IObjectPool)controller.chatBubblePool).Reclaim((PoolableBehavior)(object)pooledBubble); } } } public static class EndGameNavigationExtensions { public static void SetupPlayAgain(this EndGameNavigation navigation) { if (LocalConditions.ShouldAutoPlayAgain()) { MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)navigation, navigation.CoPlayAgain()); } } private static IEnumerator CoPlayAgain(this EndGameNavigation navigation) { while (!navigation.ContinueButton.activeSelf) { yield return (object)new WaitForEndOfFrame(); } yield return (object)new WaitForSeconds(3f); PassiveButton componentInChildren = navigation.ContinueButton.GetComponentInChildren<PassiveButton>(); if (Object.op_Implicit((Object)(object)componentInChildren) && ((Behaviour)componentInChildren).enabled) { ((UnityEvent)componentInChildren.OnClick).Invoke(); } while (!((Renderer)navigation.PlayAgainButton).enabled) { yield return (object)new WaitForEndOfFrame(); } yield return (object)new WaitForSeconds(3f); PassiveButton component = ((Component)navigation.PlayAgainButton).gameObject.GetComponent<PassiveButton>(); if (Object.op_Implicit((Object)(object)component) && ((Behaviour)component).enabled) { ((UnityEvent)component.OnClick).Invoke(); } } } public static class EnumerableExtensions { public static List<T> ToIl2CppList<T>(this IEnumerable<T> enumerable) { List<T> val = new List<T>(); foreach (T item in enumerable) { val.Add(item); } return val; } } public static class GameManagerExtensions { public static List<RulesCategory> GetAllCategories(this GameManager gameManager) { List<RulesCategory> list = new List<RulesCategory>(); foreach (HostCategory allCategory in HostCategory.AllCategories) { list.Add(allCategory.GameOptionsMenuCategory); } Enumerator<RulesCategory> enumerator2 = gameManager.GameSettingsList.AllCategories.GetEnumerator(); while (enumerator2.MoveNext()) { RulesCategory current2 = enumerator2.Current; list.Add(current2); } return list; } } public static class GameOptionsMenuExtensions { public static bool CustomValueChanged(this GameOptionsMenu menu, OptionBehaviour optionBehaviour) { BaseHostOption baseHostOption = BaseHostOption.AllOptions.Find((BaseHostOption x) => (Object)(object)x.Behaviour == (Object)(object)optionBehaviour); if (baseHostOption == null) { return true; } baseHostOption.UpdateValueFromBehaviour(); return false; } public static void CreateBetterSettings(this GameOptionsMenu menu) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected I4, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) float num = 0.713f; foreach (RulesCategory allCategory in GameManager.Instance.GetAllCategories()) { HostCategory hostCategory = HostCategory.AllCategories.Find((HostCategory x) => ((Il2CppObjectBase)x.GameOptionsMenuCategory).Pointer == ((Il2CppObjectBase)allCategory).Pointer); CategoryHeaderMasked val = Object.Instantiate<CategoryHeaderMasked