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.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Photon.Pun; using Photon.Realtime; using REPOLib; using REPOLib.Modules; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Xuaun")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Registers MoreHead .hhh cosmetics into the vanilla REPO cosmetics system via REPOLib.")] [assembly: AssemblyFileVersion("3.0.0.0")] [assembly: AssemblyInformationalVersion("3.0.0+ce7a067d8229aec8619b63065777d71107459760")] [assembly: AssemblyProduct("MoreHeadBridge")] [assembly: AssemblyTitle("MoreHeadBridge")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 MoreHeadBridge { internal static class AtomicJson { internal static void Write(string path, string json) { string text = path + ".tmp"; File.WriteAllText(text, json, Encoding.UTF8); try { if (File.Exists(path)) { File.Replace(text, path, null); } else { File.Move(text, path); } } catch { try { if (File.Exists(text)) { File.Delete(text); } } catch { } throw; } } internal static Task QueueWrite(Task lastWrite, string path, string json, string errLabel) { return lastWrite.ContinueWith(delegate { try { Write(path, json); } catch (Exception ex) { BceConsole.LogWarning(errLabel + ": " + ex.Message); } }, TaskScheduler.Default); } } internal enum AvatarKind { Local, Menu, RemoteMini, Remote } internal readonly struct AvatarIdentity { public readonly AvatarKind Kind; public readonly int Actor; public bool IsRemote { get { if (Kind != AvatarKind.RemoteMini) { return Kind == AvatarKind.Remote; } return true; } } public AvatarIdentity(AvatarKind kind, int actor) { Kind = kind; Actor = actor; } public static AvatarIdentity Of(PlayerCosmetics instance) { if (!SemiFunc.IsMultiplayer()) { return new AvatarIdentity(AvatarKind.Local, -1); } int num = MiniSemibotSpawner.RemoteMiniActorOf(instance); if (num > 0) { return new AvatarIdentity(AvatarKind.RemoteMini, num); } if (MiniSemibotSpawner.IsMenuOrPreviewWearer(instance.playerAvatarVisuals)) { return new AvatarIdentity(AvatarKind.Menu, -1); } PhotonView val = ((Object.op_Implicit((Object)(object)instance.deathHead) && instance.deathHead.setup && Object.op_Implicit((Object)(object)instance.deathHead.playerAvatar)) ? instance.deathHead.playerAvatar.photonView : instance.photonView); if ((Object)(object)val == (Object)null || val.IsMine) { return new AvatarIdentity(AvatarKind.Local, -1); } Player owner = val.Owner; int num2 = ((owner != null) ? owner.ActorNumber : (-1)); if (num2 <= 0) { return new AvatarIdentity(AvatarKind.Local, -1); } return new AvatarIdentity(AvatarKind.Remote, num2); } internal static bool TryGetRemoteActor(PlayerCosmetics instance, out int actorNumber) { AvatarIdentity avatarIdentity = Of(instance); actorNumber = (avatarIdentity.IsRemote ? avatarIdentity.Actor : (-1)); return avatarIdentity.IsRemote; } internal static bool IsLocalOrMenu(PlayerCosmetics pc) { if ((Object)(object)pc == (Object)null) { return false; } PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if (playerAvatarVisuals != null && playerAvatarVisuals.isMenuAvatar) { return true; } if ((Object)(object)pc.photonView == (Object)null) { return true; } if (pc.photonView.IsMine) { return true; } if ((Object)(object)pc.deathHead != (Object)null && pc.deathHead.setup) { PlayerAvatar playerAvatar = pc.deathHead.playerAvatar; if (playerAvatar == null) { return false; } PhotonView photonView = playerAvatar.photonView; return ((photonView != null) ? new bool?(photonView.IsMine) : ((bool?)null)) == true; } return false; } internal static bool IsRemoteMini(PlayerCosmetics? pc) { return MiniSemibotSpawner.IsRemoteMiniCosmetics(pc); } internal static bool IsLocalStyleTarget(PlayerCosmetics pc) { if (IsLocalOrMenu(pc)) { return !IsRemoteMini(pc); } return false; } } internal static class BceConsole { private const string InfoPrefix = "[Info : MoreHead Bridge] "; private const string WarnPrefix = "[Warning: MoreHead Bridge] "; private const string ErrorPrefix = "[Error : MoreHead Bridge] "; private const string DebugPrefix = "[Debug : MoreHead Bridge] "; private static readonly Action? _writeLineDelegate; private static readonly Action? _writeDelegate; internal static bool IsAvailable => _writeLineDelegate != null; static BceConsole() { Type type = Type.GetType("BCE.console, BCE"); if (type == null) { return; } try { MethodInfo method = type.GetMethod("WriteLine", new Type[2] { typeof(string), typeof(ConsoleColor) }); MethodInfo method2 = type.GetMethod("Write", new Type[2] { typeof(string), typeof(ConsoleColor) }); if (method != null) { _writeLineDelegate = (Action)Delegate.CreateDelegate(typeof(Action), null, method); } if (method2 != null) { _writeDelegate = (Action)Delegate.CreateDelegate(typeof(Action), null, method2); } } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; if (logger != null) { logger.LogWarning((object)("BceConsole: delegate creation failed (" + ex.Message + "). BCE output disabled — falling back to BepInEx logger.")); } } } internal static void WriteLine(string msg, ConsoleColor color) { _writeLineDelegate?.Invoke(msg, color); } internal static void Write(string msg, ConsoleColor color) { _writeDelegate?.Invoke(msg, color); } internal static void LogInfo(string msg) { LogInfo(msg, ConsoleColor.Cyan); } internal static void LogInfo(string msg, ConsoleColor color) { if (IsAvailable) { WriteLine("[Info : MoreHead Bridge] " + msg, color); } else { Plugin.Logger.LogInfo((object)msg); } } internal static void LogWarning(string msg) { LogWarning(msg, ConsoleColor.Yellow); } internal static void LogWarning(string msg, ConsoleColor color) { if (IsAvailable) { WriteLine("[Warning: MoreHead Bridge] " + msg, color); } else { Plugin.Logger.LogWarning((object)msg); } } internal static void LogError(string msg) { if (IsAvailable) { WriteLine("[Error : MoreHead Bridge] " + msg, ConsoleColor.Red); } else { Plugin.Logger.LogError((object)msg); } } internal static void LogDebug(string msg) { if (IsAvailable) { WriteLine("[Debug : MoreHead Bridge] " + msg, ConsoleColor.DarkGray); } else { Plugin.Logger.LogDebug((object)msg); } } } public enum BlacklistLoadMode { NotLoadIngame, LoadOnHiddenMenu } internal static class BridgeBlacklist { private sealed class Entry { public string AssetId { get; set; } = ""; public string DisplayName { get; set; } = ""; } private sealed class SaveData { public List Entries { get; set; } = new List(); public List MirroredNames { get; set; } = new List(); } private sealed class MoreHeadBlacklistData { public List DecorationNames { get; set; } = new List(); } private static readonly Dictionary _byAssetId = new Dictionary(StringComparer.Ordinal); private static readonly HashSet _mirrored = new HashSet(StringComparer.Ordinal); private static readonly string SavePath = BridgePaths.Of("Blacklist.json"); private static readonly string MoreHeadPath = Path.Combine(Paths.ConfigPath, "MoreHeadBlacklist.json"); private static bool _loaded; internal static bool ExistedAtStartup { get; private set; } internal static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; ExistedAtStartup = File.Exists(SavePath); if (!ExistedAtStartup) { return; } try { SaveData saveData = JsonConvert.DeserializeObject(File.ReadAllText(SavePath)); if (saveData == null) { return; } foreach (Entry item in saveData.Entries ?? new List()) { if (!string.IsNullOrEmpty(item.AssetId)) { _byAssetId[item.AssetId] = item.DisplayName ?? ""; } } foreach (string item2 in saveData.MirroredNames ?? new List()) { _mirrored.Add(item2); } } catch (Exception ex) { BceConsole.LogWarning("BridgeBlacklist: load failed: " + ex.Message); } } internal static bool Contains(string assetId) { return _byAssetId.ContainsKey(assetId); } internal static void Add(string assetId, string displayName) { if (!string.IsNullOrEmpty(assetId)) { _byAssetId[assetId] = displayName ?? ""; } } internal static void SetBlacklisted(string assetId, string? displayName, bool blacklisted) { EnsureLoaded(); if (string.IsNullOrEmpty(assetId)) { return; } string value; if (blacklisted) { if (!_byAssetId.ContainsKey(assetId)) { _byAssetId[assetId] = displayName ?? ""; Save(); if (Plugin.MirrorBlacklistToMoreHead.Value) { MirrorAdd(displayName); } } } else if (_byAssetId.TryGetValue(assetId, out value)) { _byAssetId.Remove(assetId); Save(); if (Plugin.MirrorBlacklistToMoreHead.Value) { MirrorRemove(value); } } } internal static HashSet ReadMoreHeadNames() { HashSet hashSet = new HashSet(StringComparer.Ordinal); try { if (!File.Exists(MoreHeadPath)) { return hashSet; } foreach (string item in JsonConvert.DeserializeObject(File.ReadAllText(MoreHeadPath))?.DecorationNames ?? new List()) { hashSet.Add(item); } } catch (Exception ex) { BceConsole.LogWarning("BridgeBlacklist: reading MoreHead blacklist failed: " + ex.Message); } return hashSet; } internal static void Save() { try { Directory.CreateDirectory(BridgePaths.DataDir); SaveData saveData = new SaveData { Entries = _byAssetId.Select, Entry>((KeyValuePair kv) => new Entry { AssetId = kv.Key, DisplayName = kv.Value }).ToList(), MirroredNames = _mirrored.ToList() }; AtomicJson.Write(SavePath, JsonConvert.SerializeObject((object)saveData, (Formatting)1)); } catch (Exception ex) { BceConsole.LogWarning("BridgeBlacklist: save failed: " + ex.Message); } } internal static void MirrorToMoreHead() { if (!Plugin.MirrorBlacklistToMoreHead.Value) { return; } try { HashSet hashSet = ReadMoreHeadNames(); bool flag = false; foreach (string item in _byAssetId.Values.Where((string n) => !string.IsNullOrEmpty(n))) { if (hashSet.Add(item)) { _mirrored.Add(item); flag = true; } } if (flag) { WriteMoreHead(hashSet); Save(); } } catch (Exception ex) { BceConsole.LogWarning("BridgeBlacklist: mirror failed: " + ex.Message); } } private static void MirrorAdd(string? name) { if (string.IsNullOrEmpty(name)) { return; } try { HashSet hashSet = ReadMoreHeadNames(); if (hashSet.Add(name)) { _mirrored.Add(name); WriteMoreHead(hashSet); Save(); } } catch (Exception ex) { BceConsole.LogWarning("BridgeBlacklist: mirror add failed: " + ex.Message); } } private static void MirrorRemove(string? name) { if (string.IsNullOrEmpty(name) || !_mirrored.Contains(name)) { return; } try { HashSet hashSet = ReadMoreHeadNames(); if (hashSet.Remove(name)) { WriteMoreHead(hashSet); } _mirrored.Remove(name); Save(); } catch (Exception ex) { BceConsole.LogWarning("BridgeBlacklist: mirror remove failed: " + ex.Message); } } private static void WriteMoreHead(HashSet names) { Directory.CreateDirectory(Path.GetDirectoryName(MoreHeadPath)); File.WriteAllText(MoreHeadPath, JsonConvert.SerializeObject((object)new MoreHeadBlacklistData { DecorationNames = names.ToList() }, (Formatting)1)); } } internal static class BridgeIds { internal const string Prefix = "morehead-bridge:"; private static HashSet? _registeredSet; private static int _registeredCount = -1; private static HashSet RegisteredSet() { IReadOnlyList registeredCosmetics = Cosmetics.RegisteredCosmetics; if (_registeredSet == null || _registeredCount != registeredCosmetics.Count) { _registeredSet = new HashSet(registeredCosmetics); _registeredCount = registeredCosmetics.Count; } return _registeredSet; } internal static bool IsBridgeAsset(string? assetId) { if (!string.IsNullOrEmpty(assetId)) { return assetId.StartsWith("morehead-bridge:", StringComparison.Ordinal); } return false; } internal static bool IsBridgeAsset(CosmeticAsset? asset) { if ((Object)(object)asset != (Object)null) { return IsBridgeAsset(asset.assetId); } return false; } internal static bool IsModdedCosmetic(CosmeticAsset? asset) { if ((Object)(object)asset != (Object)null && !IsBridgeAsset(asset)) { return RegisteredSet().Contains(asset); } return false; } internal static bool HasAnyNonBridgeModded() { return Cosmetics.RegisteredCosmetics.Count > 0; } internal static bool IsCustomizable(CosmeticAsset? asset) { if (!IsBridgeAsset(asset)) { if (Plugin.AllowModdedOverrides.Value) { return IsModdedCosmetic(asset); } return false; } return true; } } internal static class BridgeLog { internal static void UserInfo(string msg) { BceConsole.LogInfo(msg); } internal static void UserInfo(string msg, ConsoleColor color) { BceConsole.LogInfo(msg, color); } internal static void UserWarning(string msg) { BceConsole.LogWarning(msg); } internal static void UserWarning(string msg, ConsoleColor color) { BceConsole.LogWarning(msg, color); } internal static void UserError(string msg) { BceConsole.LogError(msg); } internal static void Debug(string msg) { if (Plugin.ShowBridgeDebugLogs.Value) { BceConsole.LogDebug(msg); } } internal static void Trace(string msg) { Plugin.Logger.LogDebug((object)msg); } } internal static class BridgePaths { internal static readonly string DataDir = Path.Combine(Paths.ConfigPath, "MoreHeadBridge"); private static bool _migrated; internal static string Of(string fileName) { return Path.Combine(DataDir, fileName); } internal static void Init() { if (_migrated) { return; } _migrated = true; try { Directory.CreateDirectory(DataDir); string[] files = Directory.GetFiles(Paths.ConfigPath, "MoreHeadBridge_*.json"); foreach (string text in files) { string text2 = Path.Combine(DataDir, Path.GetFileName(text).Substring("MoreHeadBridge_".Length)); if (!File.Exists(text2)) { File.Move(text, text2); } } } catch (Exception ex) { BceConsole.LogWarning("BridgePaths: could not move legacy save files into MoreHeadBridge/ — " + ex.Message); } } } internal sealed class BridgeHideCondition : MonoBehaviour { private sealed class Target { internal Transform Transform; internal Vector3 BaseScale; internal Renderer[] Renderers = Array.Empty(); } private const float CheckInterval = 0.1f; private const float HideSpeed = 6f; private const float ShowSpeed = 4f; private Cosmetic _cosmetic; private PlayerCosmetics? _pc; private CosmeticHideConfig _config; private readonly List _targets = new List(); private float _checkTimer; private bool _hidden; private float _shownFactor = 1f; private bool _renderersDisabled; internal void Init(Cosmetic cosmetic, CosmeticHideConfig config) { _cosmetic = cosmetic; _pc = cosmetic.playerCosmetics; _config = config; CosmeticHideCondition[] componentsInChildren = ((Component)cosmetic).GetComponentsInChildren(true); foreach (CosmeticHideCondition val in componentsInChildren) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } _targets.Clear(); List meshParents = cosmetic.meshParents; if (meshParents != null && meshParents.Count > 0) { foreach (Transform meshParent in cosmetic.meshParents) { AddTarget(meshParent); } } if (_targets.Count == 0) { Renderer[] componentsInChildren2 = ((Component)cosmetic).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { AddTarget(((Component)val2).transform); } } } ((Behaviour)this).enabled = _targets.Count > 0 && config.HasAny; } private void AddTarget(Transform? t) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null) { return; } foreach (Target target in _targets) { if ((Object)(object)target.Transform == (Object)(object)t) { return; } } _targets.Add(new Target { Transform = t, BaseScale = t.localScale, Renderers = ((Component)t).GetComponentsInChildren(true) }); } private void LateUpdate() { //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (_targets.Count == 0) { return; } _checkTimer -= Time.deltaTime; if (_checkTimer <= 0f) { _checkTimer = 0.1f; _hidden = ShouldHide(); } float num = (_hidden ? 0f : 1f); float num2 = (_hidden ? 6f : 4f); _shownFactor = Mathf.MoveTowards(_shownFactor, num, num2 * Time.deltaTime); if (_shownFactor >= 0.999f && !_hidden) { EnsureRenderers(on: true); for (int i = 0; i < _targets.Count; i++) { Target target = _targets[i]; if ((Object)(object)target.Transform != (Object)null) { target.BaseScale = target.Transform.localScale; } } return; } float num3 = Mathf.SmoothStep(0f, 1f, _shownFactor); for (int num4 = _targets.Count - 1; num4 >= 0; num4--) { Target target2 = _targets[num4]; if ((Object)(object)target2.Transform == (Object)null) { _targets.RemoveAt(num4); } else { target2.Transform.localScale = target2.BaseScale * num3; } } EnsureRenderers(_shownFactor > 0.001f); } private void OnDestroy() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) foreach (Target target in _targets) { if ((Object)(object)target.Transform != (Object)null) { target.Transform.localScale = target.BaseScale; } Renderer[] renderers = target.Renderers; foreach (Renderer val in renderers) { if ((Object)(object)val != (Object)null) { val.enabled = true; } } } } private void EnsureRenderers(bool on) { if (_renderersDisabled == !on) { return; } _renderersDisabled = !on; foreach (Target target in _targets) { Renderer[] renderers = target.Renderers; foreach (Renderer val in renderers) { if ((Object)(object)val != (Object)null) { val.enabled = on; } } } } private bool ShouldHide() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_pc == (Object)null) { return false; } List whenConditions = _config.WhenConditions; if (whenConditions != null && whenConditions.Count > 0) { foreach (Type whenCondition in _config.WhenConditions) { if (_pc.ConditionCustomCheck(whenCondition)) { return true; } } } List whenPoses = _config.WhenPoses; if (whenPoses != null && whenPoses.Count > 0) { PlayerAvatarVisuals playerAvatarVisuals = _pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals != (Object)null && _config.WhenPoses.Contains(playerAvatarVisuals.currentPose)) { return true; } } List whenTypes = _config.WhenTypes; bool flag = whenTypes != null && whenTypes.Count > 0; List whenCosmetics = _config.WhenCosmetics; bool flag2 = whenCosmetics != null && whenCosmetics.Count > 0; if (flag || flag2) { PlayerAvatarVisuals playerAvatarVisuals2 = _pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals2 != (Object)null) { Cosmetic[] componentsInChildren = ((Component)playerAvatarVisuals2).GetComponentsInChildren(false); foreach (Cosmetic val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)_cosmetic)) { if (flag && _config.WhenTypes.Contains(val.type)) { return true; } if (flag2 && (Object)(object)val.cosmeticAsset != (Object)null && _config.WhenCosmetics.Contains(((Object)val.cosmeticAsset).name)) { return true; } } } } } return false; } } internal sealed class BridgeLiveBlocked : MonoBehaviour { private const float CheckInterval = 0.1f; private const float BlockedCooldown = 0.25f; private const float SwitchDebounce = 0.1f; private const float ProbeRadiusMin = 0.03f; private const float ProbeRadiusMax = 0.1f; private const float SpringStiffness = 120f; private const float SpringDamping = 14f; private const float SpringKickVelocity = 6f; private const float MaxBlockedDuration = 6f; private const string GrabHandleColliderName = "Health Grab"; private PlayerCosmetics? _pc; private Transform _target; private Transform _anchor; private DeathHeadFloorPose _pose; private MiniSemibotFollow? _miniFollow; private Vector3 _anchorLocalCenter; private float _localMaxExtent; private bool _valid; private LayerMask _layerMask; private float _springPos; private float _springVel; private bool _blocked; private float _checkTimer; private float _cooldownTimer; private float _switchTimer; private float _blockedDuration; private Vector3 _refPos; private Vector3 _refEuler; private Vector3 _refScale; internal void Init(Cosmetic cosmetic, DeathHeadFloorPose pose) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) _pc = cosmetic.playerCosmetics; _target = ((Component)cosmetic).transform; _anchor = (Transform)(((Object)(object)_target.parent != (Object)null) ? ((object)_target.parent) : ((object)_target)); _pose = pose; _pose.MigrateLegacy(); _refPos = _target.localPosition; _refEuler = _target.localEulerAngles; _refScale = _target.localScale; Transform val = _target; while ((Object)(object)val != (Object)null && (Object)(object)_miniFollow == (Object)null) { _miniFollow = ((Component)val).GetComponent(); val = val.parent; } if (TryGetWorldBounds(out var bounds)) { Vector3 val2 = ((Bounds)(ref bounds)).center + Vector3.up * ((Bounds)(ref bounds)).extents.y; _anchorLocalCenter = _anchor.InverseTransformPoint(val2); float num = Mathf.Max(new float[3] { ((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.y, ((Bounds)(ref bounds)).extents.z }); _localMaxExtent = num / Mathf.Max(0.0001f, Mathf.Abs(_anchor.lossyScale.y)); _valid = num > 0.0001f; } _layerMask = LayerMask.op_Implicit(LayerMask.op_Implicit(SemiFunc.LayerMaskGetPhysGrabObject()) + LayerMask.GetMask(new string[1] { "Default" }) + LayerMask.GetMask(new string[1] { "Enemy" })); } private bool IsLiveBody() { if ((Object)(object)_pc == (Object)null) { return false; } PlayerAvatarVisuals playerAvatarVisuals = _pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null) { return false; } if (!playerAvatarVisuals.isMenuAvatar) { return true; } if ((Object)(object)_miniFollow != (Object)null && !_miniFollow.ExpressionPreview && (Object)(object)_miniFollow.WearerVisuals != (Object)null) { return !MiniSemibotSpawner.IsMenuOrPreviewWearer(_miniFollow.WearerVisuals); } return false; } private void LateUpdate() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) if (!_valid || _pose == null) { return; } if (!_pose.ReactWhenAlive || !IsLiveBody()) { if (_springPos > 0.001f || Mathf.Abs(_springVel) > 0.001f) { _target.localPosition = _refPos; _target.localRotation = Quaternion.Euler(_refEuler); _target.localScale = _refScale; } _springPos = 0f; _springVel = 0f; _blocked = false; _blockedDuration = 0f; return; } if (_cooldownTimer > 0f) { _cooldownTimer -= Time.deltaTime; } if (_switchTimer > 0f) { _switchTimer -= Time.deltaTime; } bool blocked = _blocked; if (_switchTimer <= 0f) { _checkTimer -= Time.deltaTime; if (_checkTimer <= 0f) { _checkTimer = 0.1f; if (CheckBlocked()) { _blocked = true; _cooldownTimer = 0.25f; } else if (_cooldownTimer <= 0f) { _blocked = false; } } } if (_blocked) { _blockedDuration += Time.deltaTime; if (_blockedDuration >= 6f) { _blocked = false; _cooldownTimer = 0f; _blockedDuration = 0f; } } else { _blockedDuration = 0f; } if (_blocked != blocked) { _switchTimer = 0.1f; _springVel += (_blocked ? 6f : (-6f)); } float num = (_blocked ? 1f : 0f); float num2 = (num - _springPos) * 120f - _springVel * 14f; _springVel += num2 * Time.deltaTime; _springPos += _springVel * Time.deltaTime; float num3 = Mathf.Clamp01(_springPos); if (num3 <= 0f) { _refPos = _target.localPosition; _refEuler = _target.localEulerAngles; _refScale = _target.localScale; if (!_blocked && Mathf.Abs(_springVel) < 0.05f) { _springPos = 0f; _springVel = 0f; } } else { _target.localPosition = Vector3.Lerp(_refPos, new Vector3(_pose.PosX, _pose.PosY, _pose.PosZ), num3); _target.localRotation = Quaternion.Slerp(Quaternion.Euler(_refEuler), Quaternion.Euler(_pose.RotX, _pose.RotY, _pose.RotZ), num3); _target.localScale = Vector3.Lerp(_refScale, new Vector3(_pose.ScaleX, _pose.ScaleY, _pose.ScaleZ), num3); } } private void OnDestroy() { //IL_0035: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_target == (Object)null) && (_springPos > 0.001f || Mathf.Abs(_springVel) > 0.001f)) { _target.localPosition = _refPos; _target.localRotation = Quaternion.Euler(_refEuler); _target.localScale = _refScale; } } private bool CheckBlocked() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) Vector3 val = _anchor.TransformPoint(_anchorLocalCenter); float num = Mathf.Max(0.0001f, Mathf.Abs(_anchor.lossyScale.y)); float num2 = ((num < 1f) ? Mathf.Sqrt(num) : num); float num3 = Mathf.Clamp(_localMaxExtent * num2 * 0.25f, 0.03f * num2, 0.1f * num2); Collider[] array = Physics.OverlapSphere(val, num3, LayerMask.op_Implicit(_layerMask), (QueryTriggerInteraction)2); Collider[] array2 = array; foreach (Collider val2 in array2) { if (!((Object)(object)val2 == (Object)null) && !(((Object)val2).name == "Health Grab") && !((Object)(object)((Component)val2).GetComponentInParent() != (Object)null) && !((Object)(object)((Component)val2).GetComponentInParent() != (Object)null)) { return true; } } return false; } private bool TryGetWorldBounds(out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) bounds = default(Bounds); Renderer[] componentsInChildren = ((Component)_target).GetComponentsInChildren(true); bool flag = false; Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } if (flag) { return true; } Renderer[] array2 = componentsInChildren; foreach (Renderer val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { if (!flag) { bounds = val2.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val2.bounds); } } } return flag; } } internal static class CosmeticEquipAnimation { private static FieldInfo? _equipLerpField; private static FieldInfo? _meshParentsScaleField; internal static void Finish(GameObject go) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) try { Cosmetic val = (((Object)(object)go != (Object)null) ? go.GetComponentInChildren(true) : null); if ((Object)(object)val == (Object)null) { return; } if ((object)_equipLerpField == null) { _equipLerpField = AccessTools.Field(typeof(Cosmetic), "equipLerp"); } _equipLerpField?.SetValue(val, 1f); if ((object)_meshParentsScaleField == null) { _meshParentsScaleField = AccessTools.Field(typeof(Cosmetic), "meshParentsScale"); } if (!(_meshParentsScaleField?.GetValue(val) is List list)) { return; } List meshParents = val.meshParents; for (int i = 0; i < meshParents.Count && i < list.Count; i++) { if ((Object)(object)meshParents[i] != (Object)null) { meshParents[i].localScale = list[i]; } } } catch (Exception ex) { BridgeLog.Trace("CosmeticEquipAnimation.Finish failed: " + ex.Message); } } } internal static class MultiEquipTypeFlags { private static readonly Dictionary _originals = new Dictionary(); internal static void Sync() { if (!Plugin.AllowMultipleCosmetics.Value) { Restore(); } else { Apply(); } } private static void Apply() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) MetaManager instance = MetaManager.instance; if (instance?.cosmeticTypeAssets == null) { return; } foreach (CosmeticTypeAsset cosmeticTypeAsset in instance.cosmeticTypeAssets) { if (!((Object)(object)cosmeticTypeAsset == (Object)null) && MultiEquipTypes.All.Contains(cosmeticTypeAsset.type)) { if (!_originals.ContainsKey(cosmeticTypeAsset)) { _originals[cosmeticTypeAsset] = cosmeticTypeAsset.canEquipMultiple; } cosmeticTypeAsset.canEquipMultiple = true; } } } internal static void Restore() { if (_originals.Count == 0) { return; } foreach (KeyValuePair original in _originals) { if ((Object)(object)original.Key != (Object)null) { original.Key.canEquipMultiple = original.Value; } } _originals.Clear(); } } internal static class MultiEquipTypes { internal static readonly HashSet All = new HashSet { (CosmeticType)0, (CosmeticType)30, (CosmeticType)31, (CosmeticType)32, (CosmeticType)18, (CosmeticType)17, (CosmeticType)20, (CosmeticType)21, (CosmeticType)1, (CosmeticType)2, (CosmeticType)3, (CosmeticType)19, (CosmeticType)4, (CosmeticType)22 }; } [HarmonyPatch(typeof(MetaManager), "Awake")] internal static class MultiEquipFlagsApplyPatch { [HarmonyPostfix] private static void Postfix() { MultiEquipTypeFlags.Sync(); } } internal static class CustomizerIO { internal static string ExportFolder => Path.Combine(Paths.ConfigPath, "MoreHeadBridge"); internal static string ExportFilePath => Path.Combine(ExportFolder, "overrides_export.json"); internal static void ExportAll() { Dictionary allData = CustomizerStore.GetAllData(); if (allData.Count == 0) { BceConsole.LogInfo("CustomizerIO: no overrides to export."); } else { MergeWrite(allData); } } internal static void ExportSingle(string assetId) { if (!CustomizerStore.TryGet(assetId, out CosmeticOverrideData data)) { BceConsole.LogWarning("CustomizerIO: no saved override for '" + assetId + "' — save first."); return; } MergeWrite(new Dictionary { [assetId] = data }); } internal static void ImportMerge() { try { if (!File.Exists(ExportFilePath)) { BceConsole.LogWarning("CustomizerIO: export file not found — nothing to import."); return; } string text = File.ReadAllText(ExportFilePath); Dictionary dictionary = JsonConvert.DeserializeObject>(text); if (dictionary == null || dictionary.Count == 0) { BceConsole.LogWarning("CustomizerIO: export file is empty — nothing to import."); return; } CustomizerStore.ImportBatch(dictionary); BceConsole.LogInfo($"CustomizerIO: imported {dictionary.Count} override(s) from {ExportFilePath}"); } catch (Exception ex) { BceConsole.LogWarning("CustomizerIO: import failed — " + ex.Message); } } private static void MergeWrite(Dictionary incoming) { try { Directory.CreateDirectory(ExportFolder); Dictionary dictionary = new Dictionary(); if (File.Exists(ExportFilePath)) { string text = File.ReadAllText(ExportFilePath); Dictionary dictionary2 = JsonConvert.DeserializeObject>(text); if (dictionary2 != null) { dictionary = dictionary2; } } foreach (KeyValuePair item in incoming) { dictionary[item.Key] = item.Value; } string json = JsonConvert.SerializeObject((object)dictionary, (Formatting)1); AtomicJson.Write(ExportFilePath, json); BceConsole.LogInfo($"CustomizerIO: exported {incoming.Count} override(s) to {ExportFilePath}"); } catch (Exception ex) { BceConsole.LogWarning("CustomizerIO: export failed — " + ex.Message); } } } internal static class BridgeFavoritesManager { private sealed class SaveData { public List Favorites { get; set; } = new List(); public List Hidden { get; set; } = new List(); } private static readonly HashSet _favorites = new HashSet(); private static readonly HashSet _hidden = new HashSet(); private static bool _loaded; private static readonly string SavePath = BridgePaths.Of("Favorites.json"); private static Task _lastWrite = Task.CompletedTask; internal static void EnsureLoaded() { if (!_loaded) { _loaded = true; Load(); } } internal static bool IsFavorite(CosmeticAsset? asset) { if ((Object)(object)asset != (Object)null) { return _favorites.Contains(KeyFor(asset)); } return false; } internal static bool IsHidden(CosmeticAsset? asset) { if ((Object)(object)asset != (Object)null) { return _hidden.Contains(KeyFor(asset)); } return false; } internal static bool HasAnyFavorite() { return _favorites.Count > 0; } internal static bool HasAnyHidden() { return _hidden.Count > 0; } internal static bool ToggleFavorite(CosmeticAsset asset) { string item = KeyFor(asset); if (_favorites.Remove(item)) { Save(); return false; } _hidden.Remove(item); _favorites.Add(item); Save(); return true; } internal static bool ToggleHidden(CosmeticAsset asset) { string item = KeyFor(asset); if (_hidden.Remove(item)) { Save(); return false; } _favorites.Remove(item); _hidden.Add(item); Save(); return true; } internal static void EnsureHidden(CosmeticAsset asset) { EnsureLoaded(); string item = KeyFor(asset); _favorites.Remove(item); if (_hidden.Add(item)) { Save(); } } private static void Load() { try { if (!File.Exists(SavePath)) { return; } SaveData saveData = JsonConvert.DeserializeObject(File.ReadAllText(SavePath)); if (saveData == null) { return; } _favorites.Clear(); _hidden.Clear(); foreach (string item in saveData.Favorites ?? new List()) { _favorites.Add(item); } foreach (string item2 in saveData.Hidden ?? new List()) { _hidden.Add(item2); } BceConsole.LogInfo($"BridgeFavoritesManager: loaded {_favorites.Count} favorite(s), {_hidden.Count} hidden.", ConsoleColor.DarkBlue); } catch (Exception ex) { BceConsole.LogWarning("BridgeFavoritesManager: load failed: " + ex.Message); } } private static void Save() { string json = JsonConvert.SerializeObject((object)new SaveData { Favorites = new List(_favorites), Hidden = new List(_hidden) }, (Formatting)1); _lastWrite = AtomicJson.QueueWrite(_lastWrite, SavePath, json, "BridgeFavoritesManager: save failed"); } internal static void FlushPendingWrites() { try { _lastWrite.Wait(TimeSpan.FromSeconds(2.0)); } catch { } } private static string KeyFor(CosmeticAsset asset) { if (!string.IsNullOrEmpty(asset.assetId)) { return asset.assetId; } if (!string.IsNullOrEmpty(asset.assetName)) { return asset.assetName; } return ((Object)asset).name ?? ""; } } internal static class FavHideIcons { private const string ResourcePrefix = "MoreHeadBridge.Icons.Resources."; private static Sprite? _star; private static Sprite? _hide; internal static Sprite? StarSprite => _star ?? (_star = LoadSprite("star.png")); internal static Sprite? HideSprite => _hide ?? (_hide = LoadSprite("hide.png")); private static Sprite? LoadSprite(string fileName) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) try { string text = "MoreHeadBridge.Icons.Resources." + fileName; using Stream stream = typeof(FavHideIcons).Assembly.GetManifestResourceStream(text); if (stream == null) { BceConsole.LogWarning("FavHideIcons: embedded resource '" + text + "' not found"); return null; } byte[] array = new byte[stream.Length]; for (int i = 0; i < array.Length; i += stream.Read(array, i, array.Length - i)) { } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)val).name = "MoreHeadBridge_" + fileName; ((Texture)val).filterMode = (FilterMode)1; if (!ImageConversion.LoadImage(val, array)) { BceConsole.LogWarning("FavHideIcons: Texture2D.LoadImage failed for '" + text + "'"); return null; } MaskWhitePixels(val); Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width); ((Object)val2).name = "MoreHeadBridge_" + fileName; return val2; } catch (Exception ex) { BceConsole.LogWarning("FavHideIcons: error loading '" + fileName + "': " + ex.Message); return null; } } private static void MaskWhitePixels(Texture2D tex) { //IL_000d: 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_0013: 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_002d: Unknown result type (might be due to invalid IL or missing references) Color32[] pixels = tex.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { Color32 val = pixels[i]; if (val.r > 220 && val.g > 220 && val.b > 220) { pixels[i].a = 0; } } tex.SetPixels32(pixels); tex.Apply(); } } internal static class FavHideMarkerHelper { private const string MarkerName = "MHB_FavHideMarker"; private const float OffsetX = -7f; private const float OffsetY = 7f; private const float Size = 9f; internal static void UpdateMarker(MenuElementCosmeticButton btn) { if (!((Object)(object)btn == (Object)null) && !((Object)(object)btn.cosmeticAsset == (Object)null)) { bool isFav = BridgeFavoritesManager.IsFavorite(btn.cosmeticAsset); bool isHide = BridgeFavoritesManager.IsHidden(btn.cosmeticAsset); UpdateMarker(btn, isFav, isHide); } } internal static void UpdateMarker(MenuElementCosmeticButton btn, bool isFav, bool isHide) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)btn == (Object)null || (Object)(object)btn.cosmeticAsset == (Object)null) { return; } Transform val = ((Component)btn).transform.Find("MHB_FavHideMarker"); if (!isFav && !isHide) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } return; } Image val4; if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject("MHB_FavHideMarker"); RectTransform val3 = val2.AddComponent(); val2.transform.SetParent(((Component)btn).transform, false); val2.transform.SetAsLastSibling(); val3.anchorMin = new Vector2(1f, 0f); val3.anchorMax = new Vector2(1f, 0f); val3.pivot = new Vector2(1f, 0f); ApplyRect(val3); val4 = val2.AddComponent(); ((Graphic)val4).raycastTarget = false; val4.preserveAspect = true; } else { val.SetAsLastSibling(); ApplyRect(((Component)val).GetComponent()); val4 = ((Component)val).GetComponent(); } if (!((Object)(object)val4 == (Object)null)) { if (isFav) { val4.sprite = FavHideIcons.StarSprite; ((Graphic)val4).color = Color.white; } else { val4.sprite = FavHideIcons.HideSprite; ((Graphic)val4).color = Color.white; } } } private static void ApplyRect(RectTransform? rt) { //IL_0015: 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) if (!((Object)(object)rt == (Object)null)) { rt.anchoredPosition = new Vector2(-7f, 7f); rt.sizeDelta = new Vector2(9f, 9f); } } } [HarmonyPatch(typeof(MenuElementCosmeticButton), "ToggleCosmetic")] [HarmonyPriority(400)] internal static class FavHideTogglePatch { private static MethodInfo? _triggerClickAnimations; private static bool _triggerLookupDone; private static int _lastShiftFrame = int.MinValue; [HarmonyPrefix] private static bool Prefix(MenuElementCosmeticButton __instance) { //IL_0214: Unknown result type (might be due to invalid IL or missing references) VariantCell component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { component.OnClick?.Invoke(); return false; } bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); bool flag2 = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); bool flag3 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); if (flag3) { _lastShiftFrame = Time.frameCount; } bool flag4 = flag3 || (_lastShiftFrame >= 0 && Time.frameCount - _lastShiftFrame <= 3); if (!flag && !flag2 && !flag4) { CosmeticGroupButton group = ((Component)__instance).GetComponent(); if ((Object)(object)group != (Object)null && group.IsActive && Plugin.MenuLibAvailable) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { CosmeticVariantPopup.Show(__instance, group); }); return false; } } if (!flag && !flag2 && !flag4) { return true; } if ((flag || flag2) && !Plugin.EnableMenuEnhancements.Value) { return true; } if ((Object)(object)__instance.menuButton != (Object)null && __instance.menuButton.disabled) { return true; } CosmeticAsset asset = __instance.cosmeticAsset; if ((Object)(object)asset == (Object)null) { return true; } if (flag4 && !flag && !flag2) { if (Plugin.EnableCosmeticCustomizer.Value && Plugin.MenuLibAvailable && BridgeIds.IsCustomizable(asset)) { bool flag5 = __instance.IsEquipped(); PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { CosmeticOverridePopup.Show(asset); }); return !flag5; } return true; } BridgeFavoritesManager.EnsureLoaded(); if (flag) { BridgeFavoritesManager.ToggleFavorite(asset); } else { BridgeFavoritesManager.ToggleHidden(asset); } try { __instance.soundClick.Play(MenuManager.instance.soundPosition, 1f, 1f, 1f, 1f); } catch (Exception ex) { BridgeLog.Trace("FavHideTogglePatch: sound skipped — " + ex.Message); } if (!_triggerLookupDone) { _triggerClickAnimations = AccessTools.Method(typeof(MenuElementCosmeticButton), "TriggerClickAnimations", (Type[])null, (Type[])null); _triggerLookupDone = true; } try { _triggerClickAnimations?.Invoke(__instance, null); } catch (Exception ex2) { BridgeLog.Trace("FavHideTogglePatch: animation skipped — " + ex2.Message); } FavHideMarkerHelper.UpdateMarker(__instance); return false; } } internal static class HhhCosmeticLoader { internal static readonly List RegisteredAssetIds = new List(); internal static readonly HashSet WorldAssetIds = new HashSet(); private static readonly Dictionary _sourcePath = new Dictionary(StringComparer.Ordinal); internal static readonly Dictionary BridgeIconTextures = new Dictionary(); private static readonly Dictionary TagMap = new Dictionary { ["head"] = ((CosmeticType)0, OverrideCosmeticType.Hat), ["neck"] = ((CosmeticType)30, OverrideCosmeticType.HeadBottom), ["body"] = ((CosmeticType)20, OverrideCosmeticType.BodyTop), ["hip"] = ((CosmeticType)21, OverrideCosmeticType.BodyBottom), ["rightarm"] = ((CosmeticType)1, OverrideCosmeticType.ArmRight), ["leftarm"] = ((CosmeticType)2, OverrideCosmeticType.ArmLeft), ["rightleg"] = ((CosmeticType)3, OverrideCosmeticType.LegRight), ["leftleg"] = ((CosmeticType)4, OverrideCosmeticType.LegLeft), ["world"] = ((CosmeticType)0, OverrideCosmeticType.World) }; private static readonly HashSet ValidTags; private static readonly HashSet _usedPrefabIds; private static readonly HashSet _usedInternalNames; private static bool _seeding; private static HashSet? _seedNames; private static bool _moreHeadFixDone; private static Rarity _lastAppliedRarity; private static bool? _lastAppliedTinting; private static readonly Dictionary _originalTypes; private static readonly Dictionary _originalTintable; internal static bool IsFromFolder(CosmeticAsset? asset, string folderName) { if ((Object)(object)asset == (Object)null || string.IsNullOrEmpty(folderName)) { return false; } if (_sourcePath.TryGetValue(asset.assetId, out string value)) { return value.IndexOf(folderName, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } internal static string? SourceModFolder(CosmeticAsset? asset) { if ((Object)(object)asset == (Object)null) { return null; } if (!_sourcePath.TryGetValue(asset.assetId, out string value) || string.IsNullOrEmpty(value)) { return null; } string[] array = value.Replace('\\', '/').Split('/'); for (int i = 0; i < array.Length - 1; i++) { if (string.Equals(array[i], "plugins", StringComparison.OrdinalIgnoreCase)) { if (array[i + 1].Length <= 0) { return null; } return array[i + 1]; } } return null; } public static void LoadAll() { BridgeBlacklist.EnsureLoaded(); _seeding = !BridgeBlacklist.ExistedAtStartup; _seedNames = (_seeding ? BridgeBlacklist.ReadMoreHeadNames() : null); string pluginPath = Paths.PluginPath; string[] files = Directory.GetFiles(pluginPath, "*.hhh", SearchOption.AllDirectories); string text = Plugin.SpecificFolders.Value ?? ""; if (!string.IsNullOrWhiteSpace(text)) { char[] invalidChars = Path.GetInvalidPathChars(); string[] array = (from s in (from s in text.Split(',') select s.Trim() into s where s.Length > 0 select s).Select(delegate(string s) { string text2 = new string(s.Where((char c) => !invalidChars.Contains(c)).ToArray()); if (text2 != s) { BceConsole.LogWarning("SpecificFolders: '" + s + "' contained invalid path characters — changed to '" + text2 + "'"); } return text2; }) where s.Length > 0 select s).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); string[] matched = array.Where((string a) => files.Any((string f) => f.IndexOf(a, StringComparison.OrdinalIgnoreCase) >= 0)).ToArray(); string[] array2 = array.Except(matched, StringComparer.OrdinalIgnoreCase).ToArray(); if (matched.Length == 0) { BceConsole.LogWarning("SpecificFolders: none of the specified folders were found (" + string.Join(", ", array) + "). Loading all .hhh files instead"); } else { if (array2.Length != 0) { BceConsole.LogWarning("SpecificFolders: folder(s) not found and skipped: " + string.Join(", ", array2)); } int num = files.Length; files = files.Where((string f) => matched.Any((string a) => f.IndexOf(a, StringComparison.OrdinalIgnoreCase) >= 0)).ToArray(); BceConsole.LogInfo(string.Format("SpecificFolders: loaded from {0} — kept {1}/{2} files", string.Join(", ", matched), files.Length, num)); } } BceConsole.LogInfo($"Found {files.Length} .hhh file(s). Translating cosmetics from MoreHead to Vanilla REPO..."); int num2 = 0; int num3 = Math.Max(2, Environment.ProcessorCount); Queue<(string, Task)> queue = new Queue<(string, Task)>(num3); int num4 = 0; while (num4 < files.Length && queue.Count < num3) { string p = files[num4++]; queue.Enqueue((p, Task.Run(() => ReadBytesOrNull(p)))); } while (queue.Count > 0) { (string, Task) tuple = queue.Dequeue(); string item = tuple.Item1; Task item2 = tuple.Item2; byte[] result = item2.GetAwaiter().GetResult(); if (TryRegister(item, result)) { num2++; } if (num4 < files.Length) { string p2 = files[num4++]; queue.Enqueue((p2, Task.Run(() => ReadBytesOrNull(p2)))); } } int num5 = files.Length; int num6 = num5 - num2; BceConsole.LogInfo($"Done — {num2}/{num5} registered, {num6} error(s)"); if (_seeding) { BridgeBlacklist.Save(); } BridgeBlacklist.MirrorToMoreHead(); } private static byte[]? ReadBytesOrNull(string path) { try { FileInfo fileInfo = new FileInfo(path); return (fileInfo.Exists && fileInfo.Length >= 1024) ? File.ReadAllBytes(path) : null; } catch { return null; } } private static bool TryRegister(string path, byte[]? bytes = null) { //IL_0058: 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) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) FileInfo fileInfo = new FileInfo(path); if (!fileInfo.Exists || fileInfo.Length < 1024) { BceConsole.LogWarning("Skipped (too small/missing): " + Path.GetFileName(path)); return false; } string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); ParseFileName(fileNameWithoutExtension, out string name, out string tag); if (!TagMap.TryGetValue(tag, out (CosmeticType, OverrideCosmeticType) value)) { return false; } CosmeticType item = value.Item1; AssetBundle val = ((bytes != null) ? AssetBundle.LoadFromMemory(bytes) : AssetBundle.LoadFromFile(path)); if ((Object)(object)val == (Object)null) { BceConsole.LogError("Failed to load bundle: " + fileNameWithoutExtension); return false; } GameObject val2 = LoadFirstPrefab(val); val.Unload(false); if ((Object)(object)val2 == (Object)null) { BceConsole.LogError("No GameObject in bundle: " + fileNameWithoutExtension); return false; } if (!val2.activeSelf) { val2.SetActive(true); } string name2 = ((Object)val2).name; ((Object)val2).name = EnsureUniqueId(name2, _usedPrefabIds); string text = name; name = EnsureUniqueId(name, _usedInternalNames); bool flag = ((Object)val2).name != name2; bool flag2 = name != text; if (flag && flag2 && name2 == text) { if (((Object)val2).name == name) { BceConsole.LogWarning("Duplicate name '" + name2 + "' — renamed internal and prefab to '" + name + "'.", ConsoleColor.DarkYellow); } else { BceConsole.LogWarning("Duplicate name '" + name2 + "' — prefab renamed to '" + ((Object)val2).name + "', internal id to '" + name + "'.", ConsoleColor.DarkYellow); } } else { if (flag) { BceConsole.LogWarning("Duplicate prefab name '" + name2 + "' → renamed to '" + ((Object)val2).name + "'", ConsoleColor.DarkYellow); } if (flag2) { BceConsole.LogWarning("Duplicate internal id '" + text + "' → renamed to '" + name + "'", ConsoleColor.DarkYellow); } } string text2 = "morehead-bridge:" + name.ToLowerInvariant(); bool flag3 = _seeding && _seedNames != null && _seedNames.Contains(name2); if (flag3) { BridgeBlacklist.Add(text2, name2); } bool flag4 = false; if (BridgeBlacklist.Contains(text2)) { if (Plugin.BridgeBlacklistMode.Value == BlacklistLoadMode.NotLoadIngame) { Object.Destroy((Object)(object)val2); return false; } flag4 = true; } Cosmetic val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(); } val3.type = item; PrefabRef val4 = NetworkPrefabs.RegisterNetworkPrefab("Cosmetics/" + ((Object)val2).name, val2); if (val4 == null) { BceConsole.LogError("Failed to register network prefab: " + name); return false; } CosmeticAsset val5 = ScriptableObject.CreateInstance(); ((Object)val5).name = name; val5.assetName = name2; val5.type = item; val5.prefab = val4; val5.assetId = text2; val5.rarity = Plugin.BridgeDefaultRarity.Value; val5.customTypeList = new List(); bool flag5 = BridgeTintHelper.DetectTintable(val2); _originalTintable[text2] = flag5; val5.tintable = Plugin.EnableBridgeTinting.Value && flag5; _originalTypes[text2] = value.Item2; CustomizerStore.ApplyIfPresent(val5); Cosmetics.RegisterCosmetic(val5); if (flag4 && flag3) { BridgeFavoritesManager.EnsureHidden(val5); } RegisteredAssetIds.Add(text2); _sourcePath[text2] = path; if (tag == "world") { WorldAssetIds.Add(text2); } Texture2D val6 = TryExtractIconTexture(val2); if ((Object)(object)val6 != (Object)null) { BridgeIconTextures[text2] = val6; } return true; } private static GameObject? LoadFirstPrefab(AssetBundle bundle) { string[] allAssetNames = bundle.GetAllAssetNames(); foreach (string text in allAssetNames) { GameObject val = bundle.LoadAsset(text); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Texture2D? TryExtractIconTexture(GameObject prefab) { Renderer[] componentsInChildren = prefab.GetComponentsInChildren(true); string[] array = new string[5] { "_MainTex", "_BaseMap", "_BaseColorMap", "_Albedo", "_AlbedoMap" }; Renderer[] array2 = componentsInChildren; foreach (Renderer val in array2) { if ((Object)(object)val == (Object)null) { continue; } Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if ((Object)(object)val2 == (Object)null) { continue; } string[] array3 = array; foreach (string text in array3) { if (val2.HasProperty(text)) { Texture texture = val2.GetTexture(text); Texture2D val3 = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (val3 != null && (Object)(object)val3 != (Object)null) { return val3; } } } } } return null; } private static void ParseFileName(string fileName, out string name, out string tag) { int num = fileName.LastIndexOf('_'); if (num >= 0) { int num2 = num + 1; string text = fileName.Substring(num2, fileName.Length - num2).ToLowerInvariant(); if (ValidTags.Contains(text)) { name = fileName.Substring(0, num); tag = text; return; } } name = fileName; tag = "head"; } private static string EnsureUniqueId(string baseName, HashSet used) { string text = baseName; int num = 1; while (!used.Add(text)) { text = $"{baseName}({num})"; num++; } return text; } internal static bool IsWorldAsset(CosmeticAsset? asset) { if ((Object)(object)asset != (Object)null && BridgeIds.IsBridgeAsset(asset)) { return WorldAssetIds.Contains(asset.assetId); } return false; } internal static bool TryGetOriginalType(string assetId, out OverrideCosmeticType type) { return _originalTypes.TryGetValue(assetId, out type); } internal static void RefreshTintableFlags() { if ((Object)(object)MetaManager.instance == (Object)null) { return; } bool value = Plugin.EnableBridgeTinting.Value; _lastAppliedTinting = value; foreach (CosmeticAsset cosmeticAsset in MetaManager.instance.cosmeticAssets) { if (!((Object)(object)cosmeticAsset == (Object)null) && BridgeIds.IsBridgeAsset(cosmeticAsset) && (!CustomizerStore.TryGet(cosmeticAsset.assetId, out CosmeticOverrideData data) || !data.Tintable.HasValue) && _originalTintable.TryGetValue(cosmeticAsset.assetId, out var value2)) { cosmeticAsset.tintable = value && value2; } } } internal static void RefreshDefaultRarity() { //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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MetaManager.instance == (Object)null) { return; } Rarity rarity = (_lastAppliedRarity = Plugin.BridgeDefaultRarity.Value); foreach (CosmeticAsset cosmeticAsset in MetaManager.instance.cosmeticAssets) { if (!((Object)(object)cosmeticAsset == (Object)null) && BridgeIds.IsBridgeAsset(cosmeticAsset) && (!CustomizerStore.TryGet(cosmeticAsset.assetId, out CosmeticOverrideData data) || !data.Rarity.HasValue)) { cosmeticAsset.rarity = rarity; } } } internal static bool TryGetDefaultTintable(CosmeticAsset asset, out bool tintable) { tintable = false; if ((Object)(object)asset == (Object)null || !BridgeIds.IsBridgeAsset(asset)) { return false; } if (!_originalTintable.TryGetValue(asset.assetId, out var value)) { return false; } tintable = Plugin.EnableBridgeTinting.Value && value; return true; } internal static void OnMenuOpen(MenuPageCosmetics page) { //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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)MetaManager.instance == (Object)null)) { Rarity value = Plugin.BridgeDefaultRarity.Value; if (value != _lastAppliedRarity) { RefreshDefaultRarity(); } bool value2 = Plugin.EnableBridgeTinting.Value; if (_lastAppliedTinting != value2) { RefreshTintableFlags(); } if (!_moreHeadFixDone && (Plugin.RemoveBridgePhysics.Value || Plugin.LoopBridgeAnimation.Value)) { _moreHeadFixDone = true; ((MonoBehaviour)page).StartCoroutine(CosmeticPrefabFixer.TryFixMoreHeadPrefabsAsync()); } } } internal static void ReapplyDefaults(CosmeticAsset asset) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) asset.rarity = Plugin.BridgeDefaultRarity.Value; if (_originalTypes.TryGetValue(asset.assetId, out var value)) { (CosmeticType cosmeticType, bool isWorld) tuple = CustomizerStore.MapOverrideToVanilla(value); CosmeticType item = tuple.cosmeticType; bool item2 = tuple.isWorld; asset.type = item; if (item2) { WorldAssetIds.Add(asset.assetId); } else { WorldAssetIds.Remove(asset.assetId); } if (_originalTintable.TryGetValue(asset.assetId, out var value2)) { asset.tintable = Plugin.EnableBridgeTinting.Value && value2; } } } static HhhCosmeticLoader() { //IL_013f: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(); foreach (string key in TagMap.Keys) { hashSet.Add(key); } ValidTags = hashSet; _usedPrefabIds = new HashSet(); _usedInternalNames = new HashSet(); _lastAppliedRarity = (Rarity)(-1); _lastAppliedTinting = null; _originalTypes = new Dictionary(); _originalTintable = new Dictionary(); } } internal static class BatchIconGenerator { private static bool _isRunning; private static bool _didStartOnce; private static int _progressDone; private static int _progressFailed; private static int _progressTotal; private static RawImage? _avatarRawImage; internal static Action? OnBatchCompleted; private static FieldInfo? _menuPageStateField; private static FieldInfo? _iconCreationAvatarField; private static readonly string[] FaceMeshNames = new string[5] { "mesh_eye_l", "mesh_eye_r", "mesh_pupil_l", "mesh_pupil_r", "mesh_head_top" }; private static FieldInfo? _equipLerpField; internal static bool IsGenerating => _isRunning; internal static string ProgressText { get; private set; } = ""; internal static int ProgressDone => _progressDone; internal static int ProgressFailed => _progressFailed; internal static int ProgressTotal => _progressTotal; internal static void TryStart(MonoBehaviour host) { if (!_isRunning && Plugin.GenerateAllIcons.Value) { if (_didStartOnce) { BceConsole.LogWarning("GenerateAllIcons: previous batch was interrupted. Resuming — only icons still missing will be generated"); } _isRunning = true; MenuPage component = ((Component)host).GetComponent(); host.StartCoroutine(Run(component)); } } internal static void NotifyMenuClosed() { if (_isRunning) { _isRunning = false; if (Plugin.MenuLibAvailable) { PopupDestroy(); } if ((Object)(object)_avatarRawImage != (Object)null) { ((Behaviour)_avatarRawImage).enabled = true; _avatarRawImage = null; } if ((Object)(object)MetaManager.instance != (Object)null) { MetaManager.instance.CosmeticPreviewSet(false); MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); } WorldCosmeticsSetupPatch.SetAllWorldInstancesActive(active: true); ProgressText = ""; int num = _progressTotal - _progressDone - _progressFailed; BceConsole.LogWarning("GenerateAllIcons: batch interrupted at " + $"{_progressDone + _progressFailed}/{_progressTotal} " + $"({num} still to go). " + "Reopen the menu to continue. (Your equipped cosmetics were not modified.)"); } } private static IEnumerator Run(MenuPage? cosmeticsMenuPage) { _didStartOnce = true; if ((object)_menuPageStateField == null) { _menuPageStateField = AccessTools.Field(typeof(MenuPage), "currentPageState"); } if ((Object)(object)cosmeticsMenuPage != (Object)null && _menuPageStateField != null) { float elapsed = 0f; while (elapsed < 3f) { PageState val = (PageState)(_menuPageStateField.GetValue(cosmeticsMenuPage) ?? ((object)(PageState)1)); if ((int)val == 1) { break; } elapsed += Time.unscaledDeltaTime; yield return null; } } else { yield return (object)new WaitForSecondsRealtime(0.5f); } if ((Object)(object)MetaManager.instance == (Object)null) { _isRunning = false; yield break; } List work = new List(); foreach (CosmeticAsset cosmeticAsset in MetaManager.instance.cosmeticAssets) { if (!((Object)(object)cosmeticAsset == (Object)null) && cosmeticAsset.assetId != null && BridgeIds.IsBridgeAsset(cosmeticAsset) && !(cosmeticAsset.assetId == MiniSemibotCosmetic.AssetId) && !IconCapture.HasCache(cosmeticAsset)) { work.Add(cosmeticAsset); } } BceConsole.LogInfo($"GenerateAllIcons: {work.Count} icon(s) to generate.", ConsoleColor.DarkGreen); if (work.Count == 0) { _isRunning = false; Plugin.GenerateAllIcons.Value = false; ((BaseUnityPlugin)Plugin.Instance).Config.Save(); yield break; } _progressDone = 0; _progressFailed = 0; _progressTotal = work.Count; _avatarRawImage = FindAvatarRawImage(); if ((Object)(object)_avatarRawImage != (Object)null && Plugin.HideAvatarWhileGenerating.Value) { ((Behaviour)_avatarRawImage).enabled = false; } if (Plugin.MenuLibAvailable) { PopupOpen(); } bool interrupted = true; try { foreach (CosmeticAsset asset in work) { if (!_isRunning || (Object)(object)MetaManager.instance == (Object)null) { break; } int num = MetaManager.instance.cosmeticAssets.IndexOf(asset); if (num < 0) { _progressFailed++; continue; } MetaManager.instance.cosmeticEquippedPreview.Clear(); if (!Plugin.HideClothesWhileGenerating.Value && MetaManager.instance.cosmeticEquipped != null) { foreach (int item in MetaManager.instance.cosmeticEquipped) { MetaManager.instance.cosmeticEquippedPreview.Add(item); } } if (!MetaManager.instance.cosmeticEquippedPreview.Contains(num)) { MetaManager.instance.cosmeticEquippedPreview.Add(num); } if (MetaManager.instance.colorsEquipped != null) { MetaManager.instance.colorsEquippedPreview = (Plugin.ResetBodyColorWhileGenerating.Value ? new int[MetaManager.instance.colorsEquipped.Length] : ((int[])MetaManager.instance.colorsEquipped.Clone())); } MetaManager.instance.CosmeticPreviewSet(true); MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); WorldCosmeticsSetupPatch.SetAllWorldInstancesActive(active: false); if (HhhCosmeticLoader.IsWorldAsset(asset)) { WorldCosmeticsSetupPatch.SetWorldAssetActive(asset, active: true); } Cosmetic[] snapshot = Object.FindObjectsOfType(); SkipEquipAnimationFor(asset, snapshot); yield return null; for (int guard = 0; guard < 3; guard++) { if (IsAnimComplete(asset)) { break; } snapshot = Object.FindObjectsOfType(); if (IsAnimComplete(asset, snapshot)) { break; } yield return null; } PlayerAvatarVisuals iconVisuals = Object.FindObjectOfType()?.playerAvatarMenu?.playerVisuals ?? PlayerAvatarMenu.instance?.playerVisuals; PartShrinkerBridge.ResyncFromMountedCosmetics(iconVisuals); PartShrinkerBridge.SetAllHiddenPartsEnabled(enabled: false); MirrorFaceMeshesToAllAvatars(iconVisuals); ResetCustomConditionsForCapture(); yield return null; MirrorFaceMeshesToAllAvatars(iconVisuals); SnapHideConditions(); yield return (object)new WaitForEndOfFrame(); MirrorFaceMeshesToAllAvatars(iconVisuals); SnapHideConditions(); yield return (object)new WaitForEndOfFrame(); if ((Object)(object)MetaManager.instance == (Object)null) { PartShrinkerBridge.SetAllHiddenPartsEnabled(enabled: true); break; } bool flag = IconCapture.TryCapture(asset); PartShrinkerBridge.SetAllHiddenPartsEnabled(enabled: true); if (flag) { _progressDone++; } else { _progressFailed++; } int num2 = _progressDone + _progressFailed; int num3 = ((_progressTotal > 0) ? (num2 * 100 / _progressTotal) : 0); ProgressText = ((_progressFailed > 0) ? $"Generating icons: {num2}/{_progressTotal} ({num3}%) | {_progressFailed} failed" : $"Generating icons: {num2}/{_progressTotal} ({num3}%)"); if (Plugin.MenuLibAvailable) { PopupUpdate(); } MetaManager.instance.CosmeticPreviewSet(false); MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); WorldCosmeticsSetupPatch.SetAllWorldInstancesActive(active: true); int num4 = _progressDone + _progressFailed; if (num4 % 50 == 0) { BceConsole.LogInfo($"Batch progress: {num4}/{work.Count} " + $"({_progressDone} ok, {_progressFailed} failed)", ConsoleColor.DarkGreen); } } if (_isRunning) { interrupted = false; } } finally { if (Plugin.MenuLibAvailable) { PopupClose(); } if (_isRunning) { _isRunning = false; if (interrupted) { int num5 = _progressTotal - _progressDone - _progressFailed; BceConsole.LogWarning("GenerateAllIcons: batch interrupted at " + $"{_progressDone + _progressFailed}/{_progressTotal} " + $"({num5} still to go). " + "Reopen the menu to continue"); } } if ((Object)(object)MetaManager.instance != (Object)null) { MetaManager.instance.CosmeticPreviewSet(false); MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); } WorldCosmeticsSetupPatch.SetAllWorldInstancesActive(active: true); if ((Object)(object)_avatarRawImage != (Object)null) { ((Behaviour)_avatarRawImage).enabled = true; _avatarRawImage = null; } ProgressText = ""; } if (!interrupted) { Plugin.GenerateAllIcons.Value = false; ((BaseUnityPlugin)Plugin.Instance).Config.Save(); _didStartOnce = false; BceConsole.LogInfo($"GenerateAllIcons done — {_progressDone} captured, " + $"{_progressFailed} failed.", ConsoleColor.DarkGreen); Action onBatchCompleted = OnBatchCompleted; OnBatchCompleted = null; onBatchCompleted?.Invoke(); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void PopupOpen() { BatchIconPopup.Open(); } [MethodImpl(MethodImplOptions.NoInlining)] private static void PopupUpdate() { BatchIconPopup.UpdateProgress(); } [MethodImpl(MethodImplOptions.NoInlining)] private static void PopupClose() { BatchIconPopup.Close(); } [MethodImpl(MethodImplOptions.NoInlining)] private static void PopupDestroy() { BatchIconPopup.Destroy(); } internal static bool OnPopupEscape() { if ((Object)(object)_avatarRawImage != (Object)null) { ((Behaviour)_avatarRawImage).enabled = true; _avatarRawImage = null; } _isRunning = false; int num = _progressTotal - _progressDone - _progressFailed; BceConsole.LogWarning("GenerateAllIcons: batch interrupted at " + $"{_progressDone + _progressFailed}/{_progressTotal} " + $"({num} still to go). " + "Reopen the menu to continue. (Your equipped cosmetics were not modified.)"); return true; } private static RawImage? FindAvatarRawImage() { PlayerAvatarMenuHover val = Object.FindObjectOfType(); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent(); } private static void SkipEquipAnimationFor(CosmeticAsset asset, Cosmetic[]? snapshot = null) { if ((object)_iconCreationAvatarField == null) { _iconCreationAvatarField = AccessTools.Field(typeof(Cosmetic), "iconCreationAvatar"); } if (_iconCreationAvatarField == null) { return; } Cosmetic[] array = snapshot ?? Object.FindObjectsOfType(); Cosmetic[] array2 = array; foreach (Cosmetic val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)val.cosmeticAsset == (Object)(object)asset) { _iconCreationAvatarField.SetValue(val, true); } } } private static void ResetCustomConditionsForCapture() { PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { try { val.conditionsCustom.Clear(); val.ConditionUpdateAll(); } catch (Exception ex) { BridgeLog.Debug("BatchIconGenerator: condition reset failed — " + ex.Message); } } } private static void SnapHideConditions() { CosmeticHideCondition[] array = Object.FindObjectsOfType(true); foreach (CosmeticHideCondition val in array) { try { val.AnimateInstant(); } catch { } } } private static void MirrorFaceMeshesToAllAvatars(PlayerAvatarVisuals? reference) { if ((Object)(object)reference == (Object)null) { return; } Dictionary dictionary = new Dictionary(); MeshRenderer[] componentsInChildren = ((Component)reference).GetComponentsInChildren(true); foreach (MeshRenderer val in componentsInChildren) { string name = ((Object)((Component)val).gameObject).name; if (Array.IndexOf(FaceMeshNames, name) >= 0 && !dictionary.ContainsKey(name)) { dictionary[name] = ((Renderer)val).enabled; } } if (dictionary.Count == 0) { return; } PlayerAvatarVisuals[] array = Object.FindObjectsOfType(true); foreach (PlayerAvatarVisuals val2 in array) { MeshRenderer[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren(true); foreach (MeshRenderer val3 in componentsInChildren2) { if (dictionary.TryGetValue(((Object)((Component)val3).gameObject).name, out var value) && ((Renderer)val3).enabled != value) { ((Renderer)val3).enabled = value; } } } } private static bool IsAnimComplete(CosmeticAsset asset, Cosmetic[]? snapshot = null) { if ((object)_equipLerpField == null) { _equipLerpField = AccessTools.Field(typeof(Cosmetic), "equipLerp"); } if (_equipLerpField == null) { return true; } Cosmetic[] array = snapshot ?? Object.FindObjectsOfType(); Cosmetic[] array2 = array; foreach (Cosmetic val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)val.cosmeticAsset == (Object)(object)asset && (float)(_equipLerpField.GetValue(val) ?? ((object)1f)) < 1f) { return false; } } return true; } } internal static class BatchIconPopup { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ShouldCloseMenuDelegate <>9__12_1; internal bool b__12_1() { Clear(); return BatchIconGenerator.OnPopupEscape(); } } private static REPOPopupPage? _page; private static TextMeshProUGUI? _progressLabel; private static TextMeshProUGUI? _hintLabel; private const float GeneratingLabelH = 140f; private const float NumbersLabelH = 40f; private static string[] _tips = Array.Empty(); private static int _currentTipIndex; internal static void Open() { _page = Create(); _page.OpenPage(false); UpdateProgress(); } internal static void Close() { if (!((Object)(object)_page == (Object)null)) { _page.ClosePage(false); Clear(); } } internal static void Destroy() { if (!((Object)(object)_page == (Object)null)) { Object.Destroy((Object)(object)((Component)_page).gameObject); Clear(); } } private static void Clear() { _page = null; _progressLabel = null; _hintLabel = null; } internal static void UpdateProgress() { if (!((Object)(object)_progressLabel == (Object)null)) { int num = BatchIconGenerator.ProgressDone + BatchIconGenerator.ProgressFailed; int progressTotal = BatchIconGenerator.ProgressTotal; int num2 = ((progressTotal > 0) ? (num * 100 / progressTotal) : 0); string text = $"{num} / {progressTotal} ({num2}%)"; if (BatchIconGenerator.ProgressFailed > 0) { text += $"\n{BatchIconGenerator.ProgressFailed} failed"; } ((TMP_Text)_progressLabel).text = text; } } private static REPOPopupPage Create() { //IL_001c: 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) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown REPOPopupPage val = MenuAPI.CreateREPOPopupPage("Generating Icons", false, true, 0f, (Vector2?)new Vector2(-120f, 0f)); PopupScrollGuard popupScrollGuard = ((Component)val).gameObject.AddComponent(); popupScrollGuard.Init(((Component)val).transform); _tips = BuildTipList(); _currentTipIndex = 0; TextMeshProUGUI capturedLabel = null; TextMeshProUGUI capturedHint = null; REPOLabel capturedParent = null; float maskW = val.maskRectTransform.sizeDelta.x; val.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) capturedParent = MenuAPI.CreateREPOLabel("Starting...", sv, default(Vector2)); capturedLabel = capturedParent.labelTMP; if ((Object)(object)capturedLabel != (Object)null) { ((TMP_Text)capturedLabel).fontSize = 16f; ((TMP_Text)capturedLabel).alignment = (TextAlignmentOptions)514; ((TMP_Text)capturedLabel).enableWordWrapping = true; float num = ((maskW > 0f) ? maskW : 200f) - 10f; ((Component)capturedParent).GetComponent().sizeDelta = new Vector2(num, 140f); GameObject val3 = Object.Instantiate(((Component)capturedLabel).gameObject, ((TMP_Text)capturedLabel).transform.parent); ((Object)val3).name = "HintLabel"; capturedHint = val3.GetComponent(); ((TMP_Text)capturedLabel).rectTransform.sizeDelta = new Vector2(num, 40f); ((Transform)((TMP_Text)capturedLabel).rectTransform).localPosition = new Vector3(0f, 100f); ((TMP_Text)capturedHint).rectTransform.sizeDelta = new Vector2(num, 100f); ((Transform)((TMP_Text)capturedHint).rectTransform).localPosition = Vector3.zero; } return ((Component)capturedParent).GetComponent(); }, 0f, 0f); if ((Object)(object)capturedParent != (Object)null) { REPOScrollViewElement component = ((Component)capturedParent).GetComponent(); if ((Object)(object)component != (Object)null) { ((MonoBehaviour)val).StartCoroutine(CenterScrollElement(val, component)); } } _progressLabel = capturedLabel; _hintLabel = capturedHint; UpdateHintLabel(); if (_tips.Length > 1) { ((MonoBehaviour)val).StartCoroutine(CycleTips()); } object obj = <>c.<>9__12_1; if (obj == null) { ShouldCloseMenuDelegate val2 = delegate { Clear(); return BatchIconGenerator.OnPopupEscape(); }; <>c.<>9__12_1 = val2; obj = (object)val2; } val.onEscapePressed = (ShouldCloseMenuDelegate)obj; return val; } private static void UpdateHintLabel() { if (!((Object)(object)_hintLabel == (Object)null)) { string text = "Press ESC to stop early"; if (_tips.Length != 0) { text = text + "\n\n" + _tips[_currentTipIndex]; } ((TMP_Text)_hintLabel).text = text; } } private static IEnumerator CycleTips() { while (BatchIconGenerator.IsGenerating && (Object)(object)_progressLabel != (Object)null) { yield return (object)new WaitForSecondsRealtime(10f); if (!BatchIconGenerator.IsGenerating || (Object)(object)_progressLabel == (Object)null) { break; } _currentTipIndex = (_currentTipIndex + 1) % _tips.Length; UpdateHintLabel(); } } private static string[] BuildTipList() { List list = new List { "Tip: close the menu anytime to pause — reopen it to resume where you left off" }; if (Plugin.AutoCaptureIcons.Value) { list.Add("Tip: hovering a cosmetic with no icon captures it automatically"); } return list.ToArray(); } private static IEnumerator CenterScrollElement(REPOPopupPage popup, REPOScrollViewElement element) { yield return null; if ((Object)(object)_progressLabel != (Object)null) { ((Transform)((TMP_Text)_progressLabel).rectTransform).localPosition = new Vector3(0f, 100f); } float y = popup.maskRectTransform.sizeDelta.y; Rect rect = element.rectTransform.rect; float height = ((Rect)(ref rect)).height; if (height > 0f) { element.topPadding = Mathf.Max(0f, (y - height) / 2f); } } } internal static class IconCacheCleaner { internal static void Run() { if (!Plugin.DeleteIconCache.Value) { return; } try { string cacheDir = IconCapture.CacheDir; if (!Directory.Exists(cacheDir)) { BceConsole.LogInfo("DeleteIconCache: no cache directory, nothing to do"); ResetFlag(); return; } string text = Plugin.DeleteIconsMatching.Value ?? ""; string[] array = (from s in text.Split(',') select s.Trim().ToLowerInvariant() into s where s.Length > 0 select s).ToArray(); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (string registeredAssetId in HhhCosmeticLoader.RegisteredAssetIds) { int num = registeredAssetId.IndexOf(':'); if (num >= 0 && num + 1 < registeredAssetId.Length) { string text2 = registeredAssetId; int num2 = num + 1; hashSet.Add(text2.Substring(num2, text2.Length - num2)); } } int num3 = 0; int num4 = 0; string text3 = "MHB_MiniMe".ToLowerInvariant(); string[] files = Directory.GetFiles(cacheDir, "*.png"); foreach (string text4 in files) { string name = Path.GetFileNameWithoutExtension(text4).ToLowerInvariant(); if (name == text3) { num4++; continue; } if (!hashSet.Contains(name)) { num4++; continue; } if (array.Length != 0 && !array.Any((string f) => name.Contains(f))) { num4++; continue; } try { File.Delete(text4); num3++; } catch (Exception ex) { BceConsole.LogWarning("Failed to delete '" + text4 + "': " + ex.Message); } } BceConsole.LogInfo($"DeleteIconCache: removed {num3} bridge icon(s), kept {num4}. " + "Filter: " + ((array.Length == 0) ? "(all bridge icons)" : string.Join(",", array))); if (num3 > 0) { IconCapture.InvalidateAll(); } } catch (Exception ex2) { BceConsole.LogError("DeleteIconCache failed: " + ex2.Message); } finally { ResetFlag(); } } private static void ResetFlag() { Plugin.DeleteIconCache.Value = false; ((BaseUnityPlugin)Plugin.Instance).Config.Save(); } } internal static class IconCapture { private const int OutSize = 128; private static string? _cacheDir; private static HashSet? _knownCached; private static FieldInfo? _renderTextureInstanceField; private static readonly Rect CropHead = new Rect(0.22f, 0.62f, 0.56f, 0.35f); private static readonly Rect CropNeck = new Rect(0.22f, 0.5f, 0.56f, 0.38f); private static readonly Rect CropBody = new Rect(0.18f, 0.34f, 0.64f, 0.36f); private static readonly Rect CropArmR = new Rect(0.05f, 0.3f, 0.5f, 0.4f); private static readonly Rect CropArmL = new Rect(0.45f, 0.3f, 0.5f, 0.4f); private static readonly Rect CropLegR = new Rect(0.1f, 0f, 0.45f, 0.45f); private static readonly Rect CropLegL = new Rect(0.45f, 0f, 0.45f, 0.45f); private static readonly Rect CropFull = new Rect(0f, 0f, 1f, 1f); internal static string CacheDir { get { if (_cacheDir != null) { return _cacheDir; } _cacheDir = Path.Combine(Application.persistentDataPath, "Cache", "Icons", "CosmeticsModded", "MoreHeadBridge_CosmeticsIcons"); MigrateLegacyCache(_cacheDir); return _cacheDir; } } private static void MigrateLegacyCache(string newDir) { string path = Path.Combine(Application.persistentDataPath, "MoreHeadBridge_Icons"); if (!Directory.Exists(path)) { return; } BceConsole.LogInfo("IconCapture: migrating icon cache from legacy location..."); try { Directory.CreateDirectory(newDir); int num = 0; int num2 = 0; string[] files = Directory.GetFiles(path, "*.png"); foreach (string text in files) { string text2 = Path.Combine(newDir, Path.GetFileName(text)); try { if (!File.Exists(text2)) { File.Move(text, text2); } else { File.Delete(text); } num++; } catch (Exception ex) { num2++; BceConsole.LogWarning("IconCapture: could not migrate '" + Path.GetFileName(text) + "': " + ex.Message); } } try { if (Directory.GetFiles(path).Length == 0) { Directory.Delete(path, recursive: false); } } catch { } BceConsole.LogInfo($"IconCapture: cache migration done — {num} moved, {num2} failed"); } catch (Exception ex2) { BceConsole.LogWarning("IconCapture: cache migration failed: " + ex2.Message); } } internal static string CachePathFor(CosmeticAsset asset) { string name = ((Object)asset).name.Replace("(Clone)", "").Trim().ToLowerInvariant(); return Path.Combine(CacheDir, MakeSafeFileName(name) + ".png"); } private static string MakeSafeFileName(string name) { name = name.Replace('/', '_').Replace('\\', '_').Replace("..", "__"); if (name.Length != 0) { return name; } return "_unnamed"; } private static void EnsureCacheSeeded() { if (_knownCached != null) { return; } _knownCached = new HashSet(StringComparer.OrdinalIgnoreCase); try { if (Directory.Exists(CacheDir)) { string[] files = Directory.GetFiles(CacheDir, "*.png"); foreach (string item in files) { _knownCached.Add(item); } } } catch { } } internal static void MarkCached(string path) { EnsureCacheSeeded(); _knownCached.Add(path); } internal static bool HasCache(CosmeticAsset asset) { EnsureCacheSeeded(); return _knownCached.Contains(CachePathFor(asset)); } internal static void MarkCached(CosmeticAsset asset) { EnsureCacheSeeded(); _knownCached.Add(CachePathFor(asset)); } internal static void DeleteCache(CosmeticAsset asset) { EnsureCacheSeeded(); string text = CachePathFor(asset); _knownCached.Remove(text); try { if (File.Exists(text)) { File.Delete(text); } } catch (Exception ex) { BceConsole.LogWarning("IconCapture: could not delete '" + Path.GetFileName(text) + "': " + ex.Message); } if ((Object)(object)asset.icon != (Object)null) { Object.Destroy((Object)(object)asset.icon); asset.icon = null; } CosmeticHoverPatch.Invalidate(asset); CosmeticsMenuStartPatch.RefreshToolsButtons?.Invoke(); BridgeLog.Trace("IconCapture: deleted cached icon for '" + ((Object)asset).name + "'"); } private static RenderTexture? FindActiveAvatarRT() { PlayerAvatarMenuHover val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { return null; } if ((object)_renderTextureInstanceField == null) { _renderTextureInstanceField = AccessTools.Field(typeof(PlayerAvatarMenuHover), "renderTextureInstance"); } if (_renderTextureInstanceField == null) { BceConsole.LogWarning("IconCapture: PlayerAvatarMenuHover.renderTextureInstance not found — update MoreHeadBridge"); } else { object? value = _renderTextureInstanceField.GetValue(val); RenderTexture val2 = (RenderTexture)((value is RenderTexture) ? value : null); if ((Object)(object)val2 != (Object)null) { return val2; } } RawImage component = ((Component)val).GetComponent(); if (!((Object)(object)component != (Object)null)) { return null; } Texture texture = component.texture; return (RenderTexture?)(object)((texture is RenderTexture) ? texture : null); } internal static bool TryCapture(CosmeticAsset asset) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return TryCapture(asset, (CosmeticType)(HhhCosmeticLoader.IsWorldAsset(asset) ? (-1) : ((asset != null) ? ((int)asset.type) : 0))); } internal static bool TryCapture(CosmeticAsset asset, CosmeticType type) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown if ((Object)(object)asset == (Object)null) { return false; } if (HasCache(asset)) { return false; } if (BridgeIds.IsBridgeAsset(asset) && asset.assetId != MiniSemibotCosmetic.AssetId && CustomizerStore.GetEffectiveIsolatedIcon(asset.assetId)) { return TryCaptureIsolated(asset); } Texture2D val = null; Texture2D val2 = null; Texture2D val3 = null; RenderTexture active = RenderTexture.active; try { RenderTexture val4 = FindActiveAvatarRT(); if ((Object)(object)val4 == (Object)null) { return false; } Directory.CreateDirectory(CacheDir); RenderTexture.active = val4; val = new Texture2D(((Texture)val4).width, ((Texture)val4).height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), 0, 0); val.Apply(); Rect cropRect = GetCropRect(type); int num = Mathf.RoundToInt(((Rect)(ref cropRect)).x * (float)((Texture)val4).width); int num2 = Mathf.RoundToInt(((Rect)(ref cropRect)).y * (float)((Texture)val4).height); int num3 = Mathf.RoundToInt(((Rect)(ref cropRect)).width * (float)((Texture)val4).width); int num4 = Mathf.RoundToInt(((Rect)(ref cropRect)).height * (float)((Texture)val4).height); num3 = Mathf.Max(1, Mathf.Min(num3, ((Texture)val4).width - num)); num4 = Mathf.Max(1, Mathf.Min(num4, ((Texture)val4).height - num2)); Color[] pixels = val.GetPixels(num, num2, num3, num4); val2 = new Texture2D(num3, num4, (TextureFormat)4, false); val2.SetPixels(pixels); val2.Apply(); val3 = ResizeBilinear(val2, 128, 128); string path = CachePathFor(asset); File.WriteAllBytes(path, ImageConversion.EncodeToPNG(val3)); MarkCached(path); if ((Object)(object)asset.icon != (Object)null) { Object.Destroy((Object)(object)asset.icon); asset.icon = null; } RefreshVisibleButtons(asset); CosmeticsMenuStartPatch.RefreshToolsButtons?.Invoke(); return true; } catch (Exception ex) { BridgeLog.Trace("Icon capture failed for '" + ((Object)asset).name + "': " + ex.Message); return false; } finally { RenderTexture.active = active; if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } if ((Object)(object)val3 != (Object)null) { Object.Destroy((Object)(object)val3); } } } private static bool TryCaptureIsolated(CosmeticAsset asset) { Texture2D val = null; Texture2D val2 = null; try { val = IsolatedIconRenderer.Render(asset); if ((Object)(object)val == (Object)null) { return false; } Directory.CreateDirectory(CacheDir); val2 = ResizeBilinear(val, 128, 128); string path = CachePathFor(asset); File.WriteAllBytes(path, ImageConversion.EncodeToPNG(val2)); MarkCached(path); if ((Object)(object)asset.icon != (Object)null) { Object.Destroy((Object)(object)asset.icon); asset.icon = null; } RefreshVisibleButtons(asset); CosmeticsMenuStartPatch.RefreshToolsButtons?.Invoke(); return true; } catch (Exception ex) { BridgeLog.Trace("Isolated icon render failed for '" + ((Object)asset).name + "': " + ex.Message); return false; } finally { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } } } private static Rect GetCropRect(CosmeticType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected I4, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) switch ((int)type) { case 0: case 5: case 14: case 15: case 17: case 18: case 24: case 31: case 32: return CropHead; case 6: case 25: case 30: return CropNeck; case 7: case 8: case 16: case 20: case 21: case 23: return CropBody; case 1: case 9: case 13: case 26: return CropArmR; case 2: case 10: case 27: return CropArmL; case 3: case 11: case 19: case 28: return CropLegR; case 4: case 12: case 22: case 29: return CropLegL; default: return CropFull; } } internal static void InvalidateAll() { _knownCached = null; MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } foreach (string id in HhhCosmeticLoader.RegisteredAssetIds) { CosmeticAsset val = instance.cosmeticAssets.Find((CosmeticAsset a) => (Object)(object)a != (Object)null && a.assetId == id); if (!((Object)(object)val == (Object)null)) { if ((Object)(object)val.icon != (Object)null) { Object.Destroy((Object)(object)val.icon); val.icon = null; } CosmeticHoverPatch.Invalidate(val); } } MenuPageCosmetics val2 = Object.FindObjectOfType(); if ((Object)(object)val2 == (Object)null) { return; } MenuElementCosmeticButton[] componentsInChildren = ((Component)val2).GetComponentsInChildren(true); foreach (MenuElementCosmeticButton val3 in componentsInChildren) { if ((Object)(object)val3?.cosmeticAsset != (Object)null && BridgeIds.IsBridgeAsset(val3.cosmeticAsset)) { val3.UpdateIcon(false); } } } internal static Sprite? SaveSquareContent(Texture2D? src, string cachePath, float marginFrac = 0.1f) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown if ((Object)(object)src == (Object)null) { return null; } Texture2D val = null; Texture2D val2 = null; try { Color32[] pixels = src.GetPixels32(); int width = ((Texture)src).width; int height = ((Texture)src).height; int num = width; int num2 = height; int num3 = -1; int num4 = -1; for (int i = 0; i < height; i++) { int num5 = i * width; for (int j = 0; j < width; j++) { if (pixels[num5 + j].a > 10) { if (j < num) { num = j; } if (j > num3) { num3 = j; } if (i < num2) { num2 = i; } if (i > num4) { num4 = i; } } } } if (num3 < 0) { num = 0; num2 = 0; num3 = width - 1; num4 = height - 1; } int num6 = num3 - num + 1; int num7 = num4 - num2 + 1; int num8 = Mathf.CeilToInt((float)Mathf.Max(num6, num7) * (1f + 2f * marginFrac)); Color32[] array = (Color32[])(object)new Color32[num8 * num8]; int num9 = (num8 - num6) / 2; int num10 = (num8 - num7) / 2; for (int k = 0; k < num7; k++) { Array.Copy(pixels, (num2 + k) * width + num, array, (num10 + k) * num8 + num9, num6); } val = new Texture2D(num8, num8, (TextureFormat)4, false); val.SetPixels32(array); val.Apply(); val2 = ResizeBilinear(val, 128, 128); Directory.CreateDirectory(CacheDir); File.WriteAllBytes(cachePath, ImageConversion.EncodeToPNG(val2)); MarkCached(cachePath); return SemiFunc.LoadSpriteFromFile(cachePath); } catch (Exception ex) { BridgeLog.Trace("SaveSquareContent failed: " + ex.Message); return null; } finally { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } } } internal static void RefreshVisibleButtons(CosmeticAsset asset) { try { MenuPageCosmetics val = Object.FindObjectOfType(); MenuElementCosmeticButton[] array = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentsInChildren(true) : Object.FindObjectsOfType()); MenuElementCosmeticButton[] array2 = array; foreach (MenuElementCosmeticButton val2 in array2) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2.cosmeticAsset == (Object)(object)asset) { val2.UpdateIcon(false); } } } catch (Exception ex) { BridgeLog.Trace("Button refresh failed: " + ex.Message); } } private static Texture2D ResizeBilinear(Texture2D src, int w, int h) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) RenderTexture temporary = RenderTexture.GetTemporary(w, h); try { Graphics.Blit((Texture)(object)src, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(w, h, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)w, (float)h), 0, 0); val.Apply(); RenderTexture.active = active; return val; } finally { RenderTexture.ReleaseTemporary(temporary); } } } internal static class IsolatedIconRenderer { private const int RenderSize = 256; private const float Fov = 26f; private static readonly Vector3 StageOrigin = new Vector3(0f, 100000f, 0f); internal static Texture2D? Render(CosmeticAsset asset) { //IL_0036: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Expected O, but got Unknown //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) GameObject val = ((PrefabRef)(object)asset?.prefab)?.Prefab; if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = null; RenderTexture val3 = null; List list = new List(); RenderTexture active = RenderTexture.active; try { val2 = Object.Instantiate(val, StageOrigin, Quaternion.identity); ((Object)val2).name = "BridgeIconRender"; Behaviour[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (Behaviour val4 in componentsInChildren) { if (!(val4 is Camera)) { val4.enabled = false; } } if (!TryGetBounds(val2, out var bounds)) { return null; } Vector3 val5 = ((Bounds)(ref bounds)).extents; float num = Mathf.Max(0.0001f, ((Vector3)(ref val5)).magnitude); float num2 = num / Mathf.Sin(0.2268928f) * 1.2f; val5 = new Vector3(0.35f, 0.25f, 1f); Vector3 normalized = ((Vector3)(ref val5)).normalized; Vector3 val6 = ((Bounds)(ref bounds)).center + normalized * num2; GameObject val7 = new GameObject("BridgeIconCam"); list.Add(val7); val7.transform.position = val6; val7.transform.LookAt(((Bounds)(ref bounds)).center, Vector3.up); Camera val8 = val7.AddComponent(); val8.clearFlags = (CameraClearFlags)2; val8.backgroundColor = new Color(0f, 0f, 0f, 0f); val8.fieldOfView = 26f; val8.nearClipPlane = Mathf.Max(0.01f, num2 - num * 2f); val8.farClipPlane = num2 + num * 4f; val8.cullingMask = -1; val8.allowHDR = false; val8.allowMSAA = true; ((Behaviour)val8).enabled = false; AddDirLight(list, val6, ((Bounds)(ref bounds)).center, Quaternion.Euler(35f, -25f, 0f), 1.2f); AddDirLight(list, val6, ((Bounds)(ref bounds)).center, Quaternion.Euler(15f, 160f, 0f), 0.55f); val3 = (val8.targetTexture = new RenderTexture(256, 256, 16, (RenderTextureFormat)0) { antiAliasing = 2 }); val8.Render(); val8.targetTexture = null; RenderTexture.active = val3; Texture2D val10 = new Texture2D(256, 256, (TextureFormat)4, false); val10.ReadPixels(new Rect(0f, 0f, 256f, 256f), 0, 0); val10.Apply(); return val10; } catch (Exception ex) { BridgeLog.Trace("IsolatedIconRenderer: render failed for '" + ((asset != null) ? ((Object)asset).name : null) + "': " + ex.Message); return null; } finally { RenderTexture.active = active; if ((Object)(object)val3 != (Object)null) { val3.Release(); Object.Destroy((Object)(object)val3); } if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } foreach (GameObject item in list) { if ((Object)(object)item != (Object)null) { Object.Destroy((Object)(object)item); } } } } private static void AddDirLight(List temps, Vector3 near, Vector3 lookAt, Quaternion rotation, float intensity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0018: 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_0041: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BridgeIconLight"); temps.Add(val); val.transform.position = near; val.transform.rotation = rotation; Light val2 = val.AddComponent(); val2.type = (LightType)1; val2.intensity = intensity; val2.color = Color.white; val2.shadows = (LightShadows)0; } private static bool TryGetBounds(GameObject root, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0034: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; Renderer[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(val is ParticleSystemRenderer)) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } return flag; } } [HarmonyPatch(typeof(MenuPageCosmetics), "Start")] internal static class BatchIconGeneratorStartPatch { [HarmonyPostfix] private static void Postfix(MenuPageCosmetics __instance) { BatchIconGenerator.TryStart((MonoBehaviour)(object)__instance); } } [HarmonyPatch(typeof(MenuPageCosmetics), "OnDestroy")] internal static class BatchIconGeneratorMenuClosePatch { [HarmonyPostfix] private static void Postfix() { BatchIconGenerator.NotifyMenuClosed(); CosmeticHoverPatch.OnMenuClosed(); CosmeticsMenuState.OnMenuClosed(); CosmeticsMenuLateUpdatePatch.OnMenuClosed(); } } [HarmonyPatch(typeof(CosmeticAsset), "GetIcon")] internal static class GetIconPatch { [HarmonyPrefix] private static bool Prefix(CosmeticAsset __instance, ref Sprite? __result) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.icon != (Object)null) { __result = __instance.icon; return false; } if ((Object)(object)((PrefabRef)(object)__instance.prefab)?.Prefab == (Object)null) { return true; } if ((Object)(object)((PrefabRef)(object)__instance.prefab).Prefab.GetComponentInChildren(true) != (Object)null) { return true; } if (IconCapture.HasCache(__instance)) { __result = SemiFunc.LoadSpriteFromFile(IconCapture.CachePathFor(__instance)); __instance.icon = __result; return false; } if (BridgeIds.IsBridgeAsset(__instance)) { if (Plugin.UseTextureAsPlaceholder.Value && HhhCosmeticLoader.BridgeIconTextures.TryGetValue(__instance.assetId, out Texture2D value) && (Object)(object)value != (Object)null) { __result = Sprite.Create(value, new Rect(0f, 0f, (float)((Texture)value).width, (float)((Texture)value).height), new Vector2(0.5f, 0.5f), 100f); ((Object)__result).name = "BridgeIcon_" + ((Object)__instance).name; } else { __result = PlaceholderIcon.Get(); } __instance.icon = __result; } else { __result = null; } return false; } } internal static class PlaceholderIcon { private const int Size = 64; private static Sprite? _cached; internal static Sprite Get() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cached != (Object)null) { return _cached; } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)val).name = "MoreHeadBridge_Placeholder"; ((Texture)val).filterMode = (FilterMode)0; Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 0.8f, 0f, 1f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.13f, 0.13f, 0.18f, 1f); Color val4 = default(Color); ((Color)(ref val4))..ctor(0.22f, 0.22f, 0.28f, 1f); Color val5 = default(Color); ((Color)(ref val5))..ctor(1f, 0.8f, 0f, 0.35f); Color[] array = (Color[])(object)new Color[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { bool flag = j < 3 || j >= 61 || i < 3 || i >= 61; bool flag2 = (j + i) / 4 % 2 == 0; Color val6 = ((!flag) ? ((!flag2) ? val4 : Color.Lerp(val3, val5, 0.5f)) : val2); array[i * 64 + j] = val6; } } DrawM(array, 64, val2); val.SetPixels(array); val.Apply(); _cached = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); ((Object)_cached).name = "MoreHeadBridge_Placeholder"; return _cached; } private static void DrawM(Color[] pixels, int size, Color color) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_0086: Unknown result type (might be due to invalid IL or missing references) for (int i = 14; i <= 50; i++) { Plot(pixels, size, 18, i, color); Plot(pixels, size, 19, i, color); Plot(pixels, size, 45, i, color); Plot(pixels, size, 44, i, color); } int num = 24; for (int j = 0; j <= num; j++) { int y = 50 - j; int num2 = 18 + j * 13 / num; int num3 = 45 - j * 14 / num; Plot(pixels, size, num2, y, color); Plot(pixels, size, num2 + 1, y, color); Plot(pixels, size, num3, y, color); Plot(pixels, size, num3 - 1, y, color); } } private static void Plot(Color[] pixels, int size, int x, int y, Color color) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (x >= 0 && y >= 0 && x < size && y < size) { pixels[y * size + x] = color; } } } internal sealed class LazyFieldRef where TObj : class { private readonly string _fieldName; private readonly string _feature; private FieldRef? _ref; internal bool Broken { get; private set; } internal LazyFieldRef(string fieldName, string feature) { _fieldName = fieldName; _feature = feature; } internal bool TryResolve() { if (Broken) { return false; } if (_ref != null) { return true; } try { _ref = AccessTools.FieldRefAccess(_fieldName); return true; } catch (Exception ex) { Broken = true; BceConsole.LogWarning(typeof(TObj).Name + "." + _fieldName + " not found (game update?) — " + _feature + " disabled: " + ex.Message); return false; } } internal bool TryGet(TObj instance, out TField value) { if (!TryResolve()) { value = default(TField); return false; } value = _ref.Invoke(instance); return true; } internal bool TrySet(TObj instance, TField value) { if (!TryResolve()) { return false; } _ref.Invoke(instance) = value; return true; } } internal static class BorderTheme { internal readonly struct Theme { internal readonly Color[]? Gradient; internal readonly float[]? Weights; internal readonly string Key; internal readonly Color Solid; internal readonly bool HasSolid; internal Theme(string key, Color[] gradient, float[]? weights = null) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) Key = key; Gradient = gradient; Weights = weights; Solid = default(Color); HasSolid = false; } internal Theme(Color solid) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Key = ""; Gradient = null; Weights = null; Solid = solid; HasSolid = true; } } private const string XuaunFolder = "Xuaun-XuaunCosmetics"; private static readonly Color XuaunColor = new Color(1f, 0.39f, 0.52f); private const string FortnitePrefix = "fortnitesemibot:"; private const string RepoPridePrefix = "repopride:"; private const string YoshiPrefix = "yoshicarry:"; private const string MonsterPrefix = "repomonsterscosmetics:"; private static readonly Dictionary Flags = new Dictionary(StringComparer.Ordinal) { ["pride"] = (Color[])(object)new Color[6] { C(228, 3, 3), C(255, 140, 0), C(255, 237, 0), C(0, 128, 38), C(0, 77, 255), C(117, 7, 135) }, ["newpride"] = (Color[])(object)new Color[11] { C(0, 0, 0), C(97, 57, 21), C(91, 206, 250), C(245, 169, 184), C(255, 255, 255), C(228, 3, 3), C(255, 140, 0), C(255, 237, 0), C(0, 128, 38), C(0, 77, 255), C(117, 7, 135) }, ["trans"] = (Color[])(object)new Color[5] { C(91, 206, 250), C(245, 169, 184), C(255, 255, 255), C(245, 169, 184), C(91, 206, 250) }, ["bi"] = (Color[])(object)new Color[5] { C(214, 2, 112), C(214, 2, 112), C(155, 79, 150), C(0, 56, 168), C(0, 56, 168) }, ["pan"] = (Color[])(object)new Color[3] { C(255, 33, 140), C(255, 216, 0), C(33, 177, 255) }, ["lesbian"] = (Color[])(object)new Color[5] { C(213, 45, 0), C(255, 154, 86), C(255, 255, 255), C(211, 98, 164), C(163, 2, 98) }, ["enby"] = (Color[])(object)new Color[4] { C(252, 244, 52), C(255, 255, 255), C(156, 89, 209), C(44, 44, 44) }, ["ace"] = (Color[])(object)new Color[4] { C(0, 0, 0), C(163, 163, 163), C(255, 255, 255), C(128, 0, 128) }, ["aro"] = (Color[])(object)new Color[5] { C(61, 165, 66), C(167, 211, 121), C(255, 255, 255), C(169, 169, 169), C(0, 0, 0) }, ["agender"] = (Color[])(object)new Color[7] { C(0, 0, 0), C(185, 185, 185), C(255, 255, 255), C(184, 244, 178), C(255, 255, 255), C(185, 185, 185), C(0, 0, 0) }, ["intersex"] = (Color[])(object)new Color[3] { C(255, 216, 0), C(122, 0, 172), C(255, 216, 0) } }; private static readonly string[] FlagsByLength = BuildOrder(Flags.Keys); private static readonly Dictionary YoshiColors = new Dictionary(StringComparer.Ordinal) { ["green"] = (Color[])(object)new Color[6] { C(110, 185, 44), C(232, 91, 4), C(227, 2, 15), C(110, 185, 44), C(224, 92, 3), C(244, 217, 10) }, ["blue"] = (Color[])(object)new Color[6] { C(1, 168, 244), C(232, 91, 4), C(227, 2, 15), C(1, 168, 244), C(184, 61, 186), C(244, 217, 10) }, ["yellow"] = (Color[])(object)new Color[6] { C(255, 243, 1), C(232, 91, 4), C(227, 2, 15), C(255, 243, 1), C(14, 210, 68), C(244, 217, 10) }, ["red"] = (Color[])(object)new Color[6] { C(236, 27, 36), C(232, 91, 4), C(227, 2, 15), C(236, 27, 36), C(114, 120, 207), C(244, 217, 10) }, ["custom"] = (Color[])(object)new Color[6] { C(231, 231, 231), C(232, 91, 4), C(227, 2, 15), C(231, 231, 231), C(1, 168, 244), C(244, 217, 10) } }; private static readonly float[] YoshiWeight = new float[6] { 4f, 2f, 3f, 2f, 3f, 1f }; private static readonly Dictionary YoshiWeights = new Dictionary(StringComparer.Ordinal) { ["green"] = YoshiWeight, ["blue"] = YoshiWeight, ["yellow"] = YoshiWeight, ["red"] = YoshiWeight, ["custom"] = YoshiWeight }; private static readonly string[] YoshiByLength = BuildOrder(YoshiColors.Keys); private static readonly Color[] MonsterStops = (Color[])(object)new Color[3] { C(15, 5, 25), C(90, 30, 140), C(180, 40, 160) }; private static readonly float[]? MonsterWeights = null; private static readonly Dictionary _gradientCache = new Dictionary(StringComparer.Ordinal); private static Color C(int r, int g, int b) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) return new Color((float)r / 255f, (float)g / 255f, (float)b / 255f, 1f); } private static string[] BuildOrder(IEnumerable tokens) { List list = new List(tokens); list.Sort((string a, string b) => b.Length - a.Length); return list.ToArray(); } internal static bool TryResolve(CosmeticAsset? asset, out Theme theme) { //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) theme = default(Theme); if ((Object)(object)asset == (Object)null) { return false; } string text = asset.assetId ?? ""; if (text.StartsWith("repopride:", StringComparison.OrdinalIgnoreCase) && CustomizerStore.IsNonBridgeModdedForAsset(asset)) { string text2 = text.Substring("repopride:".Length); if (text2.Length > 3) { string text3 = text2.Substring(3); string[] flagsByLength = FlagsByLength; foreach (string text4 in flagsByLength) { if (text3.StartsWith(text4, StringComparison.OrdinalIgnoreCase)) { theme = new Theme(text4, Flags[text4]); return true; } } } } if (text.StartsWith("yoshicarry:", StringComparison.OrdinalIgnoreCase) && CustomizerStore.IsNonBridgeModdedForAsset(asset)) { string text5 = text.Substring("yoshicarry:".Length); if (text5.Length > 3) { string text6 = text5.Substring(3); string[] yoshiByLength = YoshiByLength; foreach (string text7 in yoshiByLength) { if (text6.StartsWith(text7, StringComparison.OrdinalIgnoreCase)) { theme = new Theme("yoshi-" + text7, YoshiColors[text7], YoshiWeights[text7]); return true; } } } } if (text.StartsWith("repomonsterscosmetics:", StringComparison.OrdinalIgnoreCase) && CustomizerStore.IsNonBridgeModdedForAsset(asset)) { theme = new Theme("monster", MonsterStops, MonsterWeights); return true; } if (HhhCosmeticLoader.IsFromFolder(asset, "Xuaun-XuaunCosmetics") && CustomizerStore.IsModdedForAsset(asset)) { theme = new Theme(XuaunColor); return true; } if (text.StartsWith("fortnitesemibot:", StringComparison.OrdinalIgnoreCase) && CustomizerStore.IsNonBridgeModdedForAsset(asset)) { theme = new Theme(XuaunColor); return true; } return false; } internal static Texture2D GradientTexture(string key, Color[] stops, float[]? weights = null) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) if (_gradientCache.TryGetValue(key, out Texture2D value) && (Object)(object)value != (Object)null) { return value; } value = new Texture2D(1, 128, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; float[] array = new float[stops.Length]; if (weights != null && weights.Length == stops.Length) { float num = 0f; for (int i = 0; i < weights.Length; i++) { num += Mathf.Max(weights[i], 0f); } if (num <= 0f) { num = 1f; } float num2 = 0f; for (int j = 0; j < stops.Length; j++) { float num3 = Mathf.Max(weights[j], 0f); array[j] = (num2 + num3 * 0.5f) / num; num2 += num3; } } else { for (int k = 0; k < stops.Length; k++) { array[k] = ((stops.Length > 1) ? ((float)k / (float)(stops.Length - 1)) : 0f); } } for (int l = 0; l < 128; l++) { float num4 = 1f - (float)l / 127f; Color val; if (num4 <= array[0]) { val = stops[0]; } else if (num4 >= array[stops.Length - 1]) { val = stops[^1]; } else { int m; for (m = 0; m < stops.Length - 1 && num4 > array[m + 1]; m++) { } float num5 = array[m + 1] - array[m]; float num6 = ((num5 > 0f) ? ((num4 - array[m]) / num5) : 0f); val = Color.Lerp(stops[m], stops[m + 1], num6); } value.SetPixel(0, l, val); } value.Apply(); _gradientCache[key] = value; return value; } } internal sealed class BridgeBorderTheme : MonoBehaviour { private RawImage? _border; private Texture? _origTex; private bool _captured; internal void ConfigureGradient(RawImage border, string key, Color[] gradient, float[]? weights) { _border = border; if (!_captured) { _origTex = border.texture; _captured = true; } Texture2D val = BorderTheme.GradientTexture(key, gradient, weights); if ((Object)(object)border.texture != (Object)(object)val) { border.texture = (Texture)(object)val; } } internal void Deactivate() { if ((Object)(object)_border != (Object)null && _captured && (Object)(object)_border.texture != (Object)(object)_origTex) { _border.texture = _origTex; } } } [HarmonyPatch(typeof(MenuElementCosmeticButton), "UpdateIcon")] internal static class CosmeticBorderThemePatch { [HarmonyPostfix] private static void Postfix(MenuElementCosmeticButton __instance) { RawImage bgBorder = __instance.bgBorder; if ((Object)(object)bgBorder == (Object)null) { return; } BridgeBorderTheme bridgeBorderTheme = ((Component)__instance).GetComponent(); if (BorderTheme.TryResolve(__instance.cosmeticAsset, out var theme) && !theme.HasSolid) { if (bridgeBorderTheme == null) { bridgeBorderTheme = ((Component)__instance).gameObject.AddComponent(); } bridgeBorderTheme.ConfigureGradient(bgBorder, theme.Key, theme.Gradient, theme.Weights); } else { bridgeBorderTheme?.Deactivate(); } } } internal static class CosmeticConditionFormat { internal readonly struct ConditionOption { internal readonly Type Type; internal readonly string Label; internal ConditionOption(Type type, string label) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Type = type; Label = label; } } internal unsafe static int FamilyRank(Type type) { string text = ((object)(*(Type*)(&type))/*cast due to .constrained prefix*/).ToString(); if (TryGetFamily(text, out int familyRank, out string _)) { return familyRank; } if (text.StartsWith("EyeLeft_", StringComparison.Ordinal) || text.StartsWith("EyeRight_", StringComparison.Ordinal) || text.StartsWith("Hat_", StringComparison.Ordinal) || text.StartsWith("Eyewear_", StringComparison.Ordinal) || text.StartsWith("FaceTop_", StringComparison.Ordinal) || text.StartsWith("FaceBottom_", StringComparison.Ordinal) || text.StartsWith("Ears_", StringComparison.Ordinal) || text.StartsWith("EyeLidRightMesh_", StringComparison.Ordinal) || text.StartsWith("EyeLidLeftMesh_", StringComparison.Ordinal)) { return 2; } return 100; } internal unsafe static int VariantRank(Type type) { string name = ((object)(*(Type*)(&type))/*cast due to .constrained prefix*/).ToString(); if (TryGetFamily(name, out int _, out string variant)) { return variant switch { "Default" => 0, "Big" => 1, "Tiny" => 2, "Wide" => 3, "Tall" => 4, "BigUpper" => 5, "BigLower" => 6, "Huge" => 7, "MissingRight" => 8, _ => 50, }; } return 50; } private static bool TryGetFamily(string name, out int familyRank, out string variant) { familyRank = 100; variant = string.Empty; if (name.StartsWith("HeadTopMesh_Shape_", StringComparison.Ordinal)) { familyRank = 0; string text = name; int length = "HeadTopMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } if (name.StartsWith("HeadBottomMesh_Shape_", StringComparison.Ordinal)) { familyRank = 1; string text = name; int length = "HeadBottomMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } if (name.StartsWith("BodyTopMesh_Shape_", StringComparison.Ordinal)) { familyRank = 2; string text = name; int length = "BodyTopMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } if (name.StartsWith("BodyBottomMesh_Shape_", StringComparison.Ordinal)) { familyRank = 3; string text = name; int length = "BodyBottomMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } if (name.StartsWith("ArmRightMesh_Shape_", StringComparison.Ordinal)) { familyRank = 4; string text = name; int length = "ArmRightMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } if (name.StartsWith("ArmLeftMesh_Shape_", StringComparison.Ordinal)) { familyRank = 5; string text = name; int length = "ArmLeftMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } if (name.StartsWith("LegRightMesh_Shape_", StringComparison.Ordinal)) { familyRank = 6; string text = name; int length = "LegRightMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } if (name.StartsWith("LegLeftMesh_Shape_", StringComparison.Ordinal)) { familyRank = 7; string text = name; int length = "LegLeftMesh_Shape_".Length; variant = text.Substring(length, text.Length - length); return true; } return false; } internal unsafe static string Label(Type type, bool headExplicit = false) { string text = ((object)(*(Type*)(&type))/*cast due to .constrained prefix*/).ToString(); if (TryGetFamily(text, out int familyRank, out string variant)) { return FamilyLabel(text, headExplicit) + " - " + Humanize(variant); } int num = text.IndexOf('_'); if (num >= 0) { string token = text.Substring(0, num); string text2 = text; familyRank = num + 1; string token2 = text2.Substring(familyRank, text2.Length - familyRank); return Humanize(token, headExplicit) + " - " + Humanize(token2); } return Humanize(text, headExplicit); } private static string FamilyLabel(string name, bool headExplicit) { if (name.StartsWith("HeadTop", StringComparison.Ordinal)) { if (!headExplicit) { return "Top"; } return "Head Top"; } if (name.StartsWith("HeadBottom", StringComparison.Ordinal)) { if (!headExplicit) { return "Bottom"; } return "Head Bottom"; } if (name.StartsWith("BodyTop", StringComparison.Ordinal)) { return "Body Top"; } if (name.StartsWith("BodyBottom", StringComparison.Ordinal)) { return "Body Bottom"; } if (name.StartsWith("ArmRight", StringComparison.Ordinal)) { return "Arm Right"; } if (name.StartsWith("ArmLeft", StringComparison.Ordinal)) { return "Arm Left"; } if (name.StartsWith("LegRight", StringComparison.Ordinal)) { return "Leg Right"; } if (name.StartsWith("LegLeft", StringComparison.Ordinal)) { return "Leg Left"; } return Humanize(name.Replace("Mesh", string.Empty), headExplicit); } private static string Humanize(string token, bool headExplicit = false) { return token.Replace("BigUpper", "Big Upper").Replace("BigLower", "Big Lower").Replace("MissingRight", "Missing Right") .Replace("EyeLeft", "Eye Left") .Replace("EyeRight", "Eye Right") .Replace("EyeLidRight", "Eye Lid Right") .Replace("EyeLidLeft", "Eye Lid Left") .Replace("HeadTop", headExplicit ? "Head Top" : "Top") .Replace("HeadBottom", headExplicit ? "Head Bottom" : "Bottom") .Replace("BodyTop", "Body Top") .Replace("BodyBottom", "Body Bottom") .Replace("ArmRight", "Arm Right") .Replace("ArmLeft", "Arm Left") .Replace("LegRight", "Leg Right") .Replace("LegLeft", "Leg Left") .Replace("FootRight", "Foot Right") .Replace("FootLeft", "Foot Left") .Replace("_", " ") .Trim(); } internal static int Compare(CosmeticOffsetEntry left, CosmeticOffsetEntry right) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) int num = FamilyRank(left.TriggerType); int num2 = FamilyRank(right.TriggerType); if (num != num2) { return num.CompareTo(num2); } int num3 = VariantRank(left.TriggerType); int num4 = VariantRank(right.TriggerType); if (num3 != num4) { return num3.CompareTo(num4); } return string.Compare(Label(left.TriggerType), Label(right.TriggerType), StringComparison.Ordinal); } } internal static class CosmeticConditionsPopup { private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnTopGap = 10f; private const float BtnRowH = 30f; private const float BtnDoneX = 58f; private const float BtnCancelX = -137f; private static readonly Dictionary TypeConditions; private static readonly Dictionary Labels; internal static void Show(HashSet pendingCustomTypes, CosmeticType cosmeticType, Action? onPreview = null, Transform? parentPopupTransform = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ShowNow(pendingCustomTypes, cosmeticType, onPreview, parentPopupTransform); }); } private static void ShowNow(HashSet pendingCustomTypes, CosmeticType cosmeticType, Action? onPreview, Transform? parentPopupTransform) { //IL_0019: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Invalid comparison between Unknown and I4 //IL_011e: Expected O, but got Unknown if (!TypeConditions.TryGetValue(cosmeticType, out Type[] value) || value.Length == 0) { return; } HashSet snapshot = new HashSet(pendingCustomTypes); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Shape Conditions", false, false, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, parentPopupTransform); Type[] array = value; foreach (Type val in array) { Type captured = val; string value2; string label = (Labels.TryGetValue(captured, out value2) ? value2 : ((object)Unsafe.As(ref captured)/*cast due to .constrained prefix*/).ToString()); bool isOn = pendingCustomTypes.Contains(captured); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002f: 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) string text = label; Action obj = delegate(bool on) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (on) { pendingCustomTypes.Add(captured); } else { pendingCustomTypes.Remove(captured); } onPreview?.Invoke(); }; bool flag = isOn; REPOToggle val2 = MenuAPI.CreateREPOToggle(text, obj, scrollView, default(Vector2), "ON", "OFF", flag); return ((REPOElement)val2).rectTransform; }, ((int)val == (int)value[0]) ? 15f : 0f, 0f); } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { //IL_001b: 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_0027: Unknown result type (might be due to invalid IL or missing references) pendingCustomTypes.Clear(); foreach (Type item in snapshot) { pendingCustomTypes.Add(item); } onPreview?.Invoke(); popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Done", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(58f, 0f)); return val2; }, 10f, 0f); popup.OpenPage(true); } internal static bool HasConditions(CosmeticType type) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return TypeConditions.ContainsKey(type); } internal static IReadOnlyList ValidCustomTypes(CosmeticType type) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!TypeConditions.TryGetValue(type, out Type[] value)) { return Array.Empty(); } return value; } static CosmeticConditionsPopup() { Dictionary dictionary = new Dictionary(); Type[] array = new Type[9]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)0] = (Type[])(object)array; Type[] array2 = new Type[3]; RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)30] = (Type[])(object)array2; Type[] array3 = new Type[13]; RuntimeHelpers.InitializeArray(array3, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)18] = (Type[])(object)array3; Type[] array4 = new Type[7]; RuntimeHelpers.InitializeArray(array4, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)31] = (Type[])(object)array4; dictionary[(CosmeticType)32] = (Type[])(object)new Type[1] { (Type)32 }; dictionary[(CosmeticType)17] = (Type[])(object)new Type[1] { (Type)68 }; Type[] array5 = new Type[3]; RuntimeHelpers.InitializeArray(array5, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)20] = (Type[])(object)array5; dictionary[(CosmeticType)21] = (Type[])(object)new Type[2] { (Type)21, (Type)20 }; Type[] array6 = new Type[4]; RuntimeHelpers.InitializeArray(array6, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)3] = (Type[])(object)array6; Type[] array7 = new Type[4]; RuntimeHelpers.InitializeArray(array7, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)4] = (Type[])(object)array7; Type[] array8 = new Type[4]; RuntimeHelpers.InitializeArray(array8, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)19] = (Type[])(object)array8; Type[] array9 = new Type[4]; RuntimeHelpers.InitializeArray(array9, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)22] = (Type[])(object)array9; Type[] array10 = new Type[7]; RuntimeHelpers.InitializeArray(array10, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)5] = (Type[])(object)array10; Type[] array11 = new Type[4]; RuntimeHelpers.InitializeArray(array11, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)6] = (Type[])(object)array11; dictionary[(CosmeticType)14] = (Type[])(object)new Type[1] { (Type)83 }; dictionary[(CosmeticType)15] = (Type[])(object)new Type[1] { (Type)84 }; Type[] array12 = new Type[6]; RuntimeHelpers.InitializeArray(array12, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)7] = (Type[])(object)array12; Type[] array13 = new Type[7]; RuntimeHelpers.InitializeArray(array13, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)8] = (Type[])(object)array13; Type[] array14 = new Type[7]; RuntimeHelpers.InitializeArray(array14, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)9] = (Type[])(object)array14; Type[] array15 = new Type[7]; RuntimeHelpers.InitializeArray(array15, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)10] = (Type[])(object)array15; Type[] array16 = new Type[7]; RuntimeHelpers.InitializeArray(array16, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)11] = (Type[])(object)array16; Type[] array17 = new Type[7]; RuntimeHelpers.InitializeArray(array17, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); dictionary[(CosmeticType)12] = (Type[])(object)array17; TypeConditions = dictionary; Labels = new Dictionary { [(Type)22] = "Wide Shape", [(Type)28] = "Overlaps Face Top", [(Type)29] = "Overlaps Face Bottom", [(Type)97] = "Push Eyebrows (Big)", [(Type)99] = "Push Eyebrows (Small)", [(Type)98] = "Hide Right Eyebrow", [(Type)56] = "Covers Head Top", [(Type)25] = "Restrict Look Down", [(Type)11] = "Overlaps Body Top", [(Type)12] = "Override Flat", [(Type)24] = "Flat State", [(Type)86] = "Protrudes", [(Type)32] = "Face Bottom Protrudes", [(Type)69] = "Overlaps Head Bottom", [(Type)27] = "Tall Shape", [(Type)26] = "Very Tall (Inner)", [(Type)82] = "Very Tall (Outer)", [(Type)83] = "Right Eyelid Protrudes", [(Type)84] = "Left Eyelid Protrudes", [(Type)30] = "Overlaps Face Top", [(Type)31] = "Overlaps Face Bottom", [(Type)33] = "Overlaps Face Bottom (Protruding)", [(Type)79] = "Covers Right Eye", [(Type)80] = "Covers Left Eye", [(Type)81] = "Covers Both Eyes", [(Type)16] = "Disable Right Eye", [(Type)17] = "Disable Left Eye", [(Type)34] = "Huge Shape", [(Type)35] = "Tall Shape", [(Type)70] = "Very Tall Shape", [(Type)85] = "Overlaps Face Bottom", [(Type)76] = "Covers Middle", [(Type)77] = "Covers Left", [(Type)78] = "Covers Right", [(Type)68] = "Tall Shape", [(Type)10] = "Overlaps Neck", [(Type)18] = "Overlaps Pants (Front)", [(Type)19] = "Overlaps Pants (Back)", [(Type)13] = "Override Flat", [(Type)23] = "Flat State", [(Type)37] = "Wide Torso", [(Type)38] = "Narrow Torso", [(Type)43] = "Right Arm: Big", [(Type)71] = "Right Arm: Big Upper", [(Type)73] = "Right Arm: Big Lower", [(Type)90] = "Right Arm: Huge", [(Type)44] = "Right Arm: Tiny", [(Type)46] = "Left Arm: Big", [(Type)72] = "Left Arm: Big Upper", [(Type)74] = "Left Arm: Big Lower", [(Type)89] = "Left Arm: Huge", [(Type)47] = "Left Arm: Tiny", [(Type)21] = "Protrudes", [(Type)20] = "Protrudes (Front)", [(Type)87] = "Wide Shape", [(Type)88] = "Tall Shape", [(Type)40] = "Big Shape", [(Type)41] = "Narrow Shape", [(Type)49] = "Right Leg: Big", [(Type)91] = "Right Leg: Big Upper", [(Type)92] = "Right Leg: Big Lower", [(Type)93] = "Right Leg: Huge", [(Type)50] = "Right Leg: Tiny", [(Type)52] = "Left Leg: Big", [(Type)94] = "Left Leg: Big Upper", [(Type)95] = "Left Leg: Big Lower", [(Type)96] = "Left Leg: Huge", [(Type)53] = "Left Leg: Tiny", [(Type)4] = "Long Foot", [(Type)6] = "Normal Foot", [(Type)8] = "Short Foot", [(Type)54] = "Foot Protrudes", [(Type)5] = "Long Foot", [(Type)7] = "Normal Foot", [(Type)9] = "Short Foot", [(Type)55] = "Foot Protrudes", [(Type)3] = "Big Shape", [(Type)14] = "Default Shape", [(Type)15] = "Tiny Shape", [(Type)57] = "Unchanged Shape", [(Type)75] = "Missing Right Side", [(Type)59] = "Default Shape", [(Type)60] = "Big Shape", [(Type)61] = "Tiny Shape", [(Type)58] = "Unchanged Shape", [(Type)42] = "Default Shape", [(Type)64] = "Unchanged Shape", [(Type)45] = "Default Shape", [(Type)65] = "Unchanged Shape", [(Type)36] = "Default Shape", [(Type)62] = "Unchanged Shape", [(Type)39] = "Default Shape", [(Type)63] = "Unchanged Shape", [(Type)48] = "Default Shape", [(Type)66] = "Unchanged Shape", [(Type)51] = "Default Shape", [(Type)67] = "Unchanged Shape" }; } } internal static class CosmeticCrownPopup { private const float PosYOffset = 0.35f; private const float PosZOffset = 0.25f; private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnTopGap = 10f; private const float BtnRowH = 30f; private const float BtnDoneX = 58f; private const float BtnCancelX = -137f; private const float BtnClearX = -137f; private static readonly string[] PosOptions = BuildRange(-1f, 1f, 0.05f, "F2"); private static readonly string[] RotOptions = BuildIntRange(-180, 180, 5); private static readonly string[] ScaleOptions = BuildRange(0.5f, 2f, 0.05f, "F2"); private static readonly string[] PriorityOptions = BuildIntRange(-50, 50, 5); private static readonly string[] SpringOptions = new string[2] { "No", "Yes" }; internal static void Show(CosmeticCrownConfig? existing, CosmeticType cosmeticType, Action onDone, Action? onClear = null, Action? onPreview = null, Transform? parentPopupTransform = null, Action? onCancel = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ShowNow(existing, cosmeticType, onDone, onClear, onPreview, parentPopupTransform, onCancel); }); } private static void ShowNow(CosmeticCrownConfig? existing, CosmeticType cosmeticType, Action onDone, Action? onClear, Action? onPreview, Transform? parentPopupTransform, Action? onCancel) { //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Invalid comparison between Unknown and I4 //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Expected O, but got Unknown //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_03e9: Expected O, but got Unknown float displayX = existing?.PosX ?? 0f; float displayY = ((existing != null) ? (existing.PosY - 0.35f) : 0f); float displayZ = ((existing != null) ? (existing.PosZ - 0.25f) : 0f); float rotX = existing?.RotX ?? 0f; float rotY = existing?.RotY ?? 0f; float rotZ = existing?.RotZ ?? 0f; float scaleX = existing?.ScaleX ?? 1f; float scaleY = existing?.ScaleY ?? 1f; float scaleZ = existing?.ScaleZ ?? 1f; int priority = existing?.Priority ?? (((int)cosmeticType == 5) ? (-50) : 0); bool disableSpring = existing?.DisableSpring ?? false; REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Crown Settings", false, false, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, parentPopupTransform); PopupUI.AddFloatSlider(popup, "Pos X", PosOptions, displayX, delegate(float v) { displayX = v; Preview(); }, 15f); PopupUI.AddFloatSlider(popup, "Pos Y", PosOptions, displayY, delegate(float v) { displayY = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Pos Z", PosOptions, displayZ, delegate(float v) { displayZ = v; Preview(); }); PopupUI.AddIntSlider(popup, "Rot X", RotOptions, (int)rotX, delegate(float v) { rotX = v; Preview(); }, 10f); PopupUI.AddIntSlider(popup, "Rot Y", RotOptions, (int)rotY, delegate(float v) { rotY = v; Preview(); }); PopupUI.AddIntSlider(popup, "Rot Z", RotOptions, (int)rotZ, delegate(float v) { rotZ = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Scale X", ScaleOptions, scaleX, delegate(float v) { scaleX = v; Preview(); }, 10f); PopupUI.AddFloatSlider(popup, "Scale Y", ScaleOptions, scaleY, delegate(float v) { scaleY = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Scale Z", ScaleOptions, scaleZ, delegate(float v) { scaleZ = v; Preview(); }); PopupUI.AddIntSlider(popup, "Priority", PriorityOptions, priority, delegate(float v) { priority = (int)v; Preview(); }, 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Disable Spring", "", (Action)delegate(string opt) { disableSpring = opt == "Yes"; Preview(); }, scrollView, SpringOptions, disableSpring ? "Yes" : "No", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, 15f, 0f); if (existing != null && onClear != null) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Clear Crown", (Action)delegate { popup.ClosePage(false); onClear(); }, (Transform)(object)val, new Vector2(-137f, 0f)); return val; }, 10f, 0f); } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { onPreview?.Invoke(existing); popup.ClosePage(false); onCancel?.Invoke(); }, (Transform)(object)val, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Done", (Action)delegate { popup.ClosePage(false); onDone(new CosmeticCrownConfig { PosX = displayX, PosY = displayY + 0.35f, PosZ = displayZ + 0.25f, RotX = rotX, RotY = rotY, RotZ = rotZ, ScaleX = scaleX, ScaleY = scaleY, ScaleZ = scaleZ, Priority = priority, DisableSpring = disableSpring }); }, (Transform)(object)val, new Vector2(58f, 0f)); return val; }, (existing != null) ? 0f : 10f, 0f); Preview(); popup.OpenPage(true); void Preview() { FirePreview(onPreview, displayX, displayY, displayZ, rotX, rotY, rotZ, scaleX, scaleY, scaleZ, priority, disableSpring); } } private static void FirePreview(Action? onPreview, float displayX, float displayY, float displayZ, float rotX, float rotY, float rotZ, float scaleX, float scaleY, float scaleZ, int priority, bool disableSpring) { onPreview?.Invoke(new CosmeticCrownConfig { PosX = displayX, PosY = displayY + 0.35f, PosZ = displayZ + 0.25f, RotX = rotX, RotY = rotY, RotZ = rotZ, ScaleX = scaleX, ScaleY = scaleY, ScaleZ = scaleZ, Priority = priority, DisableSpring = disableSpring }); } private static string[] BuildRange(float min, float max, float step, string fmt) { List list = new List(); for (float num = min; num <= max + step * 0.001f; num += step) { list.Add(num.ToString(fmt, CultureInfo.InvariantCulture)); } return list.ToArray(); } private static string[] BuildIntRange(int min, int max, int step) { List list = new List(); for (int i = min; i <= max; i += step) { list.Add(i.ToString(CultureInfo.InvariantCulture)); } return list.ToArray(); } } internal static class CosmeticGrouping { internal readonly struct Member { internal readonly CosmeticAsset Asset; internal readonly string Variant; internal Member(CosmeticAsset a, string v) { Asset = a; Variant = v; } } private static readonly (string token, string label)[] PrideFlags = new(string, string)[11] { ("newpride", "Progress"), ("agender", "Agender"), ("intersex", "Intersex"), ("lesbian", "Lesbian"), ("trans", "Trans"), ("enby", "Non-binary"), ("pride", "Rainbow"), ("ace", "Ace"), ("aro", "Aro"), ("pan", "Pan"), ("bi", "Bi") }; internal static bool Enabled { get { if (Plugin.MenuLibAvailable) { return Plugin.GroupCosmeticVariants.Value; } return false; } } private static bool TryGetInfo(CosmeticAsset asset, out string groupKey, out string variant) { //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected I4, but got Unknown groupKey = ""; variant = ""; if ((Object)(object)asset == (Object)null) { return false; } string text = asset.assetId ?? ""; if (text.StartsWith("repopride:", StringComparison.OrdinalIgnoreCase) && text.Length > "repopride:".Length + 3) { string text2 = text.Substring("repopride:".Length); string text3 = text2.Substring(0, 3); string text4 = text2.Substring(3); (string, string)[] prideFlags = PrideFlags; for (int i = 0; i < prideFlags.Length; i++) { var (text5, text6) = prideFlags[i]; if (text4.StartsWith(text5, StringComparison.OrdinalIgnoreCase)) { string text7 = text4.Substring(text5.Length); groupKey = "repopride:" + text3 + "|" + text7; variant = text6; return true; } } } if (BridgeIds.IsBridgeAsset(asset)) { string text8 = ((Object)asset).name ?? ""; int num = text8.IndexOf('('); int num2 = ((num >= 0) ? text8.IndexOf(')', num + 1) : (-1)); if (num >= 0 && num2 > num) { variant = text8.Substring(num + 1, num2 - num - 1).Trim(); string text9 = (text8.Substring(0, num) + text8.Substring(num2 + 1)).Replace(" ", " ").Trim(); groupKey = $"bridge:{(int)asset.type}|{text9.ToLowerInvariant()}"; return variant.Length > 0; } } return false; } internal static List<(CosmeticAsset rep, List? members)> Collapse(IEnumerable assets) { List<(CosmeticAsset, List)> list = new List<(CosmeticAsset, List)>(); if (!Enabled) { foreach (CosmeticAsset asset2 in assets) { list.Add((asset2, null)); } return list; } Dictionary dictionary = new Dictionary(); HashSet hashSet = new HashSet(); MetaManager instance = MetaManager.instance; if ((Object)(object)instance != (Object)null) { foreach (int item2 in instance.cosmeticEquipped) { if (item2 >= 0 && item2 < instance.cosmeticAssets.Count && (Object)(object)instance.cosmeticAssets[item2] != (Object)null) { hashSet.Add(instance.cosmeticAssets[item2]); } } } foreach (CosmeticAsset asset3 in assets) { if ((Object)(object)asset3 != (Object)null && TryGetInfo(asset3, out string groupKey, out string variant)) { if (!dictionary.TryGetValue(groupKey, out var value)) { value = (dictionary[groupKey] = list.Count); list.Add((asset3, new List())); } list[value].Item2.Add(new Member(asset3, variant)); } else { list.Add((asset3, null)); } } for (int i = 0; i < list.Count; i++) { List item = list[i].Item2; if (item == null) { continue; } if (item.Count == 1) { list[i] = (item[0].Asset, null); continue; } item.Sort((Member x, Member y) => string.Compare(x.Variant, y.Variant, StringComparison.OrdinalIgnoreCase)); CosmeticAsset asset = item[0].Asset; foreach (Member item3 in item) { if (hashSet.Contains(item3.Asset)) { asset = item3.Asset; break; } } list[i] = (asset, item); } return list; } } internal sealed class CosmeticGroupButton : MonoBehaviour { internal List Members = new List(); internal bool IsActive { get { if (Members != null) { return Members.Count > 1; } return false; } } internal static void Attach(MenuElementCosmeticButton btn, List members) { CosmeticGroupButton cosmeticGroupButton = ((Component)btn).GetComponent() ?? ((Component)btn).gameObject.AddComponent(); cosmeticGroupButton.Members = members; cosmeticGroupButton.AddCountBadge(btn, members.Count); } private void AddCountBadge(MenuElementCosmeticButton btn, int count) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)((Component)btn).transform.Find("MHB_GroupCount") != (Object)null)) { TextMeshProUGUI componentInChildren = ((Component)btn).GetComponentInChildren(true); GameObject val = new GameObject("MHB_GroupCount", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)btn).transform, false); RectTransform val2 = (RectTransform)val.transform; Vector2 val3 = (val2.pivot = new Vector2(0f, 1f)); Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.anchoredPosition = new Vector2(7f, -4f); val2.sizeDelta = new Vector2(26f, 14f); TextMeshProUGUI val6 = val.AddComponent(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)val6).font = ((TMP_Text)componentInChildren).font; } ((TMP_Text)val6).text = count.ToString(); ((TMP_Text)val6).fontSize = 10f; ((TMP_Text)val6).fontStyle = (FontStyles)1; ((TMP_Text)val6).alignment = (TextAlignmentOptions)257; ((Graphic)val6).color = Color.white; ((Graphic)val6).raycastTarget = false; } } catch { } } } internal static class CosmeticHidePopup { private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnTopGap = 10f; private const float BtnDoneX = 58f; private const float BtnCancelX = -137f; private static readonly CosmeticType[] HideWhenTypes; private static readonly (Pose Pose, string Label)[] HidePoses; private static readonly Dictionary TypeLabels; internal static void Show(CosmeticHideConfig config, CosmeticType cosmeticType, Action? onPreview = null, Transform? parentPopupTransform = null, bool worldMode = false) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ShowNow(config, cosmeticType, onPreview, parentPopupTransform, worldMode); }); } private static void ShowNow(CosmeticHideConfig config, CosmeticType cosmeticType, Action? onPreview, Transform? parentPopupTransform, bool worldMode) { //IL_00b1: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Expected O, but got Unknown //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_038f: Expected O, but got Unknown //IL_02af: Expected O, but got Unknown CosmeticHideConfig cosmeticHideConfig = config; if (cosmeticHideConfig.WhenTypes == null) { List list = (cosmeticHideConfig.WhenTypes = new List()); } cosmeticHideConfig = config; if (cosmeticHideConfig.WhenConditions == null) { List list3 = (cosmeticHideConfig.WhenConditions = new List()); } cosmeticHideConfig = config; if (cosmeticHideConfig.WhenPoses == null) { List list5 = (cosmeticHideConfig.WhenPoses = new List()); } List snapTypes = new List(config.WhenTypes); List snapConds = new List(config.WhenConditions); List snapPoses = new List(config.WhenPoses); IReadOnlyList readOnlyList; if (!worldMode) { readOnlyList = CosmeticConditionsPopup.ValidCustomTypes(cosmeticType); } else { IReadOnlyList readOnlyList2 = Array.Empty(); readOnlyList = readOnlyList2; } IReadOnlyList readOnlyList3 = readOnlyList; REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Hide Conditions", false, false, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, parentPopupTransform); AddLabel(popup, "Hide when equipped:", 15f); bool flag = true; CosmeticType[] hideWhenTypes = HideWhenTypes; foreach (CosmeticType val in hideWhenTypes) { if (!worldMode && val == cosmeticType) { continue; } CosmeticType captured = val; string value; string label = (TypeLabels.TryGetValue(captured, out value) ? value : ((object)Unsafe.As(ref captured)/*cast due to .constrained prefix*/).ToString()); bool isOn = config.WhenTypes.Contains(captured); bool flag2 = flag; flag = false; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002f: 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) string text = label; Action obj = delegate(bool on) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (on) { if (!config.WhenTypes.Contains(captured)) { config.WhenTypes.Add(captured); } } else { config.WhenTypes.Remove(captured); } onPreview?.Invoke(); }; bool flag7 = isOn; REPOToggle val2 = MenuAPI.CreateREPOToggle(text, obj, scrollView, default(Vector2), "ON", "OFF", flag7); return ((REPOElement)val2).rectTransform; }, flag2 ? 6f : 0f, 0f); } if (readOnlyList3.Count > 0) { AddLabel(popup, "Hide when condition:", 10f); bool flag3 = true; foreach (Type item2 in readOnlyList3) { Type captured2 = item2; string label2 = CosmeticConditionFormat.Label(captured2); bool isOn2 = config.WhenConditions.Contains(captured2); bool flag4 = flag3; flag3 = false; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002f: 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) string text = label2; Action obj = delegate(bool on) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (on) { if (!config.WhenConditions.Contains(captured2)) { config.WhenConditions.Add(captured2); } } else { config.WhenConditions.Remove(captured2); } onPreview?.Invoke(); }; bool flag7 = isOn2; REPOToggle val2 = MenuAPI.CreateREPOToggle(text, obj, scrollView, default(Vector2), "ON", "OFF", flag7); return ((REPOElement)val2).rectTransform; }, flag4 ? 6f : 0f, 0f); } } if (!worldMode) { AddLabel(popup, "Hide when pose:", 10f); bool flag5 = true; (Pose, string)[] hidePoses = HidePoses; for (int num = 0; num < hidePoses.Length; num++) { (Pose, string) tuple = hidePoses[num]; Pose item = tuple.Item1; string label3 = tuple.Item2; Pose captured3 = item; bool isOn3 = config.WhenPoses.Contains(captured3); bool flag6 = flag5; flag5 = false; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002f: 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) string text = label3; Action obj = delegate(bool on) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (on) { if (!config.WhenPoses.Contains(captured3)) { config.WhenPoses.Add(captured3); } } else { config.WhenPoses.Remove(captured3); } onPreview?.Invoke(); }; bool flag7 = isOn3; REPOToggle val2 = MenuAPI.CreateREPOToggle(text, obj, scrollView, default(Vector2), "ON", "OFF", flag7); return ((REPOElement)val2).rectTransform; }, flag6 ? 6f : 0f, 0f); } } List whenCosmetics = config.WhenCosmetics; if (whenCosmetics != null && whenCosmetics.Count > 0) { AddLabel(popup, "Hide with (from mod):", 10f); foreach (string whenCosmetic in config.WhenCosmetics) { AddLabel(popup, "• " + Friendly(whenCosmetic), 0f); } } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { config.WhenTypes.Clear(); config.WhenTypes.AddRange(snapTypes); config.WhenConditions.Clear(); config.WhenConditions.AddRange(snapConds); config.WhenPoses.Clear(); config.WhenPoses.AddRange(snapPoses); onPreview?.Invoke(); popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Done", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(58f, 0f)); return val2; }, 10f, 0f); popup.OpenPage(true); } private static string Friendly(string name) { string text = name.Replace("(Clone)", "").Trim(); if (text.StartsWith("Cosmetic - ", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("Cosmetic - ".Length); } return text; } private static void AddLabel(REPOPopupPage popup, string text, float topPadding) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) REPOLabel val = MenuAPI.CreateREPOLabel(text, scrollView, Vector2.zero); return ((REPOElement)val).rectTransform; }, topPadding, 0f); } static CosmeticHidePopup() { CosmeticType[] array = new CosmeticType[18]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); HideWhenTypes = (CosmeticType[])(object)array; HidePoses = new(Pose, string)[4] { ((Pose)0, "Standing"), ((Pose)1, "Crouching"), ((Pose)2, "Crawling"), ((Pose)3, "Tumbling") }; TypeLabels = new Dictionary { [(CosmeticType)0] = "Hat", [(CosmeticType)5] = "Head Top (Hair)", [(CosmeticType)30] = "Head Bottom", [(CosmeticType)6] = "Head Bottom Mesh", [(CosmeticType)17] = "Ears", [(CosmeticType)18] = "Eyewear", [(CosmeticType)31] = "Face Top", [(CosmeticType)32] = "Face Bottom", [(CosmeticType)20] = "Body Top", [(CosmeticType)7] = "Body Top Mesh", [(CosmeticType)21] = "Body Bottom", [(CosmeticType)8] = "Body Bottom Mesh", [(CosmeticType)1] = "Arm Right", [(CosmeticType)2] = "Arm Left", [(CosmeticType)3] = "Leg Right", [(CosmeticType)4] = "Leg Left", [(CosmeticType)19] = "Foot Right", [(CosmeticType)22] = "Foot Left" }; } } internal sealed class OffsetEntryArgs { internal CosmeticOffsetEntry? Existing; internal Type[]? Triggers; internal Action OnDone = delegate { }; internal Action? OnPreview; internal Transform? ParentPopupTransform; internal bool WorldMode; internal Action? OnDeathHeadTrigger; internal Type? LockedTrigger; internal Action? OnClear; internal bool ShowOnDeathHead = true; internal Action? OnShowOnDeathHeadPreview; internal Action? OnShowOnDeathHeadCommit; internal DeathHeadFloorPose? FloorPose; internal Action? OnFloorPoseCommit; internal bool FloorPoseSupported; internal Action? OnFloorPosePreview; internal Action? OnFloorPosePreviewEnd; } internal static class CosmeticOffsetEntryPopup { private static readonly CosmeticConditionFormat.ConditionOption[] AllConditionOptions = BuildAllConditionOptions(); private static readonly CosmeticConditionFormat.ConditionOption[] WorldConditionOptions = BuildWorldConditionOptions(); internal static readonly string[] PosOptions = BuildPosOptions(); internal static readonly string[] RotOptions = BuildRotOptions(); internal static readonly string[] ScaleOptions = BuildScaleOptions(); internal static readonly string[] SpeedOptions = new string[10] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }; private static readonly string[] ShowHideOptions = new string[2] { "Show", "Hide" }; private static CosmeticConditionFormat.ConditionOption[] BuildAllConditionOptions() { return (from t in Enum.GetValues(typeof(Type)).Cast().OrderBy(CosmeticConditionFormat.FamilyRank) .ThenBy(CosmeticConditionFormat.VariantRank) .ThenBy((Type t) => CosmeticConditionFormat.Label(t)) select new CosmeticConditionFormat.ConditionOption(t, CosmeticConditionFormat.Label(t))).ToArray(); } private static CosmeticConditionFormat.ConditionOption[] BuildWorldConditionOptions() { return (from t in CosmeticOffsetPopup.WorldOffsetTriggers.OrderBy(CosmeticConditionFormat.FamilyRank).ThenBy(CosmeticConditionFormat.VariantRank).ThenBy((Type t) => CosmeticConditionFormat.Label(t, headExplicit: true)) select new CosmeticConditionFormat.ConditionOption(t, CosmeticConditionFormat.Label(t, headExplicit: true))).ToArray(); } private static CosmeticConditionFormat.ConditionOption[] BuildFilteredOptions(Type[] types) { CosmeticConditionFormat.ConditionOption[] array = new CosmeticConditionFormat.ConditionOption[types.Length]; for (int i = 0; i < types.Length; i++) { array[i] = new CosmeticConditionFormat.ConditionOption(types[i], CosmeticConditionFormat.Label(types[i])); } return array; } private static string[] BuildPosOptions() { List list = new List(); for (float num = -1f; num <= 1.0001f; num += 0.05f) { list.Add(num.ToString("F2", CultureInfo.InvariantCulture)); } return list.ToArray(); } private static string[] BuildRotOptions() { List list = new List(); for (int i = -180; i <= 180; i += 5) { list.Add(i.ToString(CultureInfo.InvariantCulture)); } return list.ToArray(); } private static string[] BuildScaleOptions() { List list = new List(); for (float num = 0.5f; num <= 2.0001f; num += 0.05f) { list.Add(num.ToString("F2", CultureInfo.InvariantCulture)); } return list.ToArray(); } internal static void Show(OffsetEntryArgs args) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowNow(args); }); } private static void ShowNow(OffsetEntryArgs args) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Invalid comparison between Unknown and I4 //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Expected O, but got Unknown //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Expected O, but got Unknown //IL_050a: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Expected O, but got Unknown //IL_0554: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Expected O, but got Unknown //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Expected O, but got Unknown CosmeticOffsetEntry existing = args.Existing; Type[] triggers = args.Triggers; Action onDone = args.OnDone; Action onPreview = args.OnPreview; Transform parentPopupTransform = args.ParentPopupTransform; bool worldMode = args.WorldMode; Action onDeathHeadTrigger = args.OnDeathHeadTrigger; Type? lockedTrigger = args.LockedTrigger; Action onClear = args.OnClear; bool showOnDeathHead = args.ShowOnDeathHead; Action onShowOnDeathHeadPreview = args.OnShowOnDeathHeadPreview; Action onShowOnDeathHeadCommit = args.OnShowOnDeathHeadCommit; DeathHeadFloorPose floorPose = args.FloorPose; Action onFloorPoseCommit = args.OnFloorPoseCommit; bool floorPoseSupported = args.FloorPoseSupported; Action onFloorPosePreview = args.OnFloorPosePreview; Action onFloorPosePreviewEnd = args.OnFloorPosePreviewEnd; bool deathHeadEditor = (int)lockedTrigger.GetValueOrDefault() == 2 && onShowOnDeathHeadCommit != null; bool showOnDeath = showOnDeathHead; DeathHeadFloorPose floorLocal = floorPose?.Clone(); Type? selCondition = lockedTrigger ?? existing?.TriggerType; float posX = existing?.PosX ?? 0f; float posY = existing?.PosY ?? 0f; float posZ = existing?.PosZ ?? 0f; float rotX = existing?.RotX ?? 0f; float rotY = existing?.RotY ?? 0f; float rotZ = existing?.RotZ ?? 0f; float scaleX = existing?.ScaleX ?? 1f; float scaleY = existing?.ScaleY ?? 1f; float scaleZ = existing?.ScaleZ ?? 1f; float speed = existing?.LerpSpeed ?? 3f; REPOPopupPage popup = MenuAPI.CreateREPOPopupPage(lockedTrigger.HasValue ? CosmeticConditionFormat.Label(lockedTrigger.Value) : ((existing == null) ? "Add Offset" : "Edit Offset"), false, false, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, parentPopupTransform); bool deathShown = false; CosmeticConditionFormat.ConditionOption[] conditionOptions = (worldMode ? WorldConditionOptions : ((triggers != null) ? BuildFilteredOptions(triggers) : AllConditionOptions)); Dictionary conditionLookup = conditionOptions.ToDictionary((CosmeticConditionFormat.ConditionOption o) => o.Label, (CosmeticConditionFormat.ConditionOption o) => o.Type); if (!lockedTrigger.HasValue) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown string text = (selCondition.HasValue ? CosmeticConditionFormat.Label(selCondition.Value, worldMode) : "None"); string[] array = new string[conditionOptions.Length + 1]; array[0] = "None"; for (int i = 0; i < conditionOptions.Length; i++) { array[i + 1] = conditionOptions[i].Label; } REPOSlider val = MenuAPI.CreateREPOSlider("Trigger", "", (Action)delegate(string opt) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) Type value; if (opt == "None") { selCondition = null; UpdateDeathHead(); onPreview?.Invoke(null); } else if (conditionLookup.TryGetValue(opt, out value)) { selCondition = value; UpdateDeathHead(); onPreview?.Invoke(BuildCurrentEntry()); } }, scrollView, array, text, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, 15f, 0f); } UpdateDeathHead(); if (deathHeadEditor) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Show on Death Head", "", (Action)delegate(string opt) { showOnDeath = opt != "Hide"; onShowOnDeathHeadPreview?.Invoke(showOnDeath); }, scrollView, ShowHideOptions, showOnDeath ? "Show" : "Hide", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, 15f, 0f); } PopupUI.AddFloatSlider(popup, "Pos X", PosOptions, posX, delegate(float v) { posX = v; Preview(); }, 10f); PopupUI.AddFloatSlider(popup, "Pos Y", PosOptions, posY, delegate(float v) { posY = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Pos Z", PosOptions, posZ, delegate(float v) { posZ = v; Preview(); }); PopupUI.AddIntSlider(popup, "Rot X", RotOptions, (int)rotX, delegate(float v) { rotX = v; Preview(); }, 10f); PopupUI.AddIntSlider(popup, "Rot Y", RotOptions, (int)rotY, delegate(float v) { rotY = v; Preview(); }); PopupUI.AddIntSlider(popup, "Rot Z", RotOptions, (int)rotZ, delegate(float v) { rotZ = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Scale X", ScaleOptions, scaleX, delegate(float v) { scaleX = v; Preview(); }, 10f); PopupUI.AddFloatSlider(popup, "Scale Y", ScaleOptions, scaleY, delegate(float v) { scaleY = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Scale Z", ScaleOptions, scaleZ, delegate(float v) { scaleZ = v; Preview(); }); PopupUI.AddIntSlider(popup, "Lerp Speed", SpeedOptions, Mathf.Clamp((int)speed, 1, 10), delegate(float v) { speed = v; Preview(); }, 10f); if (deathHeadEditor && floorPoseSupported) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Impact Pose →", (Action)delegate { DeathHeadFloorPosePopup.Show(floorLocal, delegate(DeathHeadFloorPose p) { onFloorPosePreview?.Invoke(p); }, delegate(DeathHeadFloorPose p) { floorLocal = p; }, delegate { onFloorPosePreviewEnd?.Invoke(); onPreview?.Invoke(BuildCurrentEntry()); }, parentPopupTransform); }, (Transform)(object)val, new Vector2(-137f, 0f)); return val; }, 10f, 0f); } if (onClear != null) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Remove Offset", (Action)delegate { popup.ClosePage(false); CommitDeathHeadExtras(); onClear(); }, (Transform)(object)val, new Vector2(-137f, 0f)); return val; }, 10f, 0f); } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { if (deathShown) { onDeathHeadTrigger?.Invoke(obj: false); } popup.ClosePage(false); onDone(null); }, (Transform)(object)val, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Done", (Action)delegate { //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (deathShown) { onDeathHeadTrigger?.Invoke(obj: false); } popup.ClosePage(false); CommitDeathHeadExtras(); if (selCondition.HasValue) { onDone(new CosmeticOffsetEntry { TriggerType = selCondition.Value, PosX = posX, PosY = posY, PosZ = posZ, RotX = rotX, RotY = rotY, RotZ = rotZ, ScaleX = scaleX, ScaleY = scaleY, ScaleZ = scaleZ, LerpSpeed = speed }); } else { onDone(null); } }, (Transform)(object)val, new Vector2(58f, 0f)); return val; }, 10f, 0f); popup.OpenPage(true); CosmeticOffsetEntry? BuildCurrentEntry() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!selCondition.HasValue) { return null; } return new CosmeticOffsetEntry { TriggerType = selCondition.Value, PosX = posX, PosY = posY, PosZ = posZ, RotX = rotX, RotY = rotY, RotZ = rotZ, ScaleX = scaleX, ScaleY = scaleY, ScaleZ = scaleZ, LerpSpeed = speed }; } void CommitDeathHeadExtras() { if (deathHeadEditor) { onShowOnDeathHeadCommit?.Invoke(showOnDeath); onFloorPoseCommit?.Invoke(floorLocal); } } void Preview() { onPreview?.Invoke(BuildCurrentEntry()); } void UpdateDeathHead() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 bool flag = (int)selCondition.GetValueOrDefault() == 2; if (flag != deathShown) { deathShown = flag; onDeathHeadTrigger?.Invoke(flag); } } } } internal static class CosmeticOffsetPopup { private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnTopGap = 10f; private const float BtnRowH = 30f; private const float BtnDoneX = 58f; private const float BtnCancelX = -137f; private const float EntryLabelX = -137f; private const float EntryEditX = 11f; private const float EntryDelX = 71f; private static readonly Type[] s_headMesh; private static readonly Type[] s_bodyTopMesh; private static readonly Type[] s_bodyBotMesh; private static readonly Type[] s_armRMesh; private static readonly Type[] s_armLMesh; private static readonly Type[] s_legRMesh; private static readonly Type[] s_legLMesh; private static readonly Dictionary OffsetTriggers; internal static readonly Type[] WorldOffsetTriggers; internal static IReadOnlyList ValidOffsetTriggers(CosmeticType type) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!OffsetTriggers.TryGetValue(type, out Type[] value)) { return Array.Empty(); } return value; } private static Type[] BuildWorldOffsetTriggers() { //IL_005a: 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) //IL_0067: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Type[][] array = new Type[7][] { s_headMesh, s_bodyTopMesh, s_bodyBotMesh, s_armRMesh, s_armLMesh, s_legRMesh, s_legLMesh }; foreach (Type[] array2 in array) { Type[] array3 = array2; foreach (Type item in array3) { if (!list.Contains(item)) { list.Add(item); } } } if (!list.Contains((Type)1)) { list.Add((Type)1); } return list.ToArray(); } internal static void Show(List pendingOffsets, CosmeticType forType = (CosmeticType)0, Action>? onPreview = null, Transform? parentPopupTransform = null, bool worldMode = false, Action? onDeathHeadTrigger = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ShowNow(pendingOffsets, forType, onPreview, parentPopupTransform, worldMode, onDeathHeadTrigger); }); } private static void ShowNow(List pendingOffsets, CosmeticType forType, Action>? onPreview, Transform? parentPopupTransform, bool worldMode, Action? onDeathHeadTrigger) { //IL_0044: 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) List working = pendingOffsets.Select((CosmeticOffsetEntry e) => e.Clone()).ToList(); Type[] value = null; if (!worldMode) { OffsetTriggers.TryGetValue(forType, out value); } ShowInternal(pendingOffsets, working, value, worldMode, forType, onPreview, parentPopupTransform, onDeathHeadTrigger); } private static void ShowInternal(List original, List working, Type[]? triggers, bool worldMode, CosmeticType forType, Action>? onPreview = null, Transform? parentPopupTransform = null, Action? onDeathHeadTrigger = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown List deathHeadAside = working.Where((CosmeticOffsetEntry e) => (int)e.TriggerType == 2).ToList(); working.RemoveAll((CosmeticOffsetEntry e) => (int)e.TriggerType == 2); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Special Position Fixes", false, false, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, parentPopupTransform); REPOScrollViewElement noEntriesEl = null; Transform noEntriesTr = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown REPOLabel val = MenuAPI.CreateREPOLabel("(no entries)", scrollView, default(Vector2)); noEntriesTr = ((Component)val).transform; return (RectTransform)((Component)val).transform; }, 15f, 0f); noEntriesEl = ((Component)noEntriesTr).GetComponent(); List entryRows = new List(); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("+ Add Entry", (Action)delegate { PopupUI.AfterMouseRelease((MonoBehaviour)(object)popup, delegate { CosmeticOffsetEntryPopup.Show(new OffsetEntryArgs { Triggers = triggers, OnDone = delegate(CosmeticOffsetEntry? result) { if (result == null) { onPreview?.Invoke(working); } else { working.Add(result); SortWorking(); Rebuild(); } }, OnPreview = delegate(CosmeticOffsetEntry? partial) { if (partial != null) { List list = working.Select((CosmeticOffsetEntry e) => e.Clone()).ToList(); list.Add(partial); onPreview?.Invoke(list); } }, ParentPopupTransform = (parentPopupTransform ?? ((Component)popup).transform), WorldMode = worldMode, OnDeathHeadTrigger = onDeathHeadTrigger }); }); }, (Transform)(object)val, new Vector2(-137f, 0f)); return val; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { onPreview?.Invoke(original); popup.ClosePage(false); }, (Transform)(object)val, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Done", (Action)delegate { original.Clear(); original.AddRange(working); original.AddRange(deathHeadAside); popup.ClosePage(false); }, (Transform)(object)val, new Vector2(58f, 0f)); return val; }, 10f, 0f); Rebuild(); popup.OpenPage(true); void Rebuild() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject item in entryRows) { if (!((Object)(object)item == (Object)null)) { REPOScrollViewElement component = item.GetComponent(); if ((Object)(object)component != (Object)null) { component.visibility = false; } Object.Destroy((Object)(object)item); } } entryRows.Clear(); IReadOnlyList readOnlyList; if (!worldMode) { readOnlyList = OffsetSeedDefaults.SeedTriggersFor(forType); } else { IReadOnlyList readOnlyList2 = Array.Empty(); readOnlyList = readOnlyList2; } IReadOnlyList readOnlyList3 = readOnlyList; HashSet seedSet = new HashSet(readOnlyList3); List list = working.Where((CosmeticOffsetEntry o) => !seedSet.Contains(o.TriggerType)).ToList(); list.Sort(CosmeticConditionFormat.Compare); int num = readOnlyList3.Count + list.Count; if ((Object)(object)noEntriesEl != (Object)null) { noEntriesEl.visibility = num == 0; } int insertAt; RectTransform scroller; int sib; if (num == 0) { popup.scrollView.UpdateElements(); } else { insertAt = noEntriesTr.GetSiblingIndex(); scroller = popup.menuScrollBox.scroller; sib = 0; foreach (Type t in readOnlyList3) { AddRow(t, working.All((CosmeticOffsetEntry o) => o.TriggerType != t)); } foreach (CosmeticOffsetEntry item2 in list) { AddRow(item2.TriggerType, isAuto: false); } popup.scrollView.UpdateElements(); onPreview?.Invoke(working); } void AddRow(Type trig, bool isAuto) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) bool fit = OffsetSeedDefaults.IsFitTrigger(trig); bool optIn = OffsetSeedDefaults.IsOptInTrigger(trig); CosmeticOffsetEntry cosmeticOffsetEntry = (isAuto ? null : working.FirstOrDefault((CosmeticOffsetEntry o) => o.TriggerType == trig)); bool off = (cosmeticOffsetEntry != null && IsIdentityFix(cosmeticOffsetEntry)) || (isAuto && optIn); string text = (off ? " (off)" : (isAuto ? " (auto)" : (fit ? " (custom)" : ""))); RectTransform val = CreateEntryRow((Transform)(object)scroller, (sib == 0) ? 15f : 0f); ((Transform)val).SetSiblingIndex(insertAt + sib); sib++; REPOLabel val2 = MenuAPI.CreateREPOLabel(CosmeticConditionFormat.Label(trig, worldMode) + text, (Transform)(object)val, new Vector2(-137f, 0f)); ((REPOElement)val2).rectTransform.sizeDelta = new Vector2(155f, 30f); ((TMP_Text)val2.labelTMP).rectTransform.sizeDelta = ((REPOElement)val2).rectTransform.sizeDelta; ((TMP_Text)val2.labelTMP).fontSize = 20f; ((TMP_Text)val2.labelTMP).enableAutoSizing = true; ((TMP_Text)val2.labelTMP).fontSizeMin = 12f; ((TMP_Text)val2.labelTMP).fontSizeMax = 20f; MenuAPI.CreateREPOButton("Edit", (Action)delegate { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) CosmeticOffsetEntry existing = working.FirstOrDefault((CosmeticOffsetEntry o) => o.TriggerType == trig); if (existing == null) { OffsetSeedDefaults.TryGetSeed(forType, trig, out existing); } Type? locked = (fit ? new Type?(trig) : ((Type?)null)); PopupUI.AfterMouseRelease((MonoBehaviour)(object)popup, delegate { CosmeticOffsetEntryPopup.Show(new OffsetEntryArgs { Existing = existing, Triggers = triggers, OnDone = delegate(CosmeticOffsetEntry? result) { if (result == null) { onPreview?.Invoke(working); } else { working.RemoveAll((CosmeticOffsetEntry o) => o.TriggerType == trig || o.TriggerType == result.TriggerType); working.Add(result); SortWorking(); Rebuild(); } }, OnPreview = delegate(CosmeticOffsetEntry? partial) { if (partial != null) { List list2 = (from e in working where e.TriggerType != trig select e.Clone()).ToList(); list2.Add(partial); onPreview?.Invoke(list2); } }, ParentPopupTransform = (parentPopupTransform ?? ((Component)popup).transform), WorldMode = worldMode, OnDeathHeadTrigger = onDeathHeadTrigger, LockedTrigger = locked }); }); }, (Transform)(object)val, new Vector2(11f, 0f)); MenuAPI.CreateREPOButton(off ? "Use" : (isAuto ? "Skip" : "Del"), (Action)delegate { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) working.RemoveAll((CosmeticOffsetEntry o) => o.TriggerType == trig); if (off && optIn) { if (OffsetSeedDefaults.TryGetSeed(forType, trig, out CosmeticOffsetEntry seed)) { working.Add(seed); } } else if (isAuto) { OffsetSeedDefaults.TryGetSeed(forType, trig, out CosmeticOffsetEntry seed2); working.Add(new CosmeticOffsetEntry { TriggerType = trig, LerpSpeed = (seed2?.LerpSpeed ?? 3f) }); } SortWorking(); Rebuild(); }, (Transform)(object)val, new Vector2(71f, 0f)); entryRows.Add(((Component)val).gameObject); } } void SortWorking() { working.Sort(CosmeticConditionFormat.Compare); } } private static bool IsIdentityFix(CosmeticOffsetEntry e) { if (e.PosX == 0f && e.PosY == 0f && e.PosZ == 0f && e.RotX == 0f && e.RotY == 0f && e.RotZ == 0f && e.ScaleX == 1f && e.ScaleY == 1f) { return e.ScaleZ == 1f; } return false; } private static RectTransform CreateEntryRow(Transform scroller, float topPadding = 0f) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject("Entry Row", new Type[1] { typeof(RectTransform) }).GetComponent(); component.sizeDelta = new Vector2(0f, 30f); ((Transform)component).SetParent(scroller, false); REPOScrollViewElement val = ((Component)component).gameObject.AddComponent(); val.topPadding = topPadding; return component; } static CosmeticOffsetPopup() { Type[] array = new Type[7]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); s_headMesh = (Type[])(object)array; s_bodyTopMesh = (Type[])(object)new Type[2] { (Type)37, (Type)38 }; Type[] array2 = new Type[4]; RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); s_bodyBotMesh = (Type[])(object)array2; Type[] array3 = new Type[5]; RuntimeHelpers.InitializeArray(array3, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); s_armRMesh = (Type[])(object)array3; Type[] array4 = new Type[5]; RuntimeHelpers.InitializeArray(array4, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); s_armLMesh = (Type[])(object)array4; Type[] array5 = new Type[5]; RuntimeHelpers.InitializeArray(array5, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); s_legRMesh = (Type[])(object)array5; Type[] array6 = new Type[5]; RuntimeHelpers.InitializeArray(array6, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); s_legLMesh = (Type[])(object)array6; OffsetTriggers = new Dictionary { [(CosmeticType)0] = s_headMesh, [(CosmeticType)18] = s_headMesh, [(CosmeticType)31] = s_headMesh, [(CosmeticType)32] = s_headMesh, [(CosmeticType)30] = s_headMesh, [(CosmeticType)17] = s_headMesh, [(CosmeticType)14] = s_headMesh, [(CosmeticType)15] = s_headMesh, [(CosmeticType)20] = s_bodyTopMesh, [(CosmeticType)21] = s_bodyBotMesh, [(CosmeticType)1] = s_armRMesh, [(CosmeticType)2] = s_armLMesh, [(CosmeticType)3] = s_legRMesh, [(CosmeticType)4] = s_legLMesh, [(CosmeticType)19] = s_legRMesh, [(CosmeticType)22] = s_legLMesh, [(CosmeticType)16] = s_bodyTopMesh, [(CosmeticType)23] = s_bodyBotMesh, [(CosmeticType)26] = s_armRMesh, [(CosmeticType)27] = s_armLMesh, [(CosmeticType)28] = s_legRMesh, [(CosmeticType)29] = s_legLMesh, [(CosmeticType)5] = s_headMesh, [(CosmeticType)6] = s_headMesh, [(CosmeticType)7] = s_bodyTopMesh, [(CosmeticType)8] = s_bodyBotMesh, [(CosmeticType)9] = s_armRMesh, [(CosmeticType)10] = s_armLMesh, [(CosmeticType)11] = s_legRMesh, [(CosmeticType)12] = s_legLMesh }; WorldOffsetTriggers = BuildWorldOffsetTriggers(); } } internal static class CosmeticOverridePopup { private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnRowH = 30f; private const float BtnTopGap = 10f; private const float BtnBackX = -137f; private const float BtnSaveX = 58f; private const float BtnResetX = 51f; private const float BtnDeleteIconX = -137f; private const float BtnExportX = -23f; private const float BtnConditionX = -137f; private const float BtnOffsetX = -137f; private const float BtnCrownX = -137f; private static readonly HashSet ImpactPoseTypes = new HashSet { (CosmeticType)0, (CosmeticType)17, (CosmeticType)20, (CosmeticType)32, (CosmeticType)30, (CosmeticType)18, (CosmeticType)8 }; private static readonly string[] RarityOptions = new string[1] { "Default" }.Concat(Enum.GetNames(typeof(Rarity))).ToArray(); private static readonly string[] MainOptions = Enum.GetNames(typeof(MainCosmeticCategory)); private static readonly string[] TriStateOptions = new string[3] { "Default", "Yes", "No" }; private static readonly string[] SwayOptions = new string[5] { "Default", "No", "Light", "Moderate", "Strong" }; private static readonly string[] EquipAnimOptions = new string[4] { "Default", "Fixed", "Normal", "Disabled" }; internal static readonly Dictionary SubOptions = new Dictionary { [MainCosmeticCategory.Head] = new OverrideCosmeticType[10] { OverrideCosmeticType.Hat, OverrideCosmeticType.Eyewear, OverrideCosmeticType.FaceTop, OverrideCosmeticType.FaceBottom, OverrideCosmeticType.HeadBottom, OverrideCosmeticType.Ears, OverrideCosmeticType.HeadTopMesh, OverrideCosmeticType.HeadBottomMesh, OverrideCosmeticType.EyeLidRightMesh, OverrideCosmeticType.EyeLidLeftMesh }, [MainCosmeticCategory.Body] = new OverrideCosmeticType[4] { OverrideCosmeticType.BodyTop, OverrideCosmeticType.BodyBottom, OverrideCosmeticType.BodyTopMesh, OverrideCosmeticType.BodyBottomMesh }, [MainCosmeticCategory.Arms] = new OverrideCosmeticType[4] { OverrideCosmeticType.ArmRight, OverrideCosmeticType.ArmLeft, OverrideCosmeticType.ArmRightMesh, OverrideCosmeticType.ArmLeftMesh }, [MainCosmeticCategory.Legs] = new OverrideCosmeticType[6] { OverrideCosmeticType.LegRight, OverrideCosmeticType.LegLeft, OverrideCosmeticType.FootRight, OverrideCosmeticType.FootLeft, OverrideCosmeticType.LegRightMesh, OverrideCosmeticType.LegLeftMesh }, [MainCosmeticCategory.World] = new OverrideCosmeticType[1] { OverrideCosmeticType.World } }; internal static readonly Dictionary SubLabels = new Dictionary { [OverrideCosmeticType.Hat] = "Hat", [OverrideCosmeticType.Eyewear] = "Eyewear", [OverrideCosmeticType.FaceTop] = "Face Upper", [OverrideCosmeticType.FaceBottom] = "Face Middle", [OverrideCosmeticType.HeadBottom] = "Face Lower", [OverrideCosmeticType.Ears] = "Ears", [OverrideCosmeticType.HeadTopMesh] = "Head Mesh", [OverrideCosmeticType.HeadBottomMesh] = "Chin Mesh", [OverrideCosmeticType.EyeLidRightMesh] = "Eyelid R Mesh", [OverrideCosmeticType.EyeLidLeftMesh] = "Eyelid L Mesh", [OverrideCosmeticType.BodyTop] = "Bodywear Top", [OverrideCosmeticType.BodyBottom] = "Bodywear Bottom", [OverrideCosmeticType.BodyTopMesh] = "Body Top Mesh", [OverrideCosmeticType.BodyBottomMesh] = "Body Bot Mesh", [OverrideCosmeticType.ArmRight] = "Armwear Right", [OverrideCosmeticType.ArmLeft] = "Armwear Left", [OverrideCosmeticType.ArmRightMesh] = "Arm R Mesh", [OverrideCosmeticType.ArmLeftMesh] = "Arm L Mesh", [OverrideCosmeticType.LegRight] = "Legwear Right", [OverrideCosmeticType.LegLeft] = "Legwear Left", [OverrideCosmeticType.FootRight] = "Footwear Right", [OverrideCosmeticType.FootLeft] = "Footwear Left", [OverrideCosmeticType.LegRightMesh] = "Leg R Mesh", [OverrideCosmeticType.LegLeftMesh] = "Leg L Mesh", [OverrideCosmeticType.World] = "World" }; internal static readonly Dictionary LabelToType = SubLabels.ToDictionary, string, OverrideCosmeticType>((KeyValuePair kvp) => kvp.Value, (KeyValuePair kvp) => kvp.Key); internal static void Show(CosmeticAsset asset) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowNow(asset); }); } private static void ShowNow(CosmeticAsset asset) { //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Expected O, but got Unknown //IL_0470: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Expected O, but got Unknown //IL_050a: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Expected O, but got Unknown //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Expected O, but got Unknown //IL_05be: Unknown result type (might be due to invalid IL or missing references) //IL_05d2: Expected O, but got Unknown //IL_0633: Unknown result type (might be due to invalid IL or missing references) //IL_0647: Expected O, but got Unknown //IL_06b2: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Expected O, but got Unknown //IL_06d3: Unknown result type (might be due to invalid IL or missing references) //IL_06e7: Expected O, but got Unknown //IL_06f4: Unknown result type (might be due to invalid IL or missing references) //IL_0708: Expected O, but got Unknown //IL_0715: Unknown result type (might be due to invalid IL or missing references) //IL_0729: Expected O, but got Unknown //IL_0798: Unknown result type (might be due to invalid IL or missing references) //IL_07ac: Expected O, but got Unknown //IL_0755: Unknown result type (might be due to invalid IL or missing references) //IL_0769: Expected O, but got Unknown //IL_081e: Unknown result type (might be due to invalid IL or missing references) //IL_0832: Expected O, but got Unknown //IL_083f: Unknown result type (might be due to invalid IL or missing references) //IL_0853: Expected O, but got Unknown //IL_08a3: Unknown result type (might be due to invalid IL or missing references) //IL_08b7: Expected O, but got Unknown //IL_08c4: Unknown result type (might be due to invalid IL or missing references) //IL_08d8: Expected O, but got Unknown //IL_0901: Unknown result type (might be due to invalid IL or missing references) //IL_0915: Expected O, but got Unknown //IL_086d: Unknown result type (might be due to invalid IL or missing references) //IL_0881: Expected O, but got Unknown //IL_07e8: Unknown result type (might be due to invalid IL or missing references) //IL_07fc: Expected O, but got Unknown //IL_094b: Unknown result type (might be due to invalid IL or missing references) //IL_095f: Expected O, but got Unknown //IL_0994: Unknown result type (might be due to invalid IL or missing references) //IL_09a8: Expected O, but got Unknown //IL_09b5: Unknown result type (might be due to invalid IL or missing references) //IL_09c9: Expected O, but got Unknown //IL_0a72: Unknown result type (might be due to invalid IL or missing references) //IL_0a86: Expected O, but got Unknown //IL_0a09: Unknown result type (might be due to invalid IL or missing references) //IL_0a1d: Expected O, but got Unknown //IL_0adb: Unknown result type (might be due to invalid IL or missing references) //IL_0aef: Expected O, but got Unknown //IL_0b41: Unknown result type (might be due to invalid IL or missing references) //IL_0b55: Expected O, but got Unknown //IL_0b71: Unknown result type (might be due to invalid IL or missing references) //IL_0b85: Expected O, but got Unknown //IL_0b9a: Unknown result type (might be due to invalid IL or missing references) //IL_0bae: Expected O, but got Unknown if (asset.assetId == MiniSemibotCosmetic.AssetId) { MiniSemibotOverridePopup.Show(asset); return; } bool hasOverride = CustomizerStore.HasOverride(asset); bool hasCachedIcon = IconCapture.HasCache(asset); string text = asset.assetName ?? ((Object)asset).name ?? asset.assetId; CustomizerStore.TryGet(asset.assetId, out CosmeticOverrideData existing); bool? pendingModded = existing?.IsModded; Rarity? pendingRarity = existing?.Rarity; MainCosmeticCategory pendingMain = CustomizerStore.GetCurrentMain(asset); OverrideCosmeticType pendingType = CustomizerStore.GetEffectiveType(asset); bool? pendingFixCollider = existing?.FixCollider; bool? pendingFixAnimation = existing?.FixAnimation; bool? pendingFixCrown = existing?.FixCrown; VanillaEquipAnimationMode? pendingEquipAnim = existing?.VanillaEquipAnimationMode; bool? pendingTintable = existing?.Tintable; bool? pendingCustomColors = existing?.EnableCustomColors; bool? pendingColorAnimations = existing?.EnableColorAnimations; bool? pendingIsolatedIcon = existing?.UseIsolatedIcon; bool? pendingUseFit = existing?.UseFitOffsets; SwayMode? pendingEnableSway = existing?.EnableSway; IEnumerable enumerable = existing?.CustomTypes; HashSet pendingCustomTypes = new HashSet(enumerable ?? Enumerable.Empty()); NativeCustomTypeImport.MergeIntoPending(asset, pendingCustomTypes); IEnumerable enumerable2 = existing?.Offsets; List pendingOffsets = new List(enumerable2 ?? Enumerable.Empty()); NativeOffsetImport.MergeIntoPending(asset, pendingOffsets); CosmeticCrownConfig pendingCrown = existing?.Crown?.Clone(); NativeCrownImport.MergeIntoPending(asset, ref pendingCrown); bool? pendingShowOnDeathHead = existing?.ShowOnDeathHead; DeathHeadFloorPose pendingFloorPose = existing?.FloorPose?.Clone(); CosmeticHideConfig pendingHide = existing?.HideConditions?.Clone() ?? new CosmeticHideConfig(); NativeHideImport.MergeIntoPending(asset, pendingHide); BridgeFavoritesManager.EnsureLoaded(); bool pendingBlacklist = BridgeBlacklist.Contains(asset.assetId); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage(text, false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); CosmeticOverridePreview preview = ((Component)popup).gameObject.AddComponent(); preview.Init(asset, popup); PopupUI.AttachGuards(popup); REPOSlider subSlider = null; REPOScrollViewElement shapeCondEl = null; REPOScrollViewElement worldLabelEl = null; REPOScrollViewElement worldShowSelfEl = null; REPOScrollViewElement worldAvoidEl = null; REPOScrollViewElement worldHideKartEl = null; REPOScrollViewElement worldSpringEl = null; REPOScrollViewElement crownEl = null; REPOScrollViewElement deathHeadEl = null; REPOScrollViewElement impactEl = null; REPOScrollViewElement fitEl = null; AddSectionLabel(popup, "Category", 15f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Main Category", "", (Action)delegate(string opt) { if (Enum.TryParse(opt, out var result) && result != pendingMain) { pendingMain = result; pendingType = SubOptions[result][0]; UpdateConditionalRows(); if (!((Object)(object)subSlider == (Object)null)) { REPOScrollViewElement component = ((Component)subSlider).GetComponent(); if (result == MainCosmeticCategory.World) { if ((Object)(object)component != (Object)null) { component.visibility = false; } } else { subSlider.stringOptions = GetSubLabels(result); subSlider.SetValue(0f, false); if ((Object)(object)component != (Object)null) { component.visibility = true; } } PreviewFull(); } } }, scrollView, MainOptions, pendingMain.ToString(), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown MainCosmeticCategory mainCosmeticCategory = ((pendingMain != MainCosmeticCategory.World) ? pendingMain : MainCosmeticCategory.Head); string[] subLabels = GetSubLabels(mainCosmeticCategory); string text2 = ((Array.IndexOf(SubOptions[mainCosmeticCategory], pendingType) >= 0 && SubLabels.ContainsKey(pendingType)) ? SubLabels[pendingType] : subLabels[0]); subSlider = MenuAPI.CreateREPOSlider("Sub Category", "", (Action)delegate(string opt) { if (LabelToType.TryGetValue(opt, out var value)) { pendingType = value; } UpdateConditionalRows(); PreviewFull(); }, scrollView, subLabels, text2, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)subSlider).transform; }, 0f, 0f); if (pendingMain == MainCosmeticCategory.World) { REPOSlider obj = subSlider; REPOScrollViewElement val = ((obj != null) ? ((Component)obj).GetComponent() : null); if ((Object)(object)val != (Object)null) { val.visibility = false; } } worldLabelEl = ((Component)AddSectionLabelRow(popup, "World", 10f)).GetComponent(); RectTransform showSelfRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009f: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Show To Self (In Game)", "", (Action)delegate(string opt) { WorldFollowPrefs.SetShowToSelf(asset.assetId, opt == "On"); }, scrollView, new string[2] { "Off", "On" }, WorldFollowPrefs.GetShowToSelf(asset.assetId) ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); RectTransform val3 = (RectTransform)((Component)val2).transform; RectTransform result = val3; showSelfRow = val3; return result; }, 10f, 0f); worldShowSelfEl = (((Object)(object)showSelfRow != (Object)null) ? ((Component)showSelfRow).GetComponent() : null); RectTransform avoidRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009f: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Avoid Walls", "", (Action)delegate(string opt) { WorldFollowPrefs.SetAvoidWalls(asset.assetId, opt == "On"); CustomizerSync.BroadcastAll(); }, scrollView, new string[2] { "Off", "On" }, WorldFollowPrefs.GetAvoidWalls(asset.assetId) ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); RectTransform val3 = (RectTransform)((Component)val2).transform; RectTransform result = val3; avoidRow = val3; return result; }, 10f, 0f); worldAvoidEl = (((Object)(object)avoidRow != (Object)null) ? ((Component)avoidRow).GetComponent() : null); RectTransform hideKartRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009f: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Hide on Kart", "", (Action)delegate(string opt) { WorldFollowPrefs.SetHideOnKart(asset.assetId, opt == "On"); CustomizerSync.BroadcastAll(); }, scrollView, new string[2] { "Off", "On" }, WorldFollowPrefs.GetHideOnKart(asset.assetId) ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); RectTransform val3 = (RectTransform)((Component)val2).transform; RectTransform result = val3; hideKartRow = val3; return result; }, 10f, 0f); worldHideKartEl = (((Object)(object)hideKartRow != (Object)null) ? ((Component)hideKartRow).GetComponent() : null); if (Plugin.EnableWorldFollowSpring.Value) { RectTransform springRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00cc: Expected O, but got Unknown Action action = delegate(string opt) { string assetId = asset.assetId; FollowSpringMode mode = ((opt == "Soft") ? FollowSpringMode.Soft : ((opt == "Bouncy") ? FollowSpringMode.Springy : FollowSpringMode.Off)); WorldFollowPrefs.SetSpring(assetId, mode); }; string[] array = new string[3] { "Off", "Soft", "Bouncy" }; REPOSlider val2 = MenuAPI.CreateREPOSlider("Follow Smoothing", "", action, scrollView, array, WorldFollowPrefs.GetSpring(asset.assetId) switch { FollowSpringMode.Soft => "Soft", FollowSpringMode.Springy => "Bouncy", _ => "Off", }, default(Vector2), "", "", (BarBehavior)0); RectTransform val3 = (RectTransform)((Component)val2).transform; RectTransform result = val3; springRow = val3; return result; }, 10f, 0f); worldSpringEl = (((Object)(object)springRow != (Object)null) ? ((Component)springRow).GetComponent() : null); } AddSectionLabel(popup, "Appearance", 10f); string borderHighlightLabel = (BridgeIds.IsBridgeAsset(asset) ? "Bridge Border Highlight" : "Modded Border Highlight"); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider(borderHighlightLabel, "", (Action)delegate(string opt) { pendingModded = TriStateToBool(opt); }, scrollView, TriStateOptions, BoolToTriState(pendingModded), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Rarity", "", (Action)delegate(string opt) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) pendingRarity = ((opt == "Default") ? ((Rarity?)null) : (Enum.TryParse(opt, out Rarity result) ? new Rarity?(result) : ((Rarity?)null))); }, scrollView, RarityOptions, RarityToOption(pendingRarity), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Allow Coloring", "", (Action)delegate(string opt) { pendingTintable = TriStateToBool(opt); }, scrollView, TriStateOptions, BoolToTriState(pendingTintable), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Allow Custom Color", "", (Action)delegate(string opt) { pendingCustomColors = TriStateToBool(opt); }, scrollView, TriStateOptions, BoolToTriState(pendingCustomColors), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); if (BridgeIds.IsBridgeAsset(asset) && !CustomizerStore.IsBridgeMeshSwitch(asset.assetId)) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Allow Animated Color", "", (Action)delegate(string opt) { pendingColorAnimations = TriStateToBool(opt); }, scrollView, TriStateOptions, BoolToTriState(pendingColorAnimations), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); } if (BridgeIds.IsBridgeAsset(asset)) { AddSectionLabel(popup, "Icon", 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Use Isolated Icon Render", "", (Action)delegate(string opt) { pendingIsolatedIcon = TriStateToBool(opt); }, scrollView, TriStateOptions, BoolToTriState(pendingIsolatedIcon), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); } if (BridgeIds.IsBridgeAsset(asset) && BridgeFavoritesManager.IsHidden(asset)) { AddSectionLabel(popup, "Blacklist", 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Add to Blacklist", "", (Action)delegate(string opt) { pendingBlacklist = opt == "On"; }, scrollView, new string[2] { "Off", "On" }, pendingBlacklist ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); } AddSectionLabel(popup, "Fixes", 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Remove Physics", "", (Action)delegate(string opt) { pendingFixCollider = TriStateToBool(opt); PreviewFull(); }, scrollView, TriStateOptions, BoolToTriState(pendingFixCollider), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Loop Animation", "", (Action)delegate(string opt) { pendingFixAnimation = TriStateToBool(opt); PreviewFull(); }, scrollView, TriStateOptions, BoolToTriState(pendingFixAnimation), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); if (!BridgeIds.IsBridgeAsset(asset)) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Fix Crown Error", "", (Action)delegate(string opt) { pendingFixCrown = TriStateToBool(opt); PreviewFull(); }, scrollView, TriStateOptions, BoolToTriState(pendingFixCrown), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); } AddSectionLabel(popup, "Behavior", 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Jiggle Physics", "", (Action)delegate(string opt) { pendingEnableSway = OptionToSwayMode(opt); preview.RefreshSway(pendingEnableSway); }, scrollView, SwayOptions, SwayModeToOption(pendingEnableSway), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0060: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Equip Animation", "", (Action)delegate(string opt) { pendingEquipAnim = EquipAnimToValue(opt); PreviewFull(); }, scrollView, EquipAnimOptions, EquipAnimToOption(pendingEquipAnim), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); AddSectionLabel(popup, "Advanced", 10f); RectTransform fitRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0067: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Vanilla Position Fixes", "", (Action)delegate(string opt) { pendingUseFit = TriStateToBool(opt); PreviewFull(); }, scrollView, TriStateOptions, BoolToTriState(pendingUseFit), default(Vector2), "", "", (BarBehavior)0); RectTransform val3 = (RectTransform)((Component)val2).transform; RectTransform result = val3; fitRow = val3; return result; }, 10f, 0f); fitEl = (((Object)(object)fitRow != (Object)null) ? ((Component)fitRow).GetComponent() : null); RectTransform shapeCondRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Shape Conditions →", (Action)delegate { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_001f: Unknown result type (might be due to invalid IL or missing references) CosmeticType item = CustomizerStore.MapOverrideToVanilla(pendingType).cosmeticType; if (CosmeticConditionsPopup.HasConditions(item)) { CosmeticConditionsPopup.Show(pendingCustomTypes, item, delegate { preview.RefreshCustomTypes(pendingCustomTypes, pendingOffsets); }, ((Component)popup).transform); } }, (Transform)(object)val2, new Vector2(-137f, 0f)); return shapeCondRow = val2; }, 10f, 0f); shapeCondEl = (((Object)(object)shapeCondRow != (Object)null) ? ((Component)shapeCondRow).GetComponent() : null); UpdateShapeCondRow(); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Special Position Fixes →", (Action)delegate { //IL_000c: 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_001e: Unknown result type (might be due to invalid IL or missing references) var (forType, worldMode) = CustomizerStore.MapOverrideToVanilla(pendingType); CosmeticOffsetPopup.Show(pendingOffsets, forType, delegate(List offsets) { preview.RefreshOffsets(offsets); }, ((Component)popup).transform, worldMode); }, (Transform)(object)val2, new Vector2(-137f, 0f)); return val2; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Hide Conditions →", (Action)delegate { //IL_000c: 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_001e: Unknown result type (might be due to invalid IL or missing references) var (cosmeticType, worldMode) = CustomizerStore.MapOverrideToVanilla(pendingType); CosmeticHidePopup.Show(pendingHide, cosmeticType, PreviewFull, ((Component)popup).transform, worldMode); }, (Transform)(object)val2, new Vector2(-137f, 0f)); return val2; }, 10f, 0f); bool impactDeathMode; if (BridgeIds.IsBridgeAsset(asset)) { impactDeathMode = false; RectTransform impactRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Impact Pose →", (Action)delegate { DeathHeadFloorPosePopup.Show(pendingFloorPose, ShowImpactPreview, delegate(DeathHeadFloorPose fp) { EndImpactPreview(); pendingFloorPose = fp; PreviewFull(); }, EndImpactPreview, ((Component)popup).transform); }, (Transform)(object)val2, new Vector2(-137f, 0f)); return impactRow = val2; }, 10f, 0f); impactEl = (((Object)(object)impactRow != (Object)null) ? ((Component)impactRow).GetComponent() : null); } RectTransform crownRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Crown Settings →", (Action)delegate { //IL_0070: Unknown result type (might be due to invalid IL or missing references) CrownForceVisibleGuard crownGuard = null; GameObject val3 = preview.FindPreviewCosmeticGo(); if ((Object)(object)val3 != (Object)null && (Object)(object)preview.PreviewPc?.playerCrown != (Object)null) { crownGuard = CrownForceVisibleGuard.Attach(preview.PreviewPc.playerCrown, val3); } CosmeticCrownPopup.Show(pendingCrown, asset.type, delegate(CosmeticCrownConfig result) { pendingCrown = result; CleanupGuard(); }, delegate { pendingCrown = null; CleanupGuard(); preview.RefreshCrown(null); }, delegate(CosmeticCrownConfig? config) { preview.RefreshCrown(config); }, onCancel: CleanupGuard, parentPopupTransform: ((Component)popup).transform); void CleanupGuard() { if ((Object)(object)crownGuard != (Object)null) { Object.Destroy((Object)(object)crownGuard); crownGuard = null; } } }, (Transform)(object)val2, new Vector2(-137f, 0f)); return crownRow = val2; }, 10f, 0f); crownEl = (((Object)(object)crownRow != (Object)null) ? ((Component)crownRow).GetComponent() : null); RectTransform deathHeadRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Death Head →", (Action)delegate { CosmeticOffsetEntry existing2 = pendingOffsets.FirstOrDefault((CosmeticOffsetEntry o) => (int)o.TriggerType == 2); CosmeticOffsetEntryPopup.Show(new OffsetEntryArgs { Existing = existing2, Triggers = null, OnDone = delegate(CosmeticOffsetEntry? result) { preview.ExitDeathHeadMode(); if (result != null) { RemoveDeathHeadOffset(); pendingOffsets.Add(result); preview.RefreshOffsets(pendingOffsets); } }, OnPreview = delegate(CosmeticOffsetEntry? partial) { preview.UpdateDeathHeadOffset(partial); }, ParentPopupTransform = ((Component)popup).transform, OnDeathHeadTrigger = delegate(bool enter) { if (enter) { preview.EnterDeathHeadMode(preview.FindPreviewCosmeticGo(), pendingCrown != null, existing2); preview.SetDeathHeadConfiguredCosmeticVisible(pendingShowOnDeathHead != false); } else { preview.ExitDeathHeadMode(); } }, LockedTrigger = (Type)2, OnClear = delegate { preview.ExitDeathHeadMode(); RemoveDeathHeadOffset(); preview.RefreshOffsets(pendingOffsets); }, ShowOnDeathHead = (pendingShowOnDeathHead != false), OnShowOnDeathHeadPreview = delegate(bool show) { preview.SetDeathHeadConfiguredCosmeticVisible(show); }, OnShowOnDeathHeadCommit = delegate(bool show) { pendingShowOnDeathHead = (show ? ((bool?)null) : new bool?(false)); } }); }, (Transform)(object)val2, new Vector2(-137f, 0f)); return deathHeadRow = val2; }, 10f, 0f); deathHeadEl = (((Object)(object)deathHeadRow != (Object)null) ? ((Component)deathHeadRow).GetComponent() : null); UpdateConditionalRows(); AddSectionLabel(popup, "Actions", 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Back", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Save", (Action)delegate { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 (CosmeticType cosmeticType, bool isWorld) tuple = CustomizerStore.MapOverrideToVanilla(pendingType); CosmeticType item = tuple.cosmeticType; bool item2 = tuple.isWorld; bool flag = pendingCrown != null; bool flag2 = flag; if (flag2) { bool flag3 = (((int)item == 0 || (int)item == 5) ? true : false); flag2 = !flag3; } bool dropCrown = flag2; IReadOnlyList validOffsets = CosmeticTriggerCatalog.ValidOffsetTriggers(item); IReadOnlyList validConds = CosmeticTriggerCatalog.ValidCustomTypes(item); bool deathHeadSupported = DeathHeadPrefabProvider.SupportedTypes.Contains(item); List dropOffsets = (item2 ? new List() : pendingOffsets.Where((CosmeticOffsetEntry o) => !validOffsets.Contains(o.TriggerType) && !((int)o.TriggerType == 2 && deathHeadSupported)).ToList()); List dropConds = pendingCustomTypes.Where((Type c) => !validConds.Contains(c)).ToList(); if (dropCrown || dropOffsets.Count > 0 || dropConds.Count > 0) { ShowPruneConfirm(dropOffsets.Count, dropConds.Count, dropCrown, delegate { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (dropCrown) { pendingCrown = null; } foreach (CosmeticOffsetEntry item7 in dropOffsets) { pendingOffsets.Remove(item7); } foreach (Type item8 in dropConds) { pendingCustomTypes.Remove(item8); } DoSave(); }); } else { DoSave(); } }, (Transform)(object)val2, new Vector2(58f, 0f)); return val2; }, 0f, 0f); if (hasCachedIcon || hasOverride) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); if (hasCachedIcon) { MenuAPI.CreateREPOButton("Delete Icon", (Action)delegate { IconCapture.DeleteCache(asset); CosmeticHoverPatch.SuppressWhileHovered(asset); IconCapture.RefreshVisibleButtons(asset); popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(-137f, 0f)); } if (hasOverride) { MenuAPI.CreateREPOButton("Export Settings", (Action)delegate { CustomizerIO.ExportSingle(asset.assetId); }, (Transform)(object)val2, new Vector2(-23f, 0f)); } return val2; }, 10f, 0f); } if (hasOverride) { popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Reset", (Action)delegate { //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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) CosmeticType type = asset.type; bool flag = HhhCosmeticLoader.IsWorldAsset(asset); (bool fixCollider, bool fixAnimation) effectiveFixes = CustomizerStore.GetEffectiveFixes(asset.assetId); bool item = effectiveFixes.fixCollider; bool item2 = effectiveFixes.fixAnimation; VanillaEquipAnimationMode effectiveEquipAnimationMode = CustomizerStore.GetEffectiveEquipAnimationMode(asset.assetId); bool tintable = asset.tintable; Rarity rarity = asset.rarity; bool flag2 = CustomizerStore.IsModdedForAsset(asset) || CustomizerStore.IsNonBridgeModdedForAsset(asset); CustomizerStore.Reset(asset); (bool fixCollider, bool fixAnimation) effectiveFixes2 = CustomizerStore.GetEffectiveFixes(asset.assetId); bool item3 = effectiveFixes2.fixCollider; bool item4 = effectiveFixes2.fixAnimation; VanillaEquipAnimationMode effectiveEquipAnimationMode2 = CustomizerStore.GetEffectiveEquipAnimationMode(asset.assetId); bool flag3 = tintable != asset.tintable; if (!(type != asset.type || flag != HhhCosmeticLoader.IsWorldAsset(asset) || item != item3 || item2 != item4 || effectiveEquipAnimationMode != effectiveEquipAnimationMode2 || flag3) && existing?.Crown == null) { CosmeticOverrideData cosmeticOverrideData = existing; if (cosmeticOverrideData == null || cosmeticOverrideData.FixCrown != true) { goto IL_0148; } } MoreHeadCosmeticMountPatch.ReinstantiateCosmetic(asset); goto IL_0148; IL_0148: if (rarity != asset.rarity || type != asset.type || flag != HhhCosmeticLoader.IsWorldAsset(asset) || flag2 != (CustomizerStore.IsModdedForAsset(asset) || CustomizerStore.IsNonBridgeModdedForAsset(asset))) { RefreshMenu(); } popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(51f, 0f)); return val2; }, 10f, 0f); } popup.OpenPage(false); CosmeticOverrideData BuildPending() { return new CosmeticOverrideData { Type = pendingType, Offsets = ((pendingOffsets.Count > 0) ? new List(pendingOffsets) : null), CustomTypes = ((pendingCustomTypes.Count > 0) ? new List(pendingCustomTypes) : null), Crown = pendingCrown, EnableSway = pendingEnableSway, FixCollider = pendingFixCollider, FixAnimation = pendingFixAnimation, FixCrown = pendingFixCrown, VanillaEquipAnimationMode = pendingEquipAnim, ShowOnDeathHead = pendingShowOnDeathHead, FloorPose = pendingFloorPose, HideConditions = (pendingHide.HasAny ? pendingHide : null), EnableCustomColors = pendingCustomColors, EnableColorAnimations = pendingColorAnimations, UseIsolatedIcon = pendingIsolatedIcon, UseFitOffsets = pendingUseFit }; } CosmeticOffsetEntry? DeathHeadOffset() { return pendingOffsets.FirstOrDefault((CosmeticOffsetEntry o) => (int)o.TriggerType == 2); } void DoSave() { //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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) CosmeticType type = asset.type; bool flag = HhhCosmeticLoader.IsWorldAsset(asset); (bool fixCollider, bool fixAnimation) effectiveFixes = CustomizerStore.GetEffectiveFixes(asset.assetId); bool item = effectiveFixes.fixCollider; bool item2 = effectiveFixes.fixAnimation; VanillaEquipAnimationMode effectiveEquipAnimationMode = CustomizerStore.GetEffectiveEquipAnimationMode(asset.assetId); bool tintable = asset.tintable; CosmeticCrownConfig a = existing?.Crown; bool flag2 = (existing?.FixCrown == true) ?? false; Rarity rarity = asset.rarity; bool flag3 = CustomizerStore.IsModdedForAsset(asset) || CustomizerStore.IsNonBridgeModdedForAsset(asset); CustomizerStore.SetAndApply(asset, new CosmeticOverrideData { IsModded = pendingModded, Rarity = pendingRarity, Type = pendingType, FixCollider = pendingFixCollider, FixAnimation = pendingFixAnimation, VanillaEquipAnimationMode = pendingEquipAnim, Tintable = pendingTintable, EnableSway = pendingEnableSway, CustomTypes = ((pendingCustomTypes != null) ? new List(pendingCustomTypes) : null), Offsets = pendingOffsets, Crown = pendingCrown, ShowOnDeathHead = pendingShowOnDeathHead, FloorPose = pendingFloorPose, FixCrown = pendingFixCrown, HideConditions = pendingHide, EnableCustomColors = pendingCustomColors, EnableColorAnimations = pendingColorAnimations, UseIsolatedIcon = pendingIsolatedIcon, UseFitOffsets = pendingUseFit }); if (pendingBlacklist != BridgeBlacklist.Contains(asset.assetId)) { BridgeBlacklist.SetBlacklisted(asset.assetId, asset.assetName ?? ((Object)asset).name, pendingBlacklist); } if (pendingTintable == false) { PerCosmeticColors.ClearForAsset(asset.assetId); PerCosmeticColorNetworkSync.BroadcastAll(); } if (CustomizerStore.IsBridgeMeshSwitch(asset.assetId) && PerCosmeticColors.ClearAllAnimationForAsset(asset.assetId)) { PerCosmeticColorNetworkSync.BroadcastAll(); } (CosmeticType cosmeticType, bool isWorld) tuple = CustomizerStore.MapOverrideToVanilla(pendingType); CosmeticType item3 = tuple.cosmeticType; bool item4 = tuple.isWorld; (bool fixCollider, bool fixAnimation) effectiveFixes2 = CustomizerStore.GetEffectiveFixes(asset.assetId); bool item5 = effectiveFixes2.fixCollider; bool item6 = effectiveFixes2.fixAnimation; VanillaEquipAnimationMode effectiveEquipAnimationMode2 = CustomizerStore.GetEffectiveEquipAnimationMode(asset.assetId); bool flag4 = tintable != asset.tintable; if (type != item3 || flag != item4 || item != item5 || item2 != item6 || effectiveEquipAnimationMode != effectiveEquipAnimationMode2 || flag4 || !CosmeticCrownConfig.ValueEquals(a, pendingCrown, 0f) || flag2 != (pendingFixCrown == true)) { MoreHeadCosmeticMountPatch.ReinstantiateCosmetic(asset); } else if (pendingTintable == false) { RuntimeConfigApplier.ReapplyLocalCosmeticColors(); } if (rarity != asset.rarity || type != item3 || flag != item4 || flag3 != (CustomizerStore.IsModdedForAsset(asset) || CustomizerStore.IsNonBridgeModdedForAsset(asset))) { RefreshMenu(); } popup.ClosePage(false); } void EndImpactPreview() { if (impactDeathMode) { preview.StopDeathHeadFloorAnimation(); preview.ExitDeathHeadMode(); impactDeathMode = false; } else { preview.StopImpactPosePreview(); } } void PreviewFull() { preview.RefreshFull(BuildPending()); } void RemoveDeathHeadOffset() { pendingOffsets.RemoveAll((CosmeticOffsetEntry o) => (int)o.TriggerType == 2); } static void SetVis(REPOScrollViewElement? el, bool v) { if ((Object)(object)el != (Object)null) { el.visibility = v; } } void ShowImpactPreview(DeathHeadFloorPose fp) { if (fp.ReactWhenDead && !fp.ReactWhenAlive) { if (!impactDeathMode) { preview.StopImpactPosePreview(); preview.EnterDeathHeadMode(preview.FindPreviewCosmeticGo(), pendingCrown != null, DeathHeadOffset()); impactDeathMode = true; } preview.SetDeathHeadFloorAnimation(fp); } else { if (impactDeathMode) { preview.StopDeathHeadFloorAnimation(); preview.ExitDeathHeadMode(); impactDeathMode = false; } preview.PlayImpactPosePreview(fp); } } void UpdateConditionalRows() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) UpdateShapeCondRow(); (CosmeticType cosmeticType, bool isWorld) tuple = CustomizerStore.MapOverrideToVanilla(pendingType); CosmeticType item = tuple.cosmeticType; bool flag = tuple.isWorld || pendingMain == MainCosmeticCategory.World; SetVis(worldLabelEl, flag); SetVis(worldShowSelfEl, flag); SetVis(worldAvoidEl, flag); SetVis(worldHideKartEl, flag); SetVis(worldSpringEl, flag); SetVis(crownEl, !flag && (pendingType == OverrideCosmeticType.Hat || pendingType == OverrideCosmeticType.HeadTopMesh)); SetVis(deathHeadEl, !flag && DeathHeadPrefabProvider.SupportedTypes.Contains(item)); SetVis(impactEl, !flag && ImpactPoseTypes.Contains(item)); SetVis(fitEl, !flag && BridgeIds.IsBridgeAsset(asset) && OffsetSeedDefaults.HasDefaults(item)); } void UpdateShapeCondRow() { //IL_001b: 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_0030: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)shapeCondEl == (Object)null)) { var (type, flag) = CustomizerStore.MapOverrideToVanilla(pendingType); shapeCondEl.visibility = !flag && CosmeticConditionsPopup.HasConditions(type); } } } private static bool? TriStateToBool(string opt) { if (!(opt == "Yes")) { if (opt == "No") { return false; } return null; } return true; } private static string BoolToTriState(bool? v) { if (v.HasValue) { if (v == true) { return "Yes"; } return "No"; } return "Default"; } private static string SwayModeToOption(SwayMode? mode) { return mode switch { SwayMode.None => "No", SwayMode.Light => "Light", SwayMode.Moderate => "Moderate", SwayMode.Strong => "Strong", _ => "Default", }; } private static SwayMode? OptionToSwayMode(string opt) { return opt switch { "No" => SwayMode.None, "Light" => SwayMode.Light, "Moderate" => SwayMode.Moderate, "Strong" => SwayMode.Strong, _ => null, }; } private static string RarityToOption(Rarity? rarity) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return (rarity.HasValue ? ((object)rarity.GetValueOrDefault()/*cast due to .constrained prefix*/).ToString() : null) ?? "Default"; } private static string EquipAnimToOption(VanillaEquipAnimationMode? mode) { return mode switch { VanillaEquipAnimationMode.Fixed => "Fixed", VanillaEquipAnimationMode.Normal => "Normal", VanillaEquipAnimationMode.Disabled => "Disabled", _ => "Default", }; } private static VanillaEquipAnimationMode? EquipAnimToValue(string opt) { return opt switch { "Fixed" => VanillaEquipAnimationMode.Fixed, "Normal" => VanillaEquipAnimationMode.Normal, "Disabled" => VanillaEquipAnimationMode.Disabled, _ => null, }; } private static string[] GetSubLabels(MainCosmeticCategory main) { return Array.ConvertAll(SubOptions[main], (OverrideCosmeticType t) => SubLabels[t]); } private static void AddSectionLabel(REPOPopupPage popup, string text, float topPadding) { AddSectionLabelRow(popup, text, topPadding); } private static RectTransform AddSectionLabelRow(REPOPopupPage popup, string text, float topPadding) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown RectTransform rt = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0073: Expected O, but got Unknown REPOLabel val = MenuAPI.CreateREPOLabel(text, scrollView, default(Vector2)); ((TMP_Text)val.labelTMP).fontSize = 18f; ((TMP_Text)val.labelTMP).alpha = 0.85f; ((TMP_Text)val.labelTMP).alignment = (TextAlignmentOptions)513; ((REPOElement)val).rectTransform.sizeDelta = new Vector2(200f, 24f); RectTransform val2 = (RectTransform)((Component)val).transform; RectTransform result = val2; rt = val2; return result; }, topPadding, 0f); return rt; } private static void RefreshMenu() { MenuPageCosmetics? activePage = CosmeticsMenuState.ActivePage; if (activePage != null) { activePage.RefreshScrollContent(); } } private static void ShowPruneConfirm(int offsets, int conds, bool crown, Action onConfirm) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown List list = new List(); if (offsets > 0) { list.Add($"{offsets} offset(s)"); } if (conds > 0) { list.Add($"{conds} condition(s)"); } if (crown) { list.Add("the crown"); } string msg = "Changing type removes:\n" + string.Join(", ", list); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Change type?", false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, null, inputGuard: false); popup.AddElementToScrollView((ScrollViewBuilderDelegate)((Transform scrollView) => (RectTransform)((Component)MenuAPI.CreateREPOLabel(msg, scrollView, default(Vector2))).transform), 15f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Confirm", (Action)delegate { popup.ClosePage(false); onConfirm(); }, (Transform)(object)val, new Vector2(58f, 0f)); return val; }, 10f, 0f); popup.OpenPage(true); } } internal sealed class CosmeticOverridePreview : MonoBehaviour { private const float PreviewX = 0f; private const float PreviewY = 0f; private const float PreviewWidth = 184f; private const float PreviewHeight = 345f; private const float PreviewLabelHeight = 30f; private const float PreviewLabelGapY = 6f; private CosmeticAsset? _asset; private PlayerAvatarMenu? _avatarMenu; private PlayerAvatarVisuals? _visuals; private readonly DeathHeadPreviewInstance _deathHead = new DeathHeadPreviewInstance(); private bool _deathHeadActive; private bool _normalCrownWasActive; private bool _normalCrownComponentWasEnabled; private Coroutine? _spawnAnim; private PlayerAvatarMenu? _cosmeticsMenuAvatar; private bool _cosmeticsMenuAvatarWasIconMaker; private Coroutine? _floorAnim; private bool _floorBaseCaptured; private DeathHeadFloorPose _floorTarget = new DeathHeadFloorPose(); private Vector3 _floorBasePos; private Vector3 _floorBaseEuler; private Vector3 _floorBaseScale; private const float FloorSquishHoldTime = 1f; internal PlayerCosmetics? PreviewPc { get; private set; } internal void Init(CosmeticAsset asset, REPOPopupPage popup) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) _asset = asset; _cosmeticsMenuAvatar = PlayerAvatarMenu.instance; if ((Object)(object)_cosmeticsMenuAvatar != (Object)null) { _cosmeticsMenuAvatarWasIconMaker = _cosmeticsMenuAvatar.iconMakerAvatar; _cosmeticsMenuAvatar.iconMakerAvatar = true; } REPOAvatarPreview val; try { val = MenuAPI.CreateREPOAvatarPreview(((Component)popup).transform, new Vector2(0f, 0f), false, (Color?)null); } catch (Exception ex) { BceConsole.LogWarning("CosmeticOverridePreview: failed to create — " + ex.Message); if ((Object)(object)_cosmeticsMenuAvatar != (Object)null) { _cosmeticsMenuAvatar.iconMakerAvatar = _cosmeticsMenuAvatarWasIconMaker; } return; } _avatarMenu = ((Component)val.playerAvatarVisuals).GetComponentInParent(); if ((Object)(object)_avatarMenu == (Object)null) { BceConsole.LogWarning("CosmeticOverridePreview: PlayerAvatarMenu not found"); return; } _visuals = val.playerAvatarVisuals; PreviewPc = ((Component)_avatarMenu).GetComponentInChildren(); if ((Object)(object)PreviewPc == (Object)null) { BceConsole.LogWarning("CosmeticOverridePreview: PlayerCosmetics not found"); return; } AddPreviewLabel(val, popup.headerTMP); RefreshFull(null); } internal void EnterDeathHeadMode(GameObject? configuredCosmetic, bool crownConfigured, CosmeticOffsetEntry? offset) { if ((Object)(object)_visuals == (Object)null || !_deathHead.TryEnsure(((Component)_visuals).transform, PreviewPc)) { return; } List<(GameObject, CosmeticAsset)> deathHeadCosmeticGos = GetDeathHeadCosmeticGos(); if ((Object)(object)configuredCosmetic != (Object)null && (Object)(object)_asset != (Object)null) { bool flag = false; foreach (var item in deathHeadCosmeticGos) { if ((Object)(object)item.Item1 == (Object)(object)configuredCosmetic) { flag = true; break; } } if (!flag) { deathHeadCosmeticGos.Add((configuredCosmetic, _asset)); } } _deathHead.MountCosmetics(deathHeadCosmeticGos, configuredCosmetic); _deathHead.ApplyOffset(offset); _deathHead.SetCrownVisible(crownConfigured); SetNormalCrownVisible(visible: false); _deathHead.Show(show: true); SetAvatarBodyVisible(visible: false); _deathHeadActive = true; if (_spawnAnim != null) { ((MonoBehaviour)this).StopCoroutine(_spawnAnim); } _spawnAnim = ((MonoBehaviour)this).StartCoroutine(SpawnAnimation()); } internal void UpdateDeathHeadOffset(CosmeticOffsetEntry? offset) { if (_deathHeadActive) { _deathHead.ApplyOffset(offset); } } internal void SetDeathHeadConfiguredCosmeticVisible(bool visible) { if (_deathHeadActive) { _deathHead.SetConfiguredCosmeticVisible(visible); } } internal void SetDeathHeadFloorAnimation(DeathHeadFloorPose pose) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) Transform configuredMountTransform = _deathHead.ConfiguredMountTransform; if (_deathHeadActive && !((Object)(object)configuredMountTransform == (Object)null)) { _floorTarget = pose; if (!_floorBaseCaptured) { _floorBasePos = configuredMountTransform.localPosition; _floorBaseEuler = configuredMountTransform.localEulerAngles; _floorBaseScale = configuredMountTransform.localScale; _floorBaseCaptured = true; } if (_floorAnim != null) { ((MonoBehaviour)this).StopCoroutine(_floorAnim); } configuredMountTransform.localPosition = _floorBasePos; configuredMountTransform.localEulerAngles = _floorBaseEuler; configuredMountTransform.localScale = _floorBaseScale; _floorAnim = ((MonoBehaviour)this).StartCoroutine(FloorAnimOneShot(configuredMountTransform)); } } internal void PlayImpactPosePreview(DeathHeadFloorPose pose) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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) GameObject val = FindPreviewCosmeticGo(); Transform val2 = (((Object)(object)val != (Object)null) ? val.transform : null); if (!((Object)(object)val2 == (Object)null)) { _floorTarget = pose; if (!_floorBaseCaptured) { _floorBasePos = val2.localPosition; _floorBaseEuler = val2.localEulerAngles; _floorBaseScale = val2.localScale; _floorBaseCaptured = true; } if (_floorAnim != null) { ((MonoBehaviour)this).StopCoroutine(_floorAnim); } val2.localPosition = _floorBasePos; val2.localEulerAngles = _floorBaseEuler; val2.localScale = _floorBaseScale; _floorAnim = ((MonoBehaviour)this).StartCoroutine(FloorAnimOneShot(val2)); } } internal void StopImpactPosePreview() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (_floorAnim != null) { ((MonoBehaviour)this).StopCoroutine(_floorAnim); _floorAnim = null; } GameObject val = FindPreviewCosmeticGo(); Transform val2 = (((Object)(object)val != (Object)null) ? val.transform : null); if ((Object)(object)val2 != (Object)null && _floorBaseCaptured) { val2.localPosition = _floorBasePos; val2.localEulerAngles = _floorBaseEuler; val2.localScale = _floorBaseScale; } _floorBaseCaptured = false; } internal void StopDeathHeadFloorAnimation() { //IL_003a: 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_0052: Unknown result type (might be due to invalid IL or missing references) if (_floorAnim != null) { ((MonoBehaviour)this).StopCoroutine(_floorAnim); _floorAnim = null; } Transform configuredMountTransform = _deathHead.ConfiguredMountTransform; if ((Object)(object)configuredMountTransform != (Object)null && _floorBaseCaptured) { configuredMountTransform.localPosition = _floorBasePos; configuredMountTransform.localEulerAngles = _floorBaseEuler; configuredMountTransform.localScale = _floorBaseScale; } _floorBaseCaptured = false; } private IEnumerator FloorAnimOneShot(Transform t) { float phase = 0f; while (phase < 1f) { if ((Object)(object)t == (Object)null) { yield break; } phase = Mathf.MoveTowards(phase, 1f, Time.deltaTime * Mathf.Max(0.1f, _floorTarget.LerpSpeed)); ApplyFloorPhase(t, phase); yield return null; } float hold = Time.time + 1f; while (Time.time < hold) { yield return null; } while (phase > 0f) { if ((Object)(object)t == (Object)null) { yield break; } phase = Mathf.MoveTowards(phase, 0f, Time.deltaTime * Mathf.Max(0.1f, _floorTarget.LerpSpeed)); ApplyFloorPhase(t, phase); yield return null; } if ((Object)(object)t != (Object)null) { t.localPosition = _floorBasePos; t.localEulerAngles = _floorBaseEuler; t.localScale = _floorBaseScale; } _floorAnim = null; } private void ApplyFloorPhase(Transform t, float phase) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) t.localPosition = Vector3.Lerp(_floorBasePos, new Vector3(_floorTarget.PosX, _floorTarget.PosY, _floorTarget.PosZ), phase); t.localRotation = Quaternion.Slerp(Quaternion.Euler(_floorBaseEuler), Quaternion.Euler(_floorTarget.RotX, _floorTarget.RotY, _floorTarget.RotZ), phase); t.localScale = Vector3.Lerp(_floorBaseScale, new Vector3(_floorTarget.ScaleX, _floorTarget.ScaleY, _floorTarget.ScaleZ), phase); } internal void ExitDeathHeadMode() { if (_deathHeadActive) { StopDeathHeadFloorAnimation(); if (_spawnAnim != null) { ((MonoBehaviour)this).StopCoroutine(_spawnAnim); _spawnAnim = null; } _deathHead.Show(show: false); SetNormalCrownVisible(visible: true); SetAvatarBodyVisible(visible: true); _deathHeadActive = false; } } private void SetAvatarBodyVisible(bool visible) { if ((Object)(object)_visuals?.meshParent != (Object)null && _visuals.meshParent.activeSelf != visible) { _visuals.meshParent.SetActive(visible); } } private void SetNormalCrownVisible(bool visible) { PlayerCrown val = PreviewPc?.playerCrown; if ((Object)(object)val == (Object)null) { return; } if (!visible) { _normalCrownComponentWasEnabled = ((Behaviour)val).enabled; ((Behaviour)val).enabled = false; if ((Object)(object)val.crownMesh != (Object)null) { _normalCrownWasActive = ((Component)val.crownMesh).gameObject.activeSelf; ((Component)val.crownMesh).gameObject.SetActive(false); } } else { if ((Object)(object)val.crownMesh != (Object)null) { ((Component)val.crownMesh).gameObject.SetActive(_normalCrownWasActive); } ((Behaviour)val).enabled = _normalCrownComponentWasEnabled; } } private List<(GameObject go, CosmeticAsset asset)> GetDeathHeadCosmeticGos() { List<(GameObject, CosmeticAsset)> list = new List<(GameObject, CosmeticAsset)>(); if ((Object)(object)PreviewPc == (Object)null) { return list; } List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(PreviewPc); if (equippedCosmetics != null) { foreach (Cosmetic item in equippedCosmetics) { if (!((Object)(object)item == (Object)null)) { CosmeticAsset cosmeticAsset = MoreHeadCosmeticMountPatch.GetCosmeticAsset(item); if (IsSupported(cosmeticAsset)) { list.Add((((Component)item).gameObject, cosmeticAsset)); } } } } return list; } private static bool IsSupported(CosmeticAsset? asset) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)asset != (Object)null) { return DeathHeadPrefabProvider.SupportedTypes.Contains(asset.type); } return false; } private IEnumerator SpawnAnimation() { AnimationCurve curve = (((Object)(object)AssetManager.instance != (Object)null) ? AssetManager.instance.animationCurvePopOut : null); float t = 0f; while (t < 1f) { t += Time.deltaTime / 0.35f; float scaleFactor = ((curve != null) ? curve.Evaluate(Mathf.Clamp01(t)) : Mathf.Clamp01(t)); _deathHead.SetScaleFactor(scaleFactor); yield return null; } _deathHead.SetScaleFactor(1f); _spawnAnim = null; } private static void AddPreviewLabel(REPOAvatarPreview avatarPreview, TextMeshProUGUI src) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Preview Label", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)avatarPreview).transform, false); val.transform.localRotation = Quaternion.Inverse(((Component)avatarPreview).transform.localRotation); RectTransform val2 = (RectTransform)val.transform; val2.pivot = new Vector2(0.5f, 0f); Vector2 anchorMin = (val2.anchorMax = Vector2.zero); val2.anchorMin = anchorMin; val2.sizeDelta = new Vector2(184f, 30f); ((Transform)val2).localPosition = new Vector3(-92f, 351f, 0f); TextMeshProUGUI val3 = val.AddComponent(); ((TMP_Text)val3).font = ((TMP_Text)src).font; ((TMP_Text)val3).fontSize = ((TMP_Text)src).fontSize; ((TMP_Text)val3).fontStyle = ((TMP_Text)src).fontStyle; ((Graphic)val3).color = ((Graphic)src).color; ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((TMP_Text)val3).text = "Preview"; } private void OnDestroy() { _deathHead.Destroy(); PlayerAvatarMenu.instance = _cosmeticsMenuAvatar; if ((Object)(object)_cosmeticsMenuAvatar != (Object)null) { _cosmeticsMenuAvatar.iconMakerAvatar = _cosmeticsMenuAvatarWasIconMaker; MetaManager instance = MetaManager.instance; if ((Object)(object)instance != (Object)null) { instance.CosmeticPreviewSet(false); instance.CosmeticPlayerUpdateLocal(false, false); } } } internal void RefreshFull(CosmeticOverrideData? pendingData) { //IL_00b1: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)PreviewPc == (Object)null || (Object)(object)_asset == (Object)null) { return; } MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } CosmeticType type = _asset.type; if (pendingData != null && pendingData.Type.HasValue) { CosmeticType item = CustomizerStore.MapOverrideToVanilla(pendingData.Type.Value).cosmeticType; _asset.type = item; } try { OverridePreviewContext.Set(PreviewPc, _asset.assetId, pendingData); PreviewPc.SetupCosmetics(false, true, instance.cosmeticEquipped); PreviewPc.SetupColors(false, (int[])null); } finally { _asset.type = type; OverridePreviewContext.Clear(); } } internal void RefreshCrown(CosmeticCrownConfig? crown) { foreach (GameObject item in FindAllPreviewCosmeticGos()) { MoreHeadCosmeticMountPatch.ApplyCrownConfig(item, crown); } if ((Object)(object)PreviewPc?.playerCrown != (Object)null) { PreviewPc.playerCrown.UpdateTarget(); if ((Object)(object)PreviewPc.playerCrown.crownMesh != (Object)null) { ((Component)PreviewPc.playerCrown.crownMesh).gameObject.SetActive(crown != null); } } } internal void RefreshOffsets(List offsets) { if ((Object)(object)PreviewPc == (Object)null || (Object)(object)_asset == (Object)null) { return; } bool flag = false; foreach (GameObject item in FindAllPreviewCosmeticGos()) { MoreHeadCosmeticMountPatch.ResetAndDestroyAll(item.transform, item.GetComponents()); MoreHeadCosmeticMountPatch.InjectOffsetConditions(item, _asset, PreviewPc, (offsets.Count > 0) ? offsets : null); flag = true; } if (flag) { MoreHeadCosmeticMountPatch.InvokeConditionsSetup(PreviewPc); } } internal void RefreshCustomTypes(IEnumerable types, List? offsets) { if ((Object)(object)PreviewPc == (Object)null || (Object)(object)_asset == (Object)null) { return; } List list = new List(types); bool flag = false; foreach (GameObject item in FindAllPreviewCosmeticGos()) { BridgeCustomTypesBroadcaster[] components = item.GetComponents(); foreach (BridgeCustomTypesBroadcaster bridgeCustomTypesBroadcaster in components) { Object.DestroyImmediate((Object)(object)bridgeCustomTypesBroadcaster); } MoreHeadCosmeticMountPatch.ResetAndDestroyAll(item.transform, item.GetComponents()); MoreHeadCosmeticMountPatch.InjectOffsetConditions(item, _asset, PreviewPc, (offsets != null && offsets.Count > 0) ? offsets : null, (list.Count > 0) ? list : null, NativeCustomTypeImport.HasNativeAnnounceList(_asset)); flag = true; } if (flag) { MoreHeadCosmeticMountPatch.InvokeConditionsSetup(PreviewPc); } } internal void RefreshSway(SwayMode? sway) { if ((Object)(object)PreviewPc == (Object)null) { return; } bool hasValue = sway.HasValue; bool flag; if (sway.HasValue) { SwayMode valueOrDefault = sway.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 2u) { flag = true; goto IL_0036; } } flag = false; goto IL_0036; IL_0036: bool flag2 = flag; float intensityFactor = CosmeticSwayHelper.SwayModeToFactor(sway); foreach (GameObject item in FindAllPreviewCosmeticGos()) { CosmeticSprings[] componentsInChildren = item.GetComponentsInChildren(true); CosmeticSprings[] array = componentsInChildren; foreach (CosmeticSprings val in array) { ((Behaviour)val).enabled = !hasValue; } BridgeSwaySpring[] components = item.GetComponents(); foreach (BridgeSwaySpring bridgeSwaySpring in components) { Object.DestroyImmediate((Object)(object)bridgeSwaySpring); } bool flag3 = hasValue || componentsInChildren.Length == 0; if (flag2 && flag3) { Cosmetic component = item.GetComponent(); if ((Object)(object)component != (Object)null) { BridgeSwaySpring bridgeSwaySpring2 = item.AddComponent(); bridgeSwaySpring2.Init(component, intensityFactor); } } } } internal GameObject? FindPreviewCosmeticGo() { if ((Object)(object)PreviewPc == (Object)null || (Object)(object)_asset == (Object)null) { return null; } List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(PreviewPc); if (equippedCosmetics == null) { return null; } foreach (Cosmetic item in equippedCosmetics) { if (!((Object)(object)item == (Object)null) && (Object)(object)MoreHeadCosmeticMountPatch.GetCosmeticAsset(item) == (Object)(object)_asset) { return ((Component)item).gameObject; } } return null; } private List FindAllPreviewCosmeticGos() { List list = new List(); if ((Object)(object)PreviewPc == (Object)null || (Object)(object)_asset == (Object)null) { return list; } List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(PreviewPc); if (equippedCosmetics != null) { foreach (Cosmetic item in equippedCosmetics) { if (!((Object)(object)item == (Object)null) && (Object)(object)MoreHeadCosmeticMountPatch.GetCosmeticAsset(item) == (Object)(object)_asset) { list.Add(((Component)item).gameObject); } } } return list; } } public enum VanillaEquipAnimationMode { Disabled, Normal, Fixed } internal enum SwayMode { None, Light, Moderate, Strong } internal enum OverrideCosmeticType { Hat, HeadBottom, Ears, Eyewear, FaceTop, FaceBottom, HeadTopMesh, HeadBottomMesh, EyeLidRightMesh, EyeLidLeftMesh, BodyTop, BodyBottom, BodyTopOverlay, BodyBottomOverlay, BodyTopMesh, BodyBottomMesh, ArmRight, ArmLeft, ArmRightOverlay, ArmLeftOverlay, ArmRightMesh, ArmLeftMesh, LegRight, LegLeft, FootRight, FootLeft, LegRightOverlay, LegLeftOverlay, LegRightMesh, LegLeftMesh, World } internal enum MainCosmeticCategory { Head, Body, Arms, Legs, World } internal sealed class CosmeticOverrideData { [JsonProperty("isModded")] public bool? IsModded { get; set; } [JsonProperty("rarity")] [JsonConverter(typeof(StringEnumConverter))] public Rarity? Rarity { get; set; } [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter))] public OverrideCosmeticType? Type { get; set; } [JsonProperty("fixCollider")] public bool? FixCollider { get; set; } [JsonProperty("fixAnimation")] public bool? FixAnimation { get; set; } [JsonProperty("fixCrown")] public bool? FixCrown { get; set; } [JsonProperty("vanillaEquipAnimationMode")] [JsonConverter(typeof(StringEnumConverter))] public VanillaEquipAnimationMode? VanillaEquipAnimationMode { get; set; } [JsonProperty("tintable")] public bool? Tintable { get; set; } [JsonProperty("enableSway")] [JsonConverter(typeof(NullableSwayModeConverter))] public SwayMode? EnableSway { get; set; } [JsonProperty("customTypes")] public List? CustomTypes { get; set; } [JsonProperty("offsets")] public List? Offsets { get; set; } [JsonProperty("crown")] public CosmeticCrownConfig? Crown { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? ShowOnDeathHead { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public DeathHeadFloorPose? FloorPose { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public CosmeticHideConfig? HideConditions { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? EnableCustomColors { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? EnableColorAnimations { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? UseIsolatedIcon { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? UseFitOffsets { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] [JsonConverter(typeof(StringEnumConverter))] public Rarity? OriginalRarity { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] [JsonConverter(typeof(StringEnumConverter))] public CosmeticType? OriginalType { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? OriginalTintable { get; set; } } internal sealed class CosmeticCrownConfig { [JsonProperty("posX")] public float PosX { get; set; } [JsonProperty("posY")] public float PosY { get; set; } = 0.35f; [JsonProperty("posZ")] public float PosZ { get; set; } = 0.25f; [JsonProperty("rotX")] public float RotX { get; set; } [JsonProperty("rotY")] public float RotY { get; set; } [JsonProperty("rotZ")] public float RotZ { get; set; } [JsonProperty("scaleX")] public float ScaleX { get; set; } = 1f; [JsonProperty("scaleY")] public float ScaleY { get; set; } = 1f; [JsonProperty("scaleZ")] public float ScaleZ { get; set; } = 1f; [JsonProperty("priority")] public int Priority { get; set; } [JsonProperty("disableSpring")] public bool DisableSpring { get; set; } internal CosmeticCrownConfig Clone() { return (CosmeticCrownConfig)MemberwiseClone(); } internal static bool ValueEquals(CosmeticCrownConfig? a, CosmeticCrownConfig? b, float eps) { if (a == null && b == null) { return true; } if (a == null || b == null) { return false; } if (Near(a.PosX, b.PosX, eps) && Near(a.PosY, b.PosY, eps) && Near(a.PosZ, b.PosZ, eps) && Near(a.RotX, b.RotX, eps) && Near(a.RotY, b.RotY, eps) && Near(a.RotZ, b.RotZ, eps) && Near(a.ScaleX, b.ScaleX, eps) && Near(a.ScaleY, b.ScaleY, eps) && Near(a.ScaleZ, b.ScaleZ, eps) && a.Priority == b.Priority) { return a.DisableSpring == b.DisableSpring; } return false; } private static bool Near(float x, float y, float eps) { if (!(eps <= 0f)) { return Math.Abs(x - y) <= eps; } return x == y; } } internal sealed class DeathHeadFloorPose { [JsonProperty("reactAlive")] public bool ReactWhenAlive { get; set; } [JsonProperty("reactDead")] public bool ReactWhenDead { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? Enabled { get; set; } [JsonProperty("posX")] public float PosX { get; set; } [JsonProperty("posY")] public float PosY { get; set; } [JsonProperty("posZ")] public float PosZ { get; set; } [JsonProperty("rotX")] public float RotX { get; set; } [JsonProperty("rotY")] public float RotY { get; set; } [JsonProperty("rotZ")] public float RotZ { get; set; } [JsonProperty("scaleX")] public float ScaleX { get; set; } = 1f; [JsonProperty("scaleY")] public float ScaleY { get; set; } = 1f; [JsonProperty("scaleZ")] public float ScaleZ { get; set; } = 1f; [JsonProperty("lerp")] public float LerpSpeed { get; set; } = 7f; internal bool HasAny { get { if (!ReactWhenAlive && !ReactWhenDead) { return Enabled == true; } return true; } } internal void MigrateLegacy() { if (Enabled == true && !ReactWhenAlive && !ReactWhenDead) { ReactWhenDead = true; } Enabled = null; } internal DeathHeadFloorPose Clone() { return (DeathHeadFloorPose)MemberwiseClone(); } } internal sealed class CosmeticHideConfig { [JsonProperty(/*Could not decode attribute arguments.*/)] [JsonConverter(typeof(EnumListConverter))] public List? WhenTypes { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] [JsonConverter(typeof(EnumListConverter))] public List? WhenConditions { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] [JsonConverter(typeof(EnumListConverter))] public List? WhenPoses { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public List? WhenCosmetics { get; set; } internal bool HasAny { get { List whenTypes = WhenTypes; if (whenTypes == null || whenTypes.Count <= 0) { List whenConditions = WhenConditions; if (whenConditions == null || whenConditions.Count <= 0) { List whenPoses = WhenPoses; if (whenPoses == null || whenPoses.Count <= 0) { List whenCosmetics = WhenCosmetics; if (whenCosmetics != null) { return whenCosmetics.Count > 0; } return false; } } } return true; } } internal CosmeticHideConfig Clone() { return new CosmeticHideConfig { WhenTypes = ((WhenTypes != null) ? new List(WhenTypes) : null), WhenConditions = ((WhenConditions != null) ? new List(WhenConditions) : null), WhenPoses = ((WhenPoses != null) ? new List(WhenPoses) : null), WhenCosmetics = ((WhenCosmetics != null) ? new List(WhenCosmetics) : null) }; } } internal sealed class EnumListConverter : JsonConverter where TEnum : struct, Enum { public override bool CanConvert(Type objectType) { return typeof(List).IsAssignableFrom(objectType); } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { writer.WriteStartArray(); if (value is List list) { foreach (TEnum item in list) { writer.WriteValue(item.ToString()); } } writer.WriteEndArray(); } public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 List list = new List(); if ((int)reader.TokenType == 2) { while (reader.Read() && (int)reader.TokenType != 14) { if (reader.Value is string value && Enum.TryParse(value, out var result)) { list.Add(result); } } } return list; } } internal sealed class CosmeticOffsetEntry { [JsonIgnore] internal bool Seeded; [JsonProperty("triggerType")] [JsonConverter(typeof(StringEnumConverter))] public Type TriggerType { get; set; } [JsonProperty("posX")] public float PosX { get; set; } [JsonProperty("posY")] public float PosY { get; set; } [JsonProperty("posZ")] public float PosZ { get; set; } [JsonProperty("rotX")] public float RotX { get; set; } [JsonProperty("rotY")] public float RotY { get; set; } [JsonProperty("rotZ")] public float RotZ { get; set; } [JsonProperty("scaleX")] public float ScaleX { get; set; } = 1f; [JsonProperty("scaleY")] public float ScaleY { get; set; } = 1f; [JsonProperty("scaleZ")] public float ScaleZ { get; set; } = 1f; [JsonProperty("lerpSpeed")] public float LerpSpeed { get; set; } = 3f; internal CosmeticOffsetEntry Clone() { return (CosmeticOffsetEntry)MemberwiseClone(); } } internal static class CosmeticSettingsPopup { private readonly struct PreviewRow { internal readonly string FieldText; internal readonly string StatusText; internal readonly Color StatusColor; internal PreviewRow(string field, string status, Color color) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) FieldText = field; StatusText = status; StatusColor = color; } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func, string> <>9__62_0; public static Func, CosmeticOverrideData> <>9__62_1; public static Func<(int actorNumber, string nickName, int overrideCount, bool isSteamFriend), string> <>9__65_10; public static Func<(int actorNumber, string nickName, int overrideCount, bool isSteamFriend), string> <>9__65_11; public static Func<(int actorNumber, string nickName, int overrideCount, bool isSteamFriend), int> <>9__65_12; public static Func <>9__65_15; public static Func <>9__65_17; public static Func <>9__68_0; public static ScrollViewBuilderDelegate <>9__75_0; internal string b__62_0(KeyValuePair kvp) { return kvp.Key; } internal CosmeticOverrideData b__62_1(KeyValuePair kvp) { return kvp.Value.ToOverrideData(); } internal string b__65_10((int actorNumber, string nickName, int overrideCount, bool isSteamFriend) p) { if (!p.isSteamFriend) { return $"{p.nickName} ({p.overrideCount})"; } return $"★ {p.nickName} ({p.overrideCount})"; } internal string b__65_11((int actorNumber, string nickName, int overrideCount, bool isSteamFriend) p) { if (!p.isSteamFriend) { return $"{p.nickName} ({p.overrideCount})"; } return $"★ {p.nickName} ({p.overrideCount})"; } internal int b__65_12((int actorNumber, string nickName, int overrideCount, bool isSteamFriend) p) { return p.actorNumber; } internal bool b__65_15(string id) { return (Object)(object)FindAsset(id) != (Object)null; } internal string b__65_17(string id) { return FindAsset(id)?.assetName ?? id; } internal string b__68_0(string t) { return "[" + t + "]"; } internal RectTransform b__75_0(Transform sv) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown REPOLabel val = MenuAPI.CreateREPOLabel("(no override data)", sv, default(Vector2)); return (RectTransform)((Component)val).transform; } } private const float FloatEps = 0.0001f; private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnTopGap = 10f; private const float BtnRowH = 30f; private const float BtnBackX = -137f; private const float BtnSaveX = 56f; private const float BtnRefreshX = -63f; private const float BtnImportAllX = 25f; private const float ItemLabelX = -40f; private const float ItemLabelY = 5f; private const float ItemLabelDisabledX = -55f; private const float ItemFontSize = 18f; private const float ItemDisabledAlpha = 0.35f; private const float PopupSpacing = 5f; private const float TagsX = 40f; private const float TagsFontSize = 10f; private const float PreviewFieldX = 5f; private const float PreviewFontSize = 15f; private const string OptionAll = "All"; private const string HeaderCosmeticSettings = "Sync/Copy\nCosmetic Settings"; private const string HeaderOverwriteFormat = "Overwrite {0} override(s)?"; private const string LabelNoOverrideData = "(no override data)"; private const string LabelMoreItemsFormat = "...and {0} more"; private const string BtnCancelText = "Cancel"; private const string BtnConfirmText = "Confirm"; private const string BtnImportText = "Import"; private const string BtnCloseText = "Close"; private const string BtnRefreshText = "Refresh"; private const string BtnImportAllText = "Import All"; private const string StatusNew = "NEW"; private const string StatusSame = "= same"; private const string StatusDiffFmt = "≠ yours: {0}"; private const string StatusDiffPlain = "≠ yours"; private const string StatusReset = "reset"; private const string StatusRemove = "REMOVED"; private static readonly Color ColNew = new Color(0.65f, 1f, 0.65f); private static readonly Color ColSame = new Color(0.5f, 0.5f, 0.5f); private static readonly Color ColDiff = new Color(1f, 0.62f, 0.35f); private static readonly Color ColReset = new Color(0.6f, 0.8f, 1f); private static readonly Color ColRemove = new Color(1f, 0.4f, 0.4f); private static Type? _moddedType; private static FieldInfo? _cosmeticEquippedField; private const int TagsMaxVisible = 3; private static bool Approx(float a, float b) { return Math.Abs(a - b) <= 0.0001f; } private static bool OffsetsEqual(List? a, List? b) { int num = a?.Count ?? 0; int num2 = b?.Count ?? 0; if (num != num2) { return false; } if (num == 0) { return true; } bool[] array = new bool[num2]; foreach (CosmeticOffsetEntry item in a) { bool flag = false; for (int i = 0; i < num2; i++) { if (!array[i] && OffsetEntryEqual(item, b[i])) { flag = (array[i] = true); break; } } if (!flag) { return false; } } return true; } private static bool OffsetEntryEqual(CosmeticOffsetEntry x, CosmeticOffsetEntry y) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (x.TriggerType == y.TriggerType && Approx(x.PosX, y.PosX) && Approx(x.PosY, y.PosY) && Approx(x.PosZ, y.PosZ) && Approx(x.RotX, y.RotX) && Approx(x.RotY, y.RotY) && Approx(x.RotZ, y.RotZ) && Approx(x.ScaleX, y.ScaleX) && Approx(x.ScaleY, y.ScaleY) && Approx(x.ScaleZ, y.ScaleZ)) { return Approx(x.LerpSpeed, y.LerpSpeed); } return false; } private static bool EnumSetEqual(List? a, List? b) where T : struct, Enum { int num = a?.Count ?? 0; int num2 = b?.Count ?? 0; if (num != num2) { return false; } if (num == 0) { return true; } return new HashSet(a).SetEquals(b); } private static bool FloorPoseEqual(DeathHeadFloorPose a, DeathHeadFloorPose b) { bool flag = a.ReactWhenDead || a.Enabled == true; bool flag2 = b.ReactWhenDead || b.Enabled == true; if (a.ReactWhenAlive == b.ReactWhenAlive && flag == flag2 && Approx(a.PosX, b.PosX) && Approx(a.PosY, b.PosY) && Approx(a.PosZ, b.PosZ) && Approx(a.RotX, b.RotX) && Approx(a.RotY, b.RotY) && Approx(a.RotZ, b.RotZ) && Approx(a.ScaleX, b.ScaleX) && Approx(a.ScaleY, b.ScaleY) && Approx(a.ScaleZ, b.ScaleZ)) { return Approx(a.LerpSpeed, b.LerpSpeed); } return false; } private static bool HideEqual(CosmeticHideConfig a, CosmeticHideConfig b) { if (EnumSetEqual(a.WhenTypes, b.WhenTypes) && EnumSetEqual(a.WhenConditions, b.WhenConditions) && EnumSetEqual(a.WhenPoses, b.WhenPoses)) { return StringSetEqual(a.WhenCosmetics, b.WhenCosmetics); } return false; } private static bool StringSetEqual(List? a, List? b) { int num = a?.Count ?? 0; int num2 = b?.Count ?? 0; if (num != num2) { return false; } if (num == 0) { return true; } return new HashSet(a).SetEquals(b); } private static int HideRuleCount(CosmeticHideConfig h) { return (h.WhenTypes?.Count ?? 0) + (h.WhenConditions?.Count ?? 0) + (h.WhenPoses?.Count ?? 0) + (h.WhenCosmetics?.Count ?? 0); } private static void EnsureReflection() { if (!(_moddedType != null)) { _moddedType = AccessTools.TypeByName("REPOLib.Objects.PlayerCosmeticsModded"); _cosmeticEquippedField = ((_moddedType != null) ? AccessTools.Field(_moddedType, "cosmeticEquipped") : null); } } private static List GetRemoteEquipped(int actorNumber) { EnsureReflection(); if (_moddedType == null || _cosmeticEquippedField == null) { return new List(); } PlayerCosmetics[] array = Object.FindObjectsOfType(); foreach (PlayerCosmetics val in array) { PhotonView photonView = val.photonView; if ((Object)(object)photonView == (Object)null) { continue; } Player owner = photonView.Owner; if (owner != null && owner.ActorNumber == actorNumber) { Component component = ((Component)val).GetComponent(_moddedType); if (!((Object)(object)component == (Object)null)) { return (_cosmeticEquippedField.GetValue(component) as List) ?? new List(); } } } return new List(); } private static CosmeticAsset? FindAsset(string assetId) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return null; } return instance.cosmeticAssets.Find((CosmeticAsset a) => (Object)(object)a != (Object)null && a.assetId == assetId); } private static string DisplayName(string assetId) { CosmeticAsset val = FindAsset(assetId); object obj; if (string.IsNullOrEmpty(val?.assetName)) { obj = ((val != null) ? ((Object)val).name : null); if (obj == null) { return assetId; } } else { obj = val.assetName; } return (string)obj; } private static MainCosmeticCategory? GetEffectiveMain(string assetId, BridgeSyncPayload? d) { if (d != null && d.Type.HasValue) { return CustomizerStore.GetMainForType(d.Type.Value); } CosmeticAsset val = FindAsset(assetId); if (!((Object)(object)val != (Object)null)) { return null; } return CustomizerStore.GetCurrentMain(val); } private static OverrideCosmeticType? GetEffectiveType(string assetId, BridgeSyncPayload? d) { if (d != null && d.Type.HasValue) { return d.Type.Value; } CosmeticAsset val = FindAsset(assetId); if (!((Object)(object)val != (Object)null)) { return null; } return CustomizerStore.GetEffectiveType(val); } private static OverrideCosmeticType? OriginalTypeOf(string assetId) { CosmeticAsset val = FindAsset(assetId); if (!((Object)(object)val != (Object)null)) { return null; } return CustomizerStore.GetOriginalType(val); } private static string[] GetSubOptions(MainCosmeticCategory main) { OverrideCosmeticType[] array = CosmeticOverridePopup.SubOptions[main]; string[] array2 = new string[array.Length + 1]; array2[0] = "All"; for (int i = 0; i < array.Length; i++) { array2[i + 1] = CosmeticOverridePopup.SubLabels[array[i]]; } return array2; } private static bool MatchesFilter(string assetId, BridgeSyncPayload? d, MainCosmeticCategory? category, OverrideCosmeticType? subCategory) { if (!category.HasValue) { return true; } MainCosmeticCategory? effectiveMain = GetEffectiveMain(assetId, d); if (!effectiveMain.HasValue) { return false; } if (effectiveMain.Value != category.Value) { return false; } if (!subCategory.HasValue) { return true; } return GetEffectiveType(assetId, d) == subCategory; } private static Dictionary FilterImportable(Dictionary data, MainCosmeticCategory? category, OverrideCosmeticType? subCategory) { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair datum in data) { if ((Object)(object)FindAsset(datum.Key) != (Object)null && MatchesFilter(datum.Key, datum.Value, category, subCategory) && HasImportableContent(datum.Key, datum.Value)) { dictionary[datum.Key] = datum.Value; } } return dictionary; } private static RectTransform CreateCosmeticRow(Transform scroller, float topPadding = 0f) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject("Cosmetic Row", new Type[1] { typeof(RectTransform) }).GetComponent(); component.sizeDelta = new Vector2(0f, 30f); ((Transform)component).SetParent(scroller, false); REPOScrollViewElement val = ((Component)component).gameObject.AddComponent(); val.topPadding = topPadding; return component; } private static void TryImportWithConflicts(Dictionary batch, REPOPopupPage parentPopup, Action refresh) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) List list = new List(); string text = ColorUtility.ToHtmlStringRGB(ColRemove); foreach (KeyValuePair item in batch) { CosmeticOverrideData data; bool flag = CustomizerStore.TryGet(item.Key, out data); bool flag2 = WorldFollowPrefs.GetAvoidWalls(item.Key) || WorldFollowPrefs.GetHideOnKart(item.Key); if (flag || flag2) { string text2 = DisplayName(item.Key); List list2 = LostFieldNames(item.Key, item.Value, data); if (list2.Count > 4) { list2 = list2.Take(4).Append("…").ToList(); } list.Add((list2.Count == 0) ? text2 : (text2 + " − " + string.Join(", ", list2) + "")); } } Dictionary asOverrideData = batch.ToDictionary, string, CosmeticOverrideData>((KeyValuePair kvp) => kvp.Key, (KeyValuePair kvp) => kvp.Value.ToOverrideData()); if (list.Count == 0) { DoImport(); } else { ShowConflictPopup(list, parentPopup, DoImport); } void DoImport() { foreach (KeyValuePair item2 in batch) { WorldFollowPrefs.SetAvoidWalls(item2.Key, item2.Value.AvoidWalls == true); WorldFollowPrefs.SetHideOnKart(item2.Key, item2.Value.HideOnKart == true); } CustomizerStore.ImportBatch(asOverrideData); refresh(); } } private static void ShowConflictPopup(List conflictNames, REPOPopupPage parentPopup, Action onConfirm) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_00b2: Expected O, but got Unknown string text = $"Overwrite {conflictNames.Count} override(s)?"; REPOPopupPage popup = MenuAPI.CreateREPOPopupPage(text, false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, ((Component)parentPopup).transform); int num = 0; foreach (string conflictName in conflictNames) { if (num >= 8) { break; } string captured = conflictName; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown REPOLabel val = MenuAPI.CreateREPOLabel(captured, sv, default(Vector2)); return (RectTransform)((Component)val).transform; }, (num == 0) ? 15f : 2f, 0f); num++; } if (conflictNames.Count > 8) { int remaining = conflictNames.Count - 8; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0031: Expected O, but got Unknown REPOLabel val = MenuAPI.CreateREPOLabel($"...and {remaining} more", sv, default(Vector2)); return (RectTransform)((Component)val).transform; }, 2f, 0f); } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0036: 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) RectTransform val = PopupUI.MakeRow(sv); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Confirm", (Action)delegate { popup.ClosePage(false); onConfirm(); }, (Transform)(object)val, new Vector2(56f, 0f)); return val; }, 10f, 0f); popup.OpenPage(true); } internal static void Show() { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, ShowNow); } private static void ShowNow() { //IL_00b8: 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_00fa: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown List<(int, string, int, bool)> remotePlayersWithData = CustomizerSync.GetRemotePlayersWithData(); if (remotePlayersWithData.Count == 0) { return; } int currentActor = remotePlayersWithData[0].Item1; MainCosmeticCategory? currentCategory = null; OverrideCosmeticType? currentSubcategory = null; string[] playerOptions = BuildPlayerOptions(remotePlayersWithData); Dictionary actorByOption = BuildActorByOption(remotePlayersWithData); REPOSlider playerSlider = null; REPOSlider subSlider = null; REPOScrollViewElement noEntriesEl = null; Transform noEntriesTr = null; List cosmeticRows = new List(); REPOButton refreshBtn = null; REPOButton importAllBtn = null; bool anyImportable = false; Action dataChangedHandler = null; REPOPopupPage popup = null; popup = MenuAPI.CreateREPOPopupPage("Sync/Copy\nCosmetic Settings", false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, null, inputGuard: false); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown playerSlider = MenuAPI.CreateREPOSlider("Player", "", (Action)delegate(string opt) { if (actorByOption.TryGetValue(opt, out var value)) { currentActor = value; } Rebuild(); }, scrollView, playerOptions, playerOptions[0], default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)playerSlider).transform; }, 15f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown REPOSlider val2 = MenuAPI.CreateREPOSlider("Category", "", (Action)delegate(string opt) { currentCategory = ((opt == "All") ? ((MainCosmeticCategory?)null) : new MainCosmeticCategory?(Enum.Parse(opt))); currentSubcategory = null; if ((Object)(object)subSlider != (Object)null) { REPOScrollViewElement component = ((Component)subSlider).GetComponent(); if (!currentCategory.HasValue || currentCategory == MainCosmeticCategory.World) { if ((Object)(object)component != (Object)null) { component.visibility = false; } } else { subSlider.stringOptions = GetSubOptions(currentCategory.Value); subSlider.SetValue(0f, false); if ((Object)(object)component != (Object)null) { component.visibility = true; } } } Rebuild(); }, scrollView, new string[1] { "All" }.Concat(Enum.GetNames(typeof(MainCosmeticCategory))).ToArray(), "All", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val2).transform; }, 0f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0040: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown subSlider = MenuAPI.CreateREPOSlider("Sub Category", "", (Action)delegate(string opt) { currentSubcategory = ((opt == "All") ? ((OverrideCosmeticType?)null) : (CosmeticOverridePopup.LabelToType.TryGetValue(opt, out var value) ? new OverrideCosmeticType?(value) : ((OverrideCosmeticType?)null))); Rebuild(); }, scrollView, new string[1] { "All" }, "All", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)subSlider).transform; }, 0f, 0f); REPOSlider obj = subSlider; REPOScrollViewElement val = ((obj != null) ? ((Component)obj).GetComponent() : null); if ((Object)(object)val != (Object)null) { val.visibility = false; } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown REPOLabel val2 = MenuAPI.CreateREPOLabel("(no override data)", scrollView, default(Vector2)); noEntriesTr = ((Component)val2).transform; return (RectTransform)((Component)val2).transform; }, 10f, 0f); noEntriesEl = ((Component)noEntriesTr).GetComponent(); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Close", (Action)delegate { CustomizerSync.OnRemoteDataChanged -= dataChangedHandler; popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(-137f, 0f)); refreshBtn = MenuAPI.CreateREPOButton("Refresh", (Action)delegate { RefreshPlayerOptions(); if ((Object)(object)popup != (Object)null) { ((Component)refreshBtn).gameObject.SetActive(false); Rebuild(); } }, (Transform)(object)val2, new Vector2(-63f, 0f)); ((Component)refreshBtn).gameObject.SetActive(false); importAllBtn = MenuAPI.CreateREPOButton("Import All", (Action)delegate { Dictionary remotePlayerData = CustomizerSync.GetRemotePlayerData(currentActor); if (remotePlayerData != null && remotePlayerData.Count != 0) { Dictionary dictionary = FilterImportable(remotePlayerData, currentCategory, currentSubcategory); if (dictionary.Count != 0) { TryImportWithConflicts(dictionary, popup, Rebuild); } } }, (Transform)(object)val2, new Vector2(25f, 0f)); ((Component)importAllBtn).gameObject.SetActive(anyImportable); return val2; }, 10f, 0f); dataChangedHandler = delegate { if ((Object)(object)popup == (Object)null) { CustomizerSync.OnRemoteDataChanged -= dataChangedHandler; } else if ((Object)(object)refreshBtn != (Object)null) { ((Component)refreshBtn).gameObject.SetActive(true); } }; CustomizerSync.OnRemoteDataChanged += dataChangedHandler; Rebuild(); popup.OpenPage(false); static Dictionary BuildActorByOption(List<(int actorNumber, string nickName, int overrideCount, bool isSteamFriend)> list) { return list.ToDictionary<(int, string, int, bool), string, int>(((int actorNumber, string nickName, int overrideCount, bool isSteamFriend) p) => (!p.isSteamFriend) ? $"{p.nickName} ({p.overrideCount})" : $"★ {p.nickName} ({p.overrideCount})", ((int actorNumber, string nickName, int overrideCount, bool isSteamFriend) p) => p.actorNumber); } static string[] BuildPlayerOptions(List<(int actorNumber, string nickName, int overrideCount, bool isSteamFriend)> list) { return list.Select<(int, string, int, bool), string>(((int actorNumber, string nickName, int overrideCount, bool isSteamFriend) p) => (!p.isSteamFriend) ? $"{p.nickName} ({p.overrideCount})" : $"★ {p.nickName} ({p.overrideCount})").ToArray(); } void Rebuild() { //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject item in cosmeticRows) { if (!((Object)(object)item == (Object)null)) { REPOScrollViewElement component = item.GetComponent(); if ((Object)(object)component != (Object)null) { component.visibility = false; } Object.Destroy((Object)(object)item); } } cosmeticRows.Clear(); Dictionary remoteOverrides = CustomizerSync.GetRemotePlayerData(currentActor); List remoteEquipped = GetRemoteEquipped(currentActor); IEnumerable enumerable = remoteOverrides?.Keys; IEnumerable collection = enumerable ?? Enumerable.Empty(); HashSet hashSet = new HashSet(collection); hashSet.UnionWith(remoteEquipped); List list = (from id in hashSet.Where((string id) => (Object)(object)FindAsset(id) != (Object)null).Where(delegate(string id) { BridgeSyncPayload d = remoteOverrides?.GetValueOrDefault(id); return MatchesFilter(id, d, currentCategory, currentSubcategory); }) orderby FindAsset(id)?.assetName ?? id select id).ToList(); if ((Object)(object)noEntriesEl != (Object)null) { noEntriesEl.visibility = list.Count == 0; } anyImportable = remoteOverrides != null && list.Any((string id) => remoteOverrides.TryGetValue(id, out BridgeSyncPayload value2) && HasImportableContent(id, value2)); REPOButton obj2 = importAllBtn; if (obj2 != null) { ((Component)obj2).gameObject.SetActive(anyImportable); } if (list.Count == 0) { popup.scrollView.UpdateElements(); } else { int siblingIndex = noEntriesTr.GetSiblingIndex(); RectTransform scroller = popup.menuScrollBox.scroller; for (int num = 0; num < list.Count; num++) { string text = list[num]; BridgeSyncPayload value; bool flag = remoteOverrides != null && remoteOverrides.TryGetValue(text, out value) && HasImportableContent(text, value); string text2 = DisplayName(text); float topPadding = ((num == 0) ? 5f : 0f); RectTransform val2 = CreateCosmeticRow((Transform)(object)scroller, topPadding); ((Transform)val2).SetSiblingIndex(siblingIndex + num); if (flag) { string capturedId = text; MenuAPI.CreateREPOButton("Import", (Action)delegate { Dictionary remotePlayerData = CustomizerSync.GetRemotePlayerData(currentActor); if (remotePlayerData != null && remotePlayerData.TryGetValue(capturedId, out value2)) { TryImportWithConflicts(new Dictionary { [capturedId] = value2 }, popup, Rebuild); } }, (Transform)(object)val2, new Vector2(-137f, 0f)); REPOButton val3 = MenuAPI.CreateREPOButton(text2, (Action)delegate { Dictionary remotePlayerData = CustomizerSync.GetRemotePlayerData(currentActor); if (remotePlayerData != null && remotePlayerData.TryGetValue(capturedId, out value2)) { ShowPreviewPopup(capturedId, value2, popup, Rebuild); } }, (Transform)(object)val2, new Vector2(-40f, 5f)); TextMeshProUGUI val4 = ((val3 != null) ? ((Component)val3).GetComponentInChildren() : null); if ((Object)(object)val4 != (Object)null) { ((TMP_Text)val4).fontSize = 18f; } BridgeSyncPayload p = remoteOverrides[text]; string text3 = BuildTagString(text, p); if (!string.IsNullOrEmpty(text3)) { REPOLabel val5 = MenuAPI.CreateREPOLabel(text3, (Transform)(object)val2, new Vector2(40f, 0f)); TextMeshProUGUI val6 = ((val5 != null) ? ((Component)val5).GetComponentInChildren() : null); if ((Object)(object)val6 != (Object)null) { ((TMP_Text)val6).fontSize = 10f; } } } else { REPOLabel val7 = MenuAPI.CreateREPOLabel(text2, (Transform)(object)val2, new Vector2(-55f, 0f)); TextMeshProUGUI val8 = ((val7 != null) ? ((Component)val7).GetComponentInChildren() : null); if ((Object)(object)val8 != (Object)null) { ((Graphic)val8).color = new Color(1f, 1f, 1f, 0.35f); ((TMP_Text)val8).fontSize = 18f; } } cosmeticRows.Add(((Component)val2).gameObject); } popup.scrollView.UpdateElements(); } } void RefreshPlayerOptions() { List<(int, string, int, bool)> remotePlayersWithData2 = CustomizerSync.GetRemotePlayersWithData(); if (remotePlayersWithData2.Count == 0) { CustomizerSync.OnRemoteDataChanged -= dataChangedHandler; popup.ClosePage(false); } else { playerOptions = BuildPlayerOptions(remotePlayersWithData2); actorByOption = BuildActorByOption(remotePlayersWithData2); if (!remotePlayersWithData2.Any<(int, string, int, bool)>(((int actorNumber, string nickName, int overrideCount, bool isSteamFriend) p) => p.actorNumber == currentActor)) { currentActor = remotePlayersWithData2[0].Item1; } if ((Object)(object)playerSlider != (Object)null) { playerSlider.stringOptions = playerOptions; int value; int num = Array.FindIndex(playerOptions, (string opt) => actorByOption.TryGetValue(opt, out value) && value == currentActor); playerSlider.SetValue((float)((num >= 0) ? num : 0), false); } } } } private static string BuildTagString(string assetId, BridgeSyncPayload p) { List list = new List(9); if (p.Type.HasValue) { OverrideCosmeticType? overrideCosmeticType = OriginalTypeOf(assetId); if (overrideCosmeticType.HasValue) { OverrideCosmeticType valueOrDefault = overrideCosmeticType.GetValueOrDefault(); if (p.Type.Value != valueOrDefault) { list.Add("Type"); } } } SwayMode? enableSway = p.EnableSway; bool flag; if (enableSway.HasValue) { SwayMode valueOrDefault2 = enableSway.GetValueOrDefault(); if ((uint)(valueOrDefault2 - 1) <= 2u) { flag = true; goto IL_0078; } } flag = false; goto IL_0078; IL_0078: if (flag) { list.Add("Sway"); } List? offsets = p.Offsets; if (offsets != null && offsets.Count > 0) { list.Add("Offset"); } List? customTypes = p.CustomTypes; if (customTypes != null && customTypes.Count > 0) { list.Add("Custom"); } if (p.Crown != null) { list.Add("Crown"); } if (p.ShowOnDeathHead == false || p.FloorPose != null) { list.Add("Death"); } if (p.FixAnimation.HasValue) { list.Add("Anim"); } if (p.Tintable.HasValue) { list.Add("Tint"); } CosmeticHideConfig hideConditions = p.HideConditions; if (hideConditions != null && hideConditions.HasAny) { list.Add("Hide"); } if (list.Count == 0) { return ""; } bool flag2 = list.Count > 3; IEnumerable enumerable2; if (!flag2) { IEnumerable enumerable = list; enumerable2 = enumerable; } else { enumerable2 = list.Take(3); } IEnumerable source = enumerable2; string text = string.Join(" ", source.Select((string t) => "[" + t + "]")); if (flag2) { text += " ..."; } return text; } private static bool HasImportableContent(string assetId, BridgeSyncPayload p) { CustomizerStore.TryGet(assetId, out CosmeticOverrideData data); return BuildPreviewRows(assetId, p, data).Count > 0; } private static List BuildPreviewRows(string assetId, BridgeSyncPayload r, CosmeticOverrideData? l) { //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_057b: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_08b0: Unknown result type (might be due to invalid IL or missing references) //IL_08a9: Unknown result type (might be due to invalid IL or missing references) //IL_0642: Unknown result type (might be due to invalid IL or missing references) //IL_08f9: Unknown result type (might be due to invalid IL or missing references) //IL_08f2: Unknown result type (might be due to invalid IL or missing references) //IL_06f8: Unknown result type (might be due to invalid IL or missing references) //IL_080c: Unknown result type (might be due to invalid IL or missing references) //IL_0750: Unknown result type (might be due to invalid IL or missing references) //IL_068b: Unknown result type (might be due to invalid IL or missing references) //IL_0867: Unknown result type (might be due to invalid IL or missing references) //IL_082f: Unknown result type (might be due to invalid IL or missing references) //IL_0798: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if (r.Type.HasValue) { OverrideCosmeticType value = r.Type.Value; string text = TypeLabel(value); OverrideCosmeticType? overrideCosmeticType = OriginalTypeOf(assetId); if (overrideCosmeticType.HasValue && value == overrideCosmeticType.Value) { if (l != null && l.Type.HasValue && (!overrideCosmeticType.HasValue || l.Type.Value != overrideCosmeticType.Value)) { list.Add(new PreviewRow("Type: " + text, "reset", ColReset)); } } else if (l == null || !l.Type.HasValue) { list.Add(new PreviewRow("Type: " + text, "NEW", ColNew)); } else if (l.Type == r.Type) { list.Add(new PreviewRow("Type: " + text, "= same", ColSame)); } else { list.Add(new PreviewRow("Type: " + text, $"≠ yours: {TypeLabel(l.Type.Value)}", ColDiff)); } } if (r.EnableSway.HasValue) { string text2 = SwayLabel(r.EnableSway.Value); if (l == null || !l.EnableSway.HasValue) { list.Add(new PreviewRow("Sway: " + text2, "NEW", ColNew)); } else if (l.EnableSway == r.EnableSway) { list.Add(new PreviewRow("Sway: " + text2, "= same", ColSame)); } else { list.Add(new PreviewRow("Sway: " + text2, $"≠ yours: {SwayLabel(l.EnableSway.Value)}", ColDiff)); } } List offsets = r.Offsets; if (offsets != null && offsets.Count > 0) { int count = r.Offsets.Count; string field = $"Offset: {count}"; offsets = l?.Offsets; if (offsets == null || offsets.Count <= 0) { list.Add(new PreviewRow(field, "NEW", ColNew)); } else if (OffsetsEqual(l.Offsets, r.Offsets)) { list.Add(new PreviewRow(field, "= same", ColSame)); } else { list.Add(new PreviewRow(field, $"≠ yours: {l.Offsets.Count}", ColDiff)); } } List customTypes = r.CustomTypes; if (customTypes != null && customTypes.Count > 0) { int count2 = r.CustomTypes.Count; string field2 = $"Custom: {count2}"; customTypes = l?.CustomTypes; if (customTypes == null || customTypes.Count <= 0) { list.Add(new PreviewRow(field2, "NEW", ColNew)); } else if (EnumSetEqual(l.CustomTypes, r.CustomTypes)) { list.Add(new PreviewRow(field2, "= same", ColSame)); } else { list.Add(new PreviewRow(field2, $"≠ yours: {l.CustomTypes.Count}", ColDiff)); } } if (r.Crown != null) { if (l?.Crown == null) { list.Add(new PreviewRow("Crown: configured", "NEW", ColNew)); } else if (CosmeticCrownConfig.ValueEquals(l.Crown, r.Crown, 0.0001f)) { list.Add(new PreviewRow("Crown: configured", "= same", ColSame)); } else { list.Add(new PreviewRow("Crown: configured", "≠ yours", ColDiff)); } } if (r.ShowOnDeathHead == false) { bool flag = l != null && l.ShowOnDeathHead == false; list.Add(new PreviewRow("Death Head: hidden", flag ? "= same" : "NEW", flag ? ColSame : ColNew)); } if (r.FloorPose != null) { if (l?.FloorPose == null) { list.Add(new PreviewRow("Impact Pose: configured", "NEW", ColNew)); } else if (FloorPoseEqual(l.FloorPose, r.FloorPose)) { list.Add(new PreviewRow("Impact Pose: configured", "= same", ColSame)); } else { list.Add(new PreviewRow("Impact Pose: configured", "≠ yours", ColDiff)); } } if (r.FixAnimation.HasValue) { string text3 = (r.FixAnimation.Value ? "Loop: on" : "Loop: off"); if (l == null || !l.FixAnimation.HasValue) { list.Add(new PreviewRow("Anim: " + text3, "NEW", ColNew)); } else if (l.FixAnimation == r.FixAnimation) { list.Add(new PreviewRow("Anim: " + text3, "= same", ColSame)); } else { string arg = (l.FixAnimation.Value ? "Loop: on" : "Loop: off"); list.Add(new PreviewRow("Anim: " + text3, $"≠ yours: {arg}", ColDiff)); } } if (r.Tintable.HasValue) { string text4 = (r.Tintable.Value ? "Tint: on" : "Tint: off"); if (l == null || !l.Tintable.HasValue) { list.Add(new PreviewRow(text4 ?? "", "NEW", ColNew)); } else if (l.Tintable == r.Tintable) { list.Add(new PreviewRow(text4 ?? "", "= same", ColSame)); } else { string arg2 = (l.Tintable.Value ? "Tint: on" : "Tint: off"); list.Add(new PreviewRow(text4 ?? "", $"≠ yours: {arg2}", ColDiff)); } } CosmeticHideConfig hideConditions = r.HideConditions; if (hideConditions != null && hideConditions.HasAny) { int num = HideRuleCount(hideConditions); CosmeticHideConfig cosmeticHideConfig = l?.HideConditions; CosmeticHideConfig cosmeticHideConfig2 = ((cosmeticHideConfig != null && cosmeticHideConfig.HasAny) ? l.HideConditions : null); string field3 = $"Hide: {num} rule(s)"; if (cosmeticHideConfig2 == null) { list.Add(new PreviewRow(field3, "NEW", ColNew)); } else if (HideEqual(cosmeticHideConfig2, hideConditions)) { list.Add(new PreviewRow(field3, "= same", ColSame)); } else { int num2 = HideRuleCount(cosmeticHideConfig2); list.Add(new PreviewRow(field3, $"≠ yours: {$"{num2} rule(s)"}", ColDiff)); } } if (r.AvoidWalls == true) { bool avoidWalls = WorldFollowPrefs.GetAvoidWalls(assetId); list.Add(new PreviewRow("Avoid Walls: on", avoidWalls ? "= same" : "NEW", avoidWalls ? ColSame : ColNew)); } if (r.HideOnKart == true) { bool hideOnKart = WorldFollowPrefs.GetHideOnKart(assetId); list.Add(new PreviewRow("Hide on Kart: on", hideOnKart ? "= same" : "NEW", hideOnKart ? ColSame : ColNew)); } return list; } private static List BuildLossRows(string assetId, BridgeSyncPayload r, CosmeticOverrideData? l) { //IL_032d: Unknown result type (might be due to invalid IL or missing references) List rows = new List(); if (WorldFollowPrefs.GetAvoidWalls(assetId) && r.AvoidWalls != true) { Lost("Avoid Walls"); } if (WorldFollowPrefs.GetHideOnKart(assetId) && r.HideOnKart != true) { Lost("Hide on Kart"); } if (l == null) { return rows; } OverrideCosmeticType? overrideCosmeticType = OriginalTypeOf(assetId); if (l.Type.HasValue && (!overrideCosmeticType.HasValue || l.Type.Value != overrideCosmeticType.Value) && !r.Type.HasValue) { Lost("Type: " + TypeLabel(l.Type.Value)); } if (l.EnableSway.HasValue && !r.EnableSway.HasValue) { Lost("Sway: " + SwayLabel(l.EnableSway.Value)); } List offsets = l.Offsets; if (offsets != null && offsets.Count > 0) { offsets = r.Offsets; if (offsets == null || offsets.Count <= 0) { Lost($"Offset: {l.Offsets.Count}"); } } List customTypes = l.CustomTypes; if (customTypes != null && customTypes.Count > 0) { customTypes = r.CustomTypes; if (customTypes == null || customTypes.Count <= 0) { Lost($"Custom: {l.CustomTypes.Count}"); } } if (l.Crown != null && r.Crown == null) { Lost("Crown: configured"); } if (l.FloorPose != null && r.FloorPose == null) { Lost("Impact Pose: configured"); } if (l.ShowOnDeathHead == false && r.ShowOnDeathHead != false) { Lost("Death Head: hidden"); } if (l.FixAnimation.HasValue && !r.FixAnimation.HasValue) { Lost("Anim: " + (l.FixAnimation.Value ? "Loop on" : "Loop off")); } if (l.Tintable.HasValue && !r.Tintable.HasValue) { Lost("Tint: " + (l.Tintable.Value ? "on" : "off")); } CosmeticHideConfig hideConditions = l.HideConditions; if (hideConditions != null && hideConditions.HasAny) { hideConditions = r.HideConditions; if (hideConditions == null || !hideConditions.HasAny) { Lost("Hide rules"); } } if (l.Rarity.HasValue) { Lost($"Rarity: {l.Rarity.Value}"); } if (l.IsModded.HasValue) { Lost("Border: " + (l.IsModded.Value ? "on" : "off")); } if (l.FixCollider.HasValue) { Lost("Remove Physics"); } if (l.FixCrown.HasValue) { Lost("Fix Crown"); } if (l.VanillaEquipAnimationMode.HasValue) { Lost($"Equip Anim: {l.VanillaEquipAnimationMode.Value}"); } if (l.EnableCustomColors.HasValue) { Lost("Custom Colors"); } if (l.EnableColorAnimations.HasValue) { Lost("Color Animations"); } if (l.UseIsolatedIcon.HasValue) { Lost("Isolated Icon"); } if (l.UseFitOffsets.HasValue) { Lost("Vanilla Position Fixes"); } return rows; void Lost(string field) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) rows.Add(new PreviewRow(field, "REMOVED", ColRemove)); } } private static List LostFieldNames(string assetId, BridgeSyncPayload r, CosmeticOverrideData? l) { List list = BuildLossRows(assetId, r, l); List list2 = new List(list.Count); foreach (PreviewRow item in list) { int num = item.FieldText.IndexOf(':'); list2.Add((num > 0) ? item.FieldText.Substring(0, num) : item.FieldText); } return list2; } private static string TypeLabel(OverrideCosmeticType t) { if (!CosmeticOverridePopup.SubLabels.TryGetValue(t, out string value)) { return t.ToString(); } return value; } private static string SwayLabel(SwayMode m) { return m switch { SwayMode.Light => "Light", SwayMode.Moderate => "Moderate", SwayMode.Strong => "Strong", _ => "None", }; } private static void ShowPreviewPopup(string assetId, BridgeSyncPayload remote, REPOPopupPage parentPopup, Action refresh) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, 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_0161: Expected O, but got Unknown CustomizerStore.TryGet(assetId, out CosmeticOverrideData data); List list = BuildPreviewRows(assetId, remote, data); list.AddRange(BuildLossRows(assetId, remote, data)); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage(DisplayName(assetId), false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, ((Component)parentPopup).transform); bool flag = true; foreach (PreviewRow item in list) { string capturedField = item.FieldText; string capturedStatus = item.StatusText; Color capturedColor = item.StatusColor; float num = (flag ? 15f : 2f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown string text = ColorUtility.ToHtmlStringRGB(capturedColor); string text2 = capturedField + " " + capturedStatus + ""; REPOLabel val2 = MenuAPI.CreateREPOLabel(text2, sv, new Vector2(5f, 0f)); TextMeshProUGUI val3 = ((val2 != null) ? ((Component)val2).GetComponentInChildren() : null); if ((Object)(object)val3 != (Object)null) { ((TMP_Text)val3).fontSize = 15f; ((TMP_Text)val3).richText = true; } return (RectTransform)((Component)val2).transform; }, num, 0f); flag = false; } if (list.Count == 0) { REPOPopupPage obj = popup; object obj2 = <>c.<>9__75_0; if (obj2 == null) { ScrollViewBuilderDelegate val = delegate(Transform sv) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown REPOLabel val2 = MenuAPI.CreateREPOLabel("(no override data)", sv, default(Vector2)); return (RectTransform)((Component)val2).transform; }; <>c.<>9__75_0 = val; obj2 = (object)val; } obj.AddElementToScrollView((ScrollViewBuilderDelegate)obj2, 15f, 0f); } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0036: 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) RectTransform val2 = PopupUI.MakeRow(sv); MenuAPI.CreateREPOButton("Close", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val2, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Import", (Action)delegate { popup.ClosePage(false); TryImportWithConflicts(new Dictionary { [assetId] = remote }, parentPopup, refresh); }, (Transform)(object)val2, new Vector2(56f, 0f)); return val2; }, 10f, 0f); popup.OpenPage(true); } } internal static class CosmeticsMenuState { private static Coroutine? _searchDebounce; private const float SearchDebounceDelay = 0.25f; private static Dictionary? _assetIndexCache; internal static CosmeticCategoryAsset? SelectedCategory { get; private set; } internal static CosmeticCategoryAsset? SearchCategory { get; private set; } internal static CosmeticCategoryAsset? FavoritesCategory { get; private set; } internal static CosmeticCategoryAsset? HiddenCategory { get; private set; } internal static TextMeshProUGUI? StatusLabel { get; private set; } internal static CanvasGroup? StatusLabelGroup { get; private set; } internal static TMP_InputField? SearchField { get; private set; } internal static GameObject? EmptyStateLabel { get; private set; } internal static bool SearchMode { get; private set; } internal static string SearchText { get; private set; } = ""; internal static MenuPageCosmetics? ActivePage { get; private set; } internal static bool IsVirtual(CosmeticCategoryAsset? c) { if ((Object)(object)c != (Object)null) { if (!((Object)(object)c == (Object)(object)SelectedCategory) && !((Object)(object)c == (Object)(object)SearchCategory) && !((Object)(object)c == (Object)(object)FavoritesCategory)) { return (Object)(object)c == (Object)(object)HiddenCategory; } return true; } return false; } internal static bool IsSelected(CosmeticCategoryAsset? c) { if ((Object)(object)c != (Object)null) { return (Object)(object)c == (Object)(object)SelectedCategory; } return false; } internal static bool IsSearch(CosmeticCategoryAsset? c) { if ((Object)(object)c != (Object)null) { return (Object)(object)c == (Object)(object)SearchCategory; } return false; } internal static bool IsFavCategory(CosmeticCategoryAsset? c) { if ((Object)(object)c != (Object)null) { return (Object)(object)c == (Object)(object)FavoritesCategory; } return false; } internal static bool IsHideCategory(CosmeticCategoryAsset? c) { if ((Object)(object)c != (Object)null) { return (Object)(object)c == (Object)(object)HiddenCategory; } return false; } internal static void EnsureCategories() { if (SelectedCategory == null) { SelectedCategory = MakeCategory("MHB_Selected", "SELECTED"); } if (SearchCategory == null) { SearchCategory = MakeCategory("MHB_Search", "SEARCH"); } if (FavoritesCategory == null) { FavoritesCategory = MakeCategory("MHB_Favorites", "FAV"); } if (HiddenCategory == null) { HiddenCategory = MakeCategory("MHB_Hidden", "HIDE"); } } internal static void SetStatusLabel(TextMeshProUGUI? v) { StatusLabel = v; } internal static void SetStatusLabelGroup(CanvasGroup? v) { StatusLabelGroup = v; } internal static void SetSearchField(TMP_InputField? v) { SearchField = v; } internal static void SetEmptyStateLabel(GameObject? v) { EmptyStateLabel = v; } internal static void SetSearchMode(bool v) { SearchMode = v; } internal static void SetSearchText(string v) { SearchText = v; } internal static void ClearSearch() { SearchText = ""; SearchMode = false; if ((Object)(object)SearchField != (Object)null) { SearchField.SetTextWithoutNotify(""); } } internal static void ScheduleSearchRefresh() { MenuPageCosmetics activePage = ActivePage; if (!((Object)(object)activePage == (Object)null)) { if (_searchDebounce != null) { ((MonoBehaviour)activePage).StopCoroutine(_searchDebounce); } _searchDebounce = ((MonoBehaviour)activePage).StartCoroutine(SearchRefreshCoroutine(activePage)); } } private static IEnumerator SearchRefreshCoroutine(MenuPageCosmetics page) { yield return (object)new WaitForSeconds(0.25f); _searchDebounce = null; page.RefreshScrollContent(); } internal static void SetActivePage(MenuPageCosmetics? v) { ActivePage = v; } internal static void OnMenuClosed() { if (_searchDebounce != null && (Object)(object)ActivePage != (Object)null) { ((MonoBehaviour)ActivePage).StopCoroutine(_searchDebounce); } _searchDebounce = null; ActivePage = null; StatusLabelGroup = null; _assetIndexCache = null; SearchText = ""; SearchMode = false; } internal static int GetAssetIndex(CosmeticAsset asset) { if ((Object)(object)MetaManager.instance == (Object)null) { return -1; } if (_assetIndexCache == null) { List cosmeticAssets = MetaManager.instance.cosmeticAssets; _assetIndexCache = new Dictionary(cosmeticAssets.Count); for (int i = 0; i < cosmeticAssets.Count; i++) { if ((Object)(object)cosmeticAssets[i] != (Object)null) { _assetIndexCache[cosmeticAssets[i]] = i; } } } if (!_assetIndexCache.TryGetValue(asset, out var value)) { return -1; } return value; } internal static bool IsPresetsCategory(CosmeticCategoryAsset? cat) { if ((Object)(object)cat == (Object)null) { return false; } string text = (cat.categoryName ?? ((Object)cat).name ?? "").ToUpperInvariant(); if (!text.Contains("PRESET")) { return text.Contains("OUTFIT"); } return true; } private static CosmeticCategoryAsset MakeCategory(string id, string label) { CosmeticCategoryAsset val = ScriptableObject.CreateInstance(); ((Object)val).name = id; val.categoryName = label; val.typeList = Enum.GetValues(typeof(CosmeticType)).Cast().ToList(); return val; } } public enum SearchBarPosition { Bottom, Top } internal static class CosmeticsScrollBuilder { private static readonly MethodInfo? RecalculateScrollHeightAfterFrame = AccessTools.Method(typeof(MenuPageCosmetics), "RecalculateScrollHeightAfterFrame", (Type[])null, (Type[])null); private static readonly FieldInfo? TopDividerRestingPositionEnd = AccessTools.Field(typeof(MenuPageCosmetics), "topDividerRestingPositionEnd"); private static readonly FieldInfo? TopDividerRestingPositionEndNew = AccessTools.Field(typeof(MenuPageCosmetics), "topDividerRestingPositionEndNew"); private static readonly HashSet VanillaTabTypes = new HashSet { (CosmeticType)0, (CosmeticType)30, (CosmeticType)17, (CosmeticType)18, (CosmeticType)31, (CosmeticType)32, (CosmeticType)20, (CosmeticType)21, (CosmeticType)16, (CosmeticType)23, (CosmeticType)1, (CosmeticType)2, (CosmeticType)26, (CosmeticType)27, (CosmeticType)3, (CosmeticType)4, (CosmeticType)19, (CosmeticType)22, (CosmeticType)28, (CosmeticType)29 }; internal static bool ShouldUseVanillaPerfPath(CosmeticCategoryAsset? category) { if (Plugin.FixCosmeticsMenuPerformance.Value || CosmeticGrouping.Enabled) { return IsVanillaTabCategory(category); } return false; } private static int CompareForMenu(CosmeticAsset a, int aIndex, CosmeticAsset b, int bIndex, HashSet unlocksSet) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) int num = (!unlocksSet.Contains(aIndex)).CompareTo(!unlocksSet.Contains(bIndex)); if (num != 0) { return num; } ref Rarity rarity = ref b.rarity; object target = a.rarity; int num2 = ((Enum)Unsafe.As(ref rarity)/*cast due to .constrained prefix*/).CompareTo(target); if (num2 != 0) { return num2; } return string.Compare(a.assetName, b.assetName, StringComparison.Ordinal); } internal static void BuildVirtualScrollContent(MenuPageCosmetics page) { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) PreparePageForCustomBuild(page); CosmeticsSearchHelper.UpdateSearchFieldVisibility(CosmeticsMenuState.IsSearch(page.selectedCategory)); BridgeFavoritesManager.EnsureLoaded(); CosmeticCategoryAsset selectedCategory = page.selectedCategory; bool flag = CosmeticsMenuState.IsSelected(selectedCategory); bool flag2 = CosmeticsMenuState.IsSearch(selectedCategory); bool flag3 = CosmeticsMenuState.IsFavCategory(selectedCategory); bool flag4 = CosmeticsMenuState.IsHideCategory(selectedCategory); string text = CosmeticsSearchHelper.FoldText(CosmeticsMenuState.SearchText?.Trim() ?? ""); bool applySearch = flag2 && text.Length > 0; bool suppressHidden = !flag4 && !flag && BridgeFavoritesManager.HasAnyHidden(); if ((Object)(object)MetaManager.instance == (Object)null || selectedCategory?.typeList == null) { HideEmptyState(); StartRecalculate(page); return; } HashSet equippedSet = new HashSet(MetaManager.instance.cosmeticEquipped); HashSet unlocksSet = new HashSet(MetaManager.instance.cosmeticUnlocks); float num = 0f; int num2 = 0; MenuElementCosmeticSection val = null; bool flag5 = HhhCosmeticLoader.WorldAssetIds.Count > 0; HashSet hashSet = new HashSet(selectedCategory.typeList); Dictionary> dictionary = new Dictionary>(); List cosmeticAssets = MetaManager.instance.cosmeticAssets; for (int i = 0; i < cosmeticAssets.Count; i++) { CosmeticAsset val2 = cosmeticAssets[i]; if (!((Object)(object)val2 == (Object)null) && ((PrefabRef)(object)val2.prefab).IsValid() && hashSet.Contains(val2.type) && (!flag5 || !HhhCosmeticLoader.IsWorldAsset(val2)) && CosmeticsFilterPatch.Matches(val2, flag, flag2, flag3, flag4, suppressHidden, applySearch, text, equippedSet, unlocksSet)) { if (!dictionary.TryGetValue(val2.type, out var value)) { value = (dictionary[val2.type] = new List<(CosmeticAsset, int)>()); } value.Add((val2, i)); } } foreach (CosmeticType type in selectedCategory.typeList) { if (dictionary.TryGetValue(type, out var value2) && value2.Count != 0) { value2.Sort(((CosmeticAsset Asset, int Index) a, (CosmeticAsset Asset, int Index) b) => CompareForMenu(a.Asset, a.Index, b.Asset, b.Index, unlocksSet)); MenuElementCosmeticSection val3 = CreateSection(page, type, GetTypeLabel(type), value2.Select<(CosmeticAsset, int), CosmeticAsset>(((CosmeticAsset Asset, int Index) x) => x.Asset), num); if (!((Object)(object)val3 == (Object)null)) { page.sections.Add(val3); CreateSubCategoryButton(page, type, GetTypeLabel(type)); val = val3; num2 += value2.Count; num -= ((Component)val3).GetComponent().sizeDelta.y + 10f; } } } if (flag2 || flag || flag3 || flag4) { CosmeticsSortHelper.SortFavoritesInCategory(page, flag, skipRebuild: true); } int num3 = (flag5 ? InjectWorldSection(page, num, flag, flag2, flag3, flag4, suppressHidden, applySearch, text, equippedSet, unlocksSet) : 0); num2 += num3; MenuElementCosmeticSection section; if (num3 <= 0) { section = val; } else { List sections = page.sections; section = sections[sections.Count - 1]; } ApplyStickyPadding(page, section); if (num2 == 0) { string message = (flag3 ? "Add a favorite with Ctrl+click :)" : (flag4 ? "Hide cosmetics with Alt+click :P" : ((!flag2) ? "Equip a cosmetic to see it here :3" : (string.IsNullOrWhiteSpace(CosmeticsMenuState.SearchText) ? "Type to search cosmetics here :)" : "No cosmetics found :'(")))); ShowEmptyState(message); } else { HideEmptyState(); } RebuildScroll(page); StartRecalculate(page); } internal static void BuildWorldScrollContent(MenuPageCosmetics page) { PreparePageForCustomBuild(page); CosmeticsSearchHelper.UpdateSearchFieldVisibility(isSearch: false); BridgeFavoritesManager.EnsureLoaded(); if ((Object)(object)MetaManager.instance == (Object)null) { HideEmptyState(); StartRecalculate(page); return; } HashSet unlocksSet = new HashSet(MetaManager.instance.cosmeticUnlocks); bool suppressHidden = BridgeFavoritesManager.HasAnyHidden(); List list = (from a in MetaManager.instance.cosmeticAssets where (Object)(object)a != (Object)null && ((PrefabRef)(object)a.prefab).IsValid() && HhhCosmeticLoader.IsWorldAsset(a) && (!suppressHidden || !BridgeFavoritesManager.IsHidden(a)) orderby a.assetId != MiniSemibotCosmetic.AssetId, !unlocksSet.Contains(CosmeticsMenuState.GetAssetIndex(a)), a.rarity descending, a.assetName select a).ToList(); if (list.Count > 0) { MenuElementCosmeticSection val = CreateSection(page, (CosmeticType)2147483646, "WORLD", list, 0f); if ((Object)(object)val != (Object)null) { page.sections.Add(val); CreateSubCategoryButton(page, (CosmeticType)2147483646, "WORLD"); CosmeticsSortHelper.SortFavoritesInCategory(page, hiddenAtEnd: false, skipRebuild: true); ApplyStickyPadding(page, val); } } HideEmptyState(); RebuildScroll(page); StartRecalculate(page); } internal static void BuildVanillaScrollContent(MenuPageCosmetics page) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) PreparePageForCustomBuild(page); CosmeticsSearchHelper.UpdateSearchFieldVisibility(isSearch: false); BridgeFavoritesManager.EnsureLoaded(); CosmeticCategoryAsset selectedCategory = page.selectedCategory; if ((Object)(object)MetaManager.instance == (Object)null || selectedCategory?.typeList == null) { HideEmptyState(); StartRecalculate(page); return; } MetaManager instance = MetaManager.instance; HashSet unlocksSet = new HashSet(instance.cosmeticUnlocks); bool flag = BridgeFavoritesManager.HasAnyHidden(); float num = 0f; MenuElementCosmeticSection section = null; foreach (CosmeticType type in selectedCategory.typeList) { List<(CosmeticAsset, int)> list = new List<(CosmeticAsset, int)>(); for (int i = 0; i < instance.cosmeticAssets.Count; i++) { CosmeticAsset val = instance.cosmeticAssets[i]; if (!((Object)(object)val == (Object)null) && val.type == type && ((PrefabRef)(object)val.prefab).IsValid() && ((int)type != 0 || !HhhCosmeticLoader.IsWorldAsset(val)) && (!flag || !BridgeFavoritesManager.IsHidden(val))) { list.Add((val, i)); } } bool flag2 = HasTintableMaterial(page, type); if (list.Count != 0 || flag2) { list.Sort(((CosmeticAsset Asset, int Index) a, (CosmeticAsset Asset, int Index) b) => CompareForMenu(a.Asset, a.Index, b.Asset, b.Index, unlocksSet)); string typeLabel = GetTypeLabel(type); CreateSubCategoryButton(page, type, typeLabel); MenuElementCosmeticSection val2 = CreateVanillaLikeSection(page, type, typeLabel, list.Select<(CosmeticAsset, int), CosmeticAsset>(((CosmeticAsset Asset, int Index) x) => x.Asset), num); page.sections.Add(val2); section = val2; num -= ((Component)val2).GetComponent().sizeDelta.y + 10f; } } CosmeticsSortHelper.SortFavoritesInCategory(page, hiddenAtEnd: false, skipRebuild: true); ApplyStickyPadding(page, section); HideEmptyState(); RebuildScroll(page); StartRecalculate(page); } internal static MenuElementCosmeticSection? CreateSection(MenuPageCosmetics page, CosmeticType subCategory, string label, IEnumerable assets, float yPos) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown List list = assets.ToList(); if (list.Count == 0) { return null; } GameObject val = Object.Instantiate(page.sectionPrefab, page.sectionRootTransform); val.transform.localPosition = new Vector3(val.transform.localPosition.x, yPos, val.transform.localPosition.z); MenuElementCosmeticSection component = val.GetComponent(); component.subCategory = subCategory; if ((Object)(object)component.headerText != (Object)null) { ((TMP_Text)component.headerText).text = label; ((TMP_Text)component.headerText).ForceMeshUpdate(false, false); } if ((Object)(object)component.highlightObj != (Object)null) { ((Component)component.highlightObj).gameObject.SetActive(false); } GridLayoutGroup component2 = ((Component)component.cosmeticListTransform).GetComponent(); ((LayoutGroup)component2).padding = new RectOffset(((LayoutGroup)component2).padding.left, ((LayoutGroup)component2).padding.right, ((LayoutGroup)component2).padding.top, 0); int count = PopulateSectionButtons(page, component, list); ApplySectionSize(component, count); return component; } private static int PopulateSectionButtons(MenuPageCosmetics page, MenuElementCosmeticSection section, IEnumerable assets) { List<(CosmeticAsset, List)> list = CosmeticGrouping.Collapse(assets); foreach (var item3 in list) { CosmeticAsset item = item3.Item1; List item2 = item3.Item2; GameObject val = Object.Instantiate(page.sectionButtonPrefab, section.cosmeticListTransform); MenuElementCosmeticButton component = val.GetComponent(); component.cosmeticAsset = item; if (item2 != null && item2.Count > 1) { CosmeticGroupButton.Attach(component, item2); } FavHideMarkerHelper.UpdateMarker(component); } return list.Count; } private static MenuElementCosmeticSection CreateVanillaLikeSection(MenuPageCosmetics page, CosmeticType subCategory, string label, IEnumerable assets, float yPos) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) List assets2 = assets.ToList(); GameObject val = Object.Instantiate(page.sectionPrefab, page.sectionRootTransform); val.transform.localPosition = new Vector3(val.transform.localPosition.x, yPos, val.transform.localPosition.z); MenuElementCosmeticSection component = val.GetComponent(); component.subCategory = subCategory; if ((Object)(object)component.headerText != (Object)null) { ((TMP_Text)component.headerText).text = label; ((TMP_Text)component.headerText).ForceMeshUpdate(false, false); } MenuElementCosmeticHighlight highlightObj = component.highlightObj; RectTransform val2 = ((highlightObj != null) ? ((Component)highlightObj).GetComponent() : null); if ((Object)(object)val2 != (Object)null && (Object)(object)component.headerText != (Object)null) { float x = ((TMP_Text)component.headerText).rectTransform.anchoredPosition.x; Bounds textBounds = ((TMP_Text)component.headerText).textBounds; val2.anchoredPosition = new Vector2(x + ((Bounds)(ref textBounds)).max.x + 15f, val2.anchoredPosition.y); } int count = PopulateSectionButtons(page, component, assets2); ApplySectionSize(component, count); return component; } internal static int InjectWorldSection(MenuPageCosmetics page, float yPos, bool isSelected, bool isSearch, bool isFav, bool isHide, bool suppressHidden, bool applySearch, string search, HashSet equippedSet, HashSet unlocksSet) { //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) for (int num = page.sections.Count - 1; num >= 0; num--) { if ((Object)(object)page.sections[num] != (Object)null && ((Object)((Component)page.sections[num]).gameObject).name == "MHB_WorldSection") { Object.Destroy((Object)(object)((Component)page.sections[num]).gameObject); page.sections.RemoveAt(num); } } List list = (from a in MetaManager.instance.cosmeticAssets where (Object)(object)a != (Object)null && ((PrefabRef)(object)a.prefab).IsValid() && HhhCosmeticLoader.IsWorldAsset(a) && CosmeticsFilterPatch.Matches(a, isSelected, isSearch, isFav, isHide, suppressHidden, applySearch, search, equippedSet, unlocksSet) orderby a.assetId != MiniSemibotCosmetic.AssetId, !unlocksSet.Contains(CosmeticsMenuState.GetAssetIndex(a)), a.rarity descending, a.assetName select a).ToList(); if (isSearch || isSelected) { bool hiddenAtEnd = isSelected; list = (from t in list.Select((CosmeticAsset a, int i) => (a: a, i: i)) orderby (!BridgeFavoritesManager.IsFavorite(t.a)) ? ((!hiddenAtEnd || !BridgeFavoritesManager.IsHidden(t.a)) ? 1 : 3) : 0, t.i select t.a).ToList(); } if (list.Count == 0) { return 0; } GameObject val = Object.Instantiate(page.sectionPrefab, page.sectionRootTransform); ((Object)val).name = "MHB_WorldSection"; MenuElementCosmeticSection component = val.GetComponent(); component.subCategory = (CosmeticType)2147483646; if ((Object)(object)component.headerText != (Object)null) { ((TMP_Text)component.headerText).text = "WORLD"; ((TMP_Text)component.headerText).ForceMeshUpdate(false, false); } if ((Object)(object)component.highlightObj != (Object)null) { ((Component)component.highlightObj).gameObject.SetActive(false); } int count = PopulateSectionButtons(page, component, list); ApplySectionSize(component, count); RectTransform component2 = val.GetComponent(); ((Transform)component2).localPosition = new Vector3(((Transform)component2).localPosition.x, yPos, ((Transform)component2).localPosition.z); page.sections.Add(component); CreateSubCategoryButton(page, (CosmeticType)2147483646, "WORLD"); return list.Count; } internal static void ShowEmptyState(string message) { GameObject emptyStateLabel = CosmeticsMenuState.EmptyStateLabel; if (!((Object)(object)emptyStateLabel == (Object)null)) { TextMeshProUGUI component = emptyStateLabel.GetComponent(); if ((Object)(object)component != (Object)null) { ((TMP_Text)component).text = message; } if (!emptyStateLabel.activeSelf) { emptyStateLabel.SetActive(true); } } } internal static void HideEmptyState() { GameObject emptyStateLabel = CosmeticsMenuState.EmptyStateLabel; if ((Object)(object)emptyStateLabel != (Object)null && emptyStateLabel.activeSelf) { emptyStateLabel.SetActive(false); } } internal static void RebuildScroll(MenuPageCosmetics page) { ScrollRect componentInChildren = ((Component)page).GetComponentInChildren(true); if ((Object)(object)((componentInChildren != null) ? componentInChildren.content : null) != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(componentInChildren.content); } } internal static void CreateSubCategoryButton(MenuPageCosmetics page, CosmeticType subCategory, string label) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate(page.categoryButtonPrefab, page.subCategoriesTransform); MenuElementButtonCosmeticCategory component = val.GetComponent(); component.subCategory = subCategory; component.buttonType = (ButtonType)1; if ((Object)(object)component.canvasGroup != (Object)null) { component.canvasGroup.alpha = 0f; } TextMeshProUGUI componentInChildren = val.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).fontSize = 16f; ((TMP_Text)componentInChildren).text = label; } } internal static void ApplyStickyPadding(MenuPageCosmetics page, MenuElementCosmeticSection? section) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)section == (Object)null) { return; } RectTransform val = page.stickyHeader?.viewport; if ((Object)(object)val == (Object)null) { return; } RectTransform component = ((Component)section).GetComponent(); Transform cosmeticListTransform = section.cosmeticListTransform; RectTransform val2 = ((cosmeticListTransform != null) ? ((Component)cosmeticListTransform).GetComponent() : null); Transform cosmeticListTransform2 = section.cosmeticListTransform; GridLayoutGroup val3 = ((cosmeticListTransform2 != null) ? ((Component)cosmeticListTransform2).GetComponent() : null); if (!((Object)(object)component == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null)) { Rect rect = val.rect; float num = Mathf.Max(0f, ((Rect)(ref rect)).height - component.sizeDelta.y - 10f); if (!(num <= 0f)) { ((LayoutGroup)val3).padding = new RectOffset(((LayoutGroup)val3).padding.left, ((LayoutGroup)val3).padding.right, ((LayoutGroup)val3).padding.top, (int)num); val2.sizeDelta = new Vector2(val2.sizeDelta.x, val2.sizeDelta.y + num); component.sizeDelta = new Vector2(component.sizeDelta.x, component.sizeDelta.y + num); } } } internal unsafe static string GetTypeLabel(CosmeticType type) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MetaManager.instance != (Object)null) { CosmeticTypeAsset val = ((IEnumerable)MetaManager.instance.cosmeticTypeAssets).FirstOrDefault((Func)((CosmeticTypeAsset x) => (Object)(object)x != (Object)null && x.type == type)); if ((Object)(object)val != (Object)null) { LocalizedAsset localizedName = val.localizedName; return ((localizedName != null) ? localizedName.GetLocalizedString() : null) ?? val.typeName; } } return ((object)(*(CosmeticType*)(&type))/*cast due to .constrained prefix*/).ToString(); } private static void PreparePageForCustomBuild(MenuPageCosmetics page) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) page.subCategoriesReady = false; MenuScrollBox menuScrollBox = page.menuScrollBox; object obj; if (menuScrollBox == null) { obj = null; } else { RectTransform scroller = menuScrollBox.scroller; obj = ((scroller != null) ? ((Component)scroller).GetComponent() : null); } CanvasGroup val = (CanvasGroup)obj; if ((Object)(object)val != (Object)null) { val.alpha = 0f; } foreach (Transform item in page.subCategoriesTransform) { Transform val2 = item; Object.Destroy((Object)(object)((Component)val2).gameObject); } foreach (MenuElementCosmeticSection item2 in page.sections.ToList()) { if ((Object)(object)item2 != (Object)null) { Object.Destroy((Object)(object)((Component)item2).gameObject); } } page.sections.Clear(); page.scrollGradientTopHidden = true; if (TopDividerRestingPositionEnd?.GetValue(page) is Vector2 val3) { TopDividerRestingPositionEndNew?.SetValue(page, (object)new Vector2(val3.x, 311f)); } if ((Object)(object)page.scrollGradientTopCanvasGroup != (Object)null) { RectTransform component = ((Component)page.scrollGradientTopCanvasGroup).GetComponent(); if ((Object)(object)component != (Object)null) { component.anchoredPosition = new Vector2(component.anchoredPosition.x, -133f); } } } private static void ApplySectionSize(MenuElementCosmeticSection section, int count) { //IL_002d: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) GridLayoutGroup component = ((Component)section.cosmeticListTransform).GetComponent(); int num = Mathf.Max(1, component.constraintCount); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)(count + 1) / (float)num)); float num3 = component.cellSize.y * (float)num2 + component.spacing.y * (float)(num2 - 1) + (float)((LayoutGroup)component).padding.top + (float)((LayoutGroup)component).padding.bottom; float num4 = 40f + num3; RectTransform component2 = ((Component)section).GetComponent(); component2.sizeDelta = new Vector2(component2.sizeDelta.x, num4); RectTransform component3 = ((Component)section.cosmeticListTransform).GetComponent(); component3.sizeDelta = new Vector2(component3.sizeDelta.x, num3); } private static void StartRecalculate(MenuPageCosmetics page) { if (RecalculateScrollHeightAfterFrame?.Invoke(page, null) is IEnumerator enumerator) { ((MonoBehaviour)page).StartCoroutine(enumerator); } } private static bool IsVanillaTabCategory(CosmeticCategoryAsset? category) { if (category?.typeList == null) { return false; } if (CosmeticsMenuState.IsVirtual(category)) { return false; } if (WorldCosmeticsMenuState.IsWorldCategory(category)) { return false; } if (CosmeticsMenuState.IsPresetsCategory(category)) { return false; } return category.typeList.Any((CosmeticType t) => VanillaTabTypes.Contains(t)); } private static bool HasTintableMaterial(MenuPageCosmetics page, CosmeticType subCategory) { //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) if ((Object)(object)page.menuPage?.playerAvatarMenu == (Object)null) { return false; } foreach (PlayerMaterial playerMaterial in page.menuPage.playerAvatarMenu.playerCosmetics.playerMaterials) { if ((Object)(object)playerMaterial != (Object)null && playerMaterial.cosmeticType == subCategory && playerMaterial.tintable) { return true; } } return false; } } internal static class CosmeticsSearchHelper { internal static string FoldText(string s) { if (string.IsNullOrEmpty(s)) { return ""; } string text = s.ToLowerInvariant().Normalize(NormalizationForm.FormD); StringBuilder stringBuilder = new StringBuilder(text.Length); string text2 = text; foreach (char c in text2) { if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) { stringBuilder.Append(c); } } return stringBuilder.ToString().Normalize(NormalizationForm.FormC); } internal static void UpdateSearchFieldVisibility(bool isSearch) { TMP_InputField searchField = CosmeticsMenuState.SearchField; if ((Object)(object)searchField == (Object)null) { return; } if (isSearch) { CosmeticsMenuState.SetSearchMode(v: true); bool activeSelf = ((Component)searchField).gameObject.activeSelf; ((Component)searchField).gameObject.SetActive(true); if (!activeSelf) { StartSearchFieldAnimation(searchField); } } else { if (CosmeticsMenuState.SearchMode) { CosmeticsMenuState.ClearSearch(); } ((Component)searchField).gameObject.SetActive(false); } } private static void StartSearchFieldAnimation(TMP_InputField field) { MenuPageCosmetics activePage = CosmeticsMenuState.ActivePage; if (!((Object)(object)activePage == (Object)null)) { ((MonoBehaviour)activePage).StartCoroutine(AnimateSearchField(field)); } } private static IEnumerator AnimateSearchField(TMP_InputField field) { RectTransform rt = ((Component)field).GetComponent(); CanvasGroup group = ((Component)field).GetComponent(); if ((Object)(object)group != (Object)null) { group.alpha = 0f; } yield return (object)new WaitForSeconds(0.05f); if ((Object)(object)field == (Object)null || (Object)(object)rt == (Object)null || !((Component)field).gameObject.activeInHierarchy) { yield break; } if ((Object)(object)group != (Object)null) { group.alpha = 1f; } float duration = 0.25f; float amplitude = 5f; float bounces = 2f; float elapsed = 0f; Vector2 basePos = rt.anchoredPosition; while (elapsed < duration) { if (!((Component)field).gameObject.activeInHierarchy) { yield break; } float num = elapsed / duration; float num2 = bounces * (1f - num); float num3 = Mathf.Sin(num2 * num * MathF.PI * 2f); float num4 = 1f - num; rt.anchoredPosition = new Vector2(basePos.x, basePos.y + num3 * amplitude * num4); elapsed += Time.deltaTime; yield return null; } rt.anchoredPosition = basePos; } } internal static class CosmeticsSortHelper { internal static void SortFavoritesInCategory(MenuPageCosmetics page, bool hiddenAtEnd = false, bool skipRebuild = false) { bool hasFavs = BridgeFavoritesManager.HasAnyFavorite(); bool flag = BridgeFavoritesManager.HasAnyHidden(); RebuildSectionSortOrder(page, hasFavs, flag, hiddenAtEnd && flag, skipRebuild); } private static void RebuildSectionSortOrder(MenuPageCosmetics page, bool hasFavs, bool hasAnyHidden, bool sortHiddenAtEnd, bool skipRebuild) { if (!hasFavs && !hasAnyHidden && !CustomizerStore.HasAnyModded()) { return; } foreach (MenuElementCosmeticSection section in page.sections) { if ((Object)(object)section == (Object)null || (Object)(object)section.cosmeticListTransform == (Object)null) { continue; } MenuElementCosmeticButton[] componentsInChildren = ((Component)section.cosmeticListTransform).GetComponentsInChildren(true); MenuElementCosmeticButton val = null; List<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int)> list = new List<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int)>(); List<(MenuElementCosmeticButton, int)> list2 = new List<(MenuElementCosmeticButton, int)>(); bool flag = false; bool flag2 = false; bool flag3 = false; MenuElementCosmeticButton[] array = componentsInChildren; foreach (MenuElementCosmeticButton val2 in array) { if ((Object)(object)val2 == (Object)null) { continue; } if ((Object)(object)val2.cosmeticAsset == (Object)null) { if (val == null) { val = val2; } continue; } int siblingIndex = ((Component)val2).transform.GetSiblingIndex(); if (!((Component)val2).gameObject.activeSelf) { list2.Add((val2, siblingIndex)); continue; } bool flag4 = hasFavs && BridgeFavoritesManager.IsFavorite(val2.cosmeticAsset); bool flag5 = hasAnyHidden && BridgeFavoritesManager.IsHidden(val2.cosmeticAsset); bool flag6 = CustomizerStore.IsModdedForAsset(val2.cosmeticAsset); bool flag7 = CustomizerStore.IsNonBridgeModdedForAsset(val2.cosmeticAsset); BorderTheme.Theme theme; bool item = BorderTheme.TryResolve(val2.cosmeticAsset, out theme); FavHideMarkerHelper.UpdateMarker(val2, flag4, flag5); flag = flag || flag4; flag2 = flag2 || flag5; flag3 = flag3 || flag6 || flag7; list.Add((val2, flag4, flag5, flag6, flag7, item, CosmeticsFilterPatch.IsUnlocked(val2), siblingIndex)); } if ((list.Count == 0 && list2.Count == 0) || (!flag && !flag2 && !flag3)) { continue; } (MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int)[] array2 = list.OrderBy<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int), int>(delegate((MenuElementCosmeticButton Button, bool Favorite, bool Hidden, bool Modded, bool NonBridgeModded, bool Themed, bool Unlocked, int Sibling) b) { if (b.Favorite) { return 0; } return (!sortHiddenAtEnd || !b.Hidden) ? 1 : 3; }).ThenBy<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int), int>(((MenuElementCosmeticButton Button, bool Favorite, bool Hidden, bool Modded, bool NonBridgeModded, bool Themed, bool Unlocked, int Sibling) b) => (!(b.Button.cosmeticAsset.assetId == MiniSemibotCosmetic.AssetId)) ? 1 : 0).ThenBy<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int), int>(((MenuElementCosmeticButton Button, bool Favorite, bool Hidden, bool Modded, bool NonBridgeModded, bool Themed, bool Unlocked, int Sibling) b) => (!b.Unlocked) ? 1 : 0) .ThenBy<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int), int>(((MenuElementCosmeticButton Button, bool Favorite, bool Hidden, bool Modded, bool NonBridgeModded, bool Themed, bool Unlocked, int Sibling) b) => (!b.Modded) ? (b.NonBridgeModded ? 1 : 2) : 0) .ThenBy<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int), int>(((MenuElementCosmeticButton Button, bool Favorite, bool Hidden, bool Modded, bool NonBridgeModded, bool Themed, bool Unlocked, int Sibling) b) => (!b.Themed) ? 1 : 0) .ThenBy<(MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int), int>(((MenuElementCosmeticButton Button, bool Favorite, bool Hidden, bool Modded, bool NonBridgeModded, bool Themed, bool Unlocked, int Sibling) b) => b.Rest.Item1) .ToArray(); int num = 0; if ((Object)(object)val != (Object)null) { ((Component)val).transform.SetSiblingIndex(num++); } (MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int)[] array3 = array2; for (int num2 = 0; num2 < array3.Length; num2++) { (MenuElementCosmeticButton, bool, bool, bool, bool, bool, bool, int) tuple = array3[num2]; ((Component)tuple.Item1).transform.SetSiblingIndex(num++); } foreach (var item2 in list2.OrderBy<(MenuElementCosmeticButton, int), int>(((MenuElementCosmeticButton Button, int Sibling) b) => b.Sibling)) { ((Component)item2.Item1).transform.SetSiblingIndex(num++); } Transform cosmeticListTransform = section.cosmeticListTransform; RectTransform val3 = ((cosmeticListTransform != null) ? ((Component)cosmeticListTransform).GetComponent() : null); if ((Object)(object)val3 != (Object)null && !skipRebuild) { LayoutRebuilder.ForceRebuildLayoutImmediate(val3); } } } } internal static class CosmeticTriggerCatalog { internal static IReadOnlyList ValidCustomTypes(CosmeticType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return CosmeticConditionsPopup.ValidCustomTypes(type); } internal static IReadOnlyList ValidOffsetTriggers(CosmeticType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return CosmeticOffsetPopup.ValidOffsetTriggers(type); } } internal static class CosmeticVariantPopup { private static readonly MethodInfo? _updateIcon = AccessTools.Method(typeof(MenuElementCosmeticButton), "UpdateIcon", (Type[])null, (Type[])null); private static readonly FieldInfo? _cosmeticIndex = AccessTools.Field(typeof(MenuElementCosmeticButton), "cosmeticIndex"); private const int Cols = 4; private const float CellSize = 50f; private const float StepX = 58f; private const float StartX = -87f; private const float RowH = 56f; private static readonly Color BgMainColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)); private static readonly Color BgSelectedColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)175)); internal static void Show(MenuElementCosmeticButton repButton, CosmeticGroupButton group) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowNow(repButton, group); }); } private static void ShowNow(MenuElementCosmeticButton repButton, CosmeticGroupButton group) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_012b: Expected O, but got Unknown if ((Object)(object)group == (Object)null || !group.IsActive) { return; } List members = group.Members; MenuPageCosmetics page = (((Object)(object)repButton.cosmeticSection != (Object)null) ? repButton.cosmeticSection.menuPageCosmetics : null); if ((Object)(object)page == (Object)null || (Object)(object)page.sectionButtonPrefab == (Object)null) { return; } REPOPopupPage popup = MenuAPI.CreateREPOPopupPage(GroupTitle(members), false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup); ((Component)popup).gameObject.AddComponent(); for (int i = 0; i < members.Count; i += 4) { int rowStart = i; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) RectTransform val = PopupUI.MakeRow(scrollView); val.sizeDelta = new Vector2(0f, 56f); int num = Mathf.Min(4, members.Count - rowStart); for (int j = 0; j < num; j++) { CosmeticGrouping.Member member = members[rowStart + j]; AddCosmeticCell(val, page, member, new Vector2(-87f + (float)j * 58f, 0f), repButton, group, popup); } return val; }, (rowStart == 0) ? 15f : 6f, 0f); } popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Back", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val, new Vector2(-137f, 0f)); return val; }, 36f, 0f); popup.OpenPage(false); } private static void AddCosmeticCell(RectTransform row, MenuPageCosmetics page, CosmeticGrouping.Member member, Vector2 pos, MenuElementCosmeticButton repButton, CosmeticGroupButton group, REPOPopupPage popup) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0091: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = Object.Instantiate(page.sectionButtonPrefab, (Transform)(object)row); MenuElementCosmeticButton component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return; } component.cosmeticAsset = member.Asset; ((Behaviour)component).enabled = false; if ((Object)(object)component.tintableButton != (Object)null) { ((Component)component.tintableButton).gameObject.SetActive(false); } RectTransform val2 = (RectTransform)val.transform; Vector2 val3 = (val2.pivot = new Vector2(0.5f, 0.5f)); Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.sizeDelta = new Vector2(50f, 50f); val2.anchoredPosition = pos; if ((Object)(object)component.iconImage != (Object)null) { Sprite val6 = (((Object)(object)member.Asset != (Object)null) ? member.Asset.GetIcon(false) : null); if ((Object)(object)val6 != (Object)null) { component.iconImage.sprite = val6; if ((Object)(object)val6.texture != (Object)null) { ((Texture)val6.texture).filterMode = (FilterMode)0; } } ((Graphic)component.iconImage).color = Color.white; ((Component)component.iconImage).gameObject.SetActive(true); } Color baseColor = ResolveBorderBase(member.Asset, component.bgBorder); VariantCell variantCell = val.AddComponent(); variantCell.Button = component.menuButton; variantCell.Border = component.bgBorder; variantCell.BgMain = component.bgMain; variantCell.BaseColor = baseColor; variantCell.Equipped = IsEquipped(member.Asset); CosmeticAsset captured = member.Asset; variantCell.OnClick = delegate { EquipVariant(repButton, group, captured); popup.ClosePage(false); }; variantCell.OnHoverEnter = delegate { PreviewVariant(group, captured); }; variantCell.OnHoverExit = ClearPreview; variantCell.Refresh(); } catch { } } private static Color ResolveBorderBase(CosmeticAsset? asset, RawImage? border) { //IL_0009: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)asset == (Object)null) { return Color.white; } if (BorderTheme.TryResolve(asset, out var theme)) { if (theme.HasSolid) { return theme.Solid; } if ((Object)(object)border != (Object)null && theme.Gradient != null) { border.texture = (Texture)(object)BorderTheme.GradientTexture(theme.Key, theme.Gradient); } return Color.white; } return asset.GetRarityColor(); } private static void EquipVariant(MenuElementCosmeticButton repButton, CosmeticGroupButton group, CosmeticAsset? chosen) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null || (Object)(object)chosen == (Object)null) { return; } bool flag = IsEquipped(chosen); foreach (CosmeticGrouping.Member member in group.Members) { if (IsEquipped(member.Asset)) { instance.CosmeticUnequip(member.Asset, false, false); } } if (!flag) { instance.CosmeticEquip(chosen, false); } instance.Save(); instance.CosmeticPreviewSet(false); instance.CosmeticPlayerUpdateLocal(false, false); if (!flag) { repButton.cosmeticAsset = chosen; try { _cosmeticIndex?.SetValue(repButton, instance.cosmeticAssets.IndexOf(chosen)); } catch { } } try { _updateIcon?.Invoke(repButton, null); } catch { } } private static bool IsEquipped(CosmeticAsset? asset) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null || (Object)(object)asset == (Object)null) { return false; } int num = instance.cosmeticAssets.IndexOf(asset); if (num >= 0) { return instance.cosmeticEquipped.Contains(num); } return false; } private static void PreviewVariant(CosmeticGroupButton group, CosmeticAsset? asset) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null || (Object)(object)asset == (Object)null) { return; } instance.cosmeticEquippedPreview = new List(instance.cosmeticEquipped); instance.colorsEquippedPreview = (int[])instance.colorsEquipped.Clone(); foreach (CosmeticGrouping.Member member in group.Members) { if (IsEquipped(member.Asset)) { instance.CosmeticUnequip(member.Asset, true, false); } } instance.CosmeticEquip(asset, true); instance.CosmeticPreviewSet(true); instance.CosmeticPlayerUpdateLocal(false, false); } internal static void ClearPreview() { MetaManager instance = MetaManager.instance; if (!((Object)(object)instance == (Object)null)) { instance.CosmeticPreviewSet(false); instance.CosmeticPlayerUpdateLocal(false, false); } } private static string GroupTitle(IReadOnlyList members) { List list = new List(TitleWords(members[0].Asset)); for (int i = 1; i < members.Count; i++) { if (list.Count <= 0) { break; } HashSet w = new HashSet(TitleWords(members[i].Asset), StringComparer.OrdinalIgnoreCase); list.RemoveAll((string x) => !w.Contains(x)); } string text = ((list.Count > 0) ? string.Join(" ", list) : CleanName(members[0].Asset)); bool flag = (members[0].Asset?.assetId ?? "").StartsWith("repopride:", StringComparison.OrdinalIgnoreCase); return text + (flag ? " - Pride Colors" : " - Colors"); } private static string[] TitleWords(CosmeticAsset? asset) { return CleanName(asset).Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); } private static string CleanName(CosmeticAsset? asset) { string text = asset?.assetName; if (string.IsNullOrEmpty(text)) { text = ((asset != null) ? ((Object)asset).name : null) ?? "Variants"; } text = Regex.Replace(text, "\\([^)]*\\)", "").Trim(); int num = text.IndexOf('~'); if (num >= 0) { text = text.Substring(0, num).Trim(); } text = Regex.Replace(text, "^\\[[^\\]]*\\]\\s*", "").Trim(); if (!string.IsNullOrEmpty(text)) { return text; } return "Variants"; } } [DefaultExecutionOrder(32000)] internal sealed class CrownForceVisibleGuard : MonoBehaviour { private PlayerCrown? _playerCrown; private CosmeticPlayerCrown? _cosmeticPlayerCrown; internal static CrownForceVisibleGuard? Attach(PlayerCrown playerCrown, GameObject cosmeticGo) { CosmeticPlayerCrown componentInChildren = cosmeticGo.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return null; } CrownForceVisibleGuard crownForceVisibleGuard = ((Component)playerCrown).gameObject.AddComponent(); crownForceVisibleGuard._playerCrown = playerCrown; crownForceVisibleGuard._cosmeticPlayerCrown = componentInChildren; return crownForceVisibleGuard; } private void LateUpdate() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_playerCrown == (Object)null) && !((Object)(object)_playerCrown.crownMesh == (Object)null)) { Transform val = _cosmeticPlayerCrown?.targetMain ?? _playerCrown.defaultPosition; if ((Object)(object)val != (Object)null) { ((Component)_playerCrown).transform.position = val.position; ((Component)_playerCrown).transform.rotation = val.rotation; } ((Component)_playerCrown.crownMesh).gameObject.SetActive(true); } } private void OnDestroy() { if ((Object)(object)_playerCrown?.crownMesh != (Object)null) { ((Component)_playerCrown.crownMesh).gameObject.SetActive(false); } } } internal static class CustomizerStore { private sealed class SaveData { [JsonProperty("overrides")] public Dictionary Overrides { get; set; } = new Dictionary(); } private static readonly string SavePath = BridgePaths.Of("CosmeticOverrides.json"); private static Dictionary _overrides = new Dictionary(); private static Task _lastWrite = Task.CompletedTask; private static readonly Dictionary OverrideToVanilla = new Dictionary { [OverrideCosmeticType.World] = (CosmeticType)0, [OverrideCosmeticType.Hat] = (CosmeticType)0, [OverrideCosmeticType.HeadBottom] = (CosmeticType)30, [OverrideCosmeticType.Ears] = (CosmeticType)17, [OverrideCosmeticType.Eyewear] = (CosmeticType)18, [OverrideCosmeticType.FaceTop] = (CosmeticType)31, [OverrideCosmeticType.FaceBottom] = (CosmeticType)32, [OverrideCosmeticType.HeadTopMesh] = (CosmeticType)5, [OverrideCosmeticType.HeadBottomMesh] = (CosmeticType)6, [OverrideCosmeticType.EyeLidRightMesh] = (CosmeticType)14, [OverrideCosmeticType.EyeLidLeftMesh] = (CosmeticType)15, [OverrideCosmeticType.BodyTop] = (CosmeticType)20, [OverrideCosmeticType.BodyBottom] = (CosmeticType)21, [OverrideCosmeticType.BodyTopOverlay] = (CosmeticType)16, [OverrideCosmeticType.BodyBottomOverlay] = (CosmeticType)23, [OverrideCosmeticType.BodyTopMesh] = (CosmeticType)7, [OverrideCosmeticType.BodyBottomMesh] = (CosmeticType)8, [OverrideCosmeticType.ArmRight] = (CosmeticType)1, [OverrideCosmeticType.ArmLeft] = (CosmeticType)2, [OverrideCosmeticType.ArmRightOverlay] = (CosmeticType)26, [OverrideCosmeticType.ArmLeftOverlay] = (CosmeticType)27, [OverrideCosmeticType.ArmRightMesh] = (CosmeticType)9, [OverrideCosmeticType.ArmLeftMesh] = (CosmeticType)10, [OverrideCosmeticType.LegRight] = (CosmeticType)3, [OverrideCosmeticType.LegLeft] = (CosmeticType)4, [OverrideCosmeticType.FootRight] = (CosmeticType)19, [OverrideCosmeticType.FootLeft] = (CosmeticType)22, [OverrideCosmeticType.LegRightOverlay] = (CosmeticType)28, [OverrideCosmeticType.LegLeftOverlay] = (CosmeticType)29, [OverrideCosmeticType.LegRightMesh] = (CosmeticType)11, [OverrideCosmeticType.LegLeftMesh] = (CosmeticType)12 }; private static readonly Dictionary VanillaToOverride = BuildVanillaToOverride(); internal static void Load() { try { if (!File.Exists(SavePath)) { _overrides = new Dictionary(); return; } string text = File.ReadAllText(SavePath); _overrides = JsonConvert.DeserializeObject(text)?.Overrides ?? new Dictionary(); if (_overrides.Count > 0) { BridgeLog.Trace($"CustomizerStore: loaded {_overrides.Count} override(s)"); } } catch (Exception ex) { BceConsole.LogWarning("CustomizerStore: load failed — " + ex.Message); _overrides = new Dictionary(); } } internal static bool TryGet(string assetId, out CosmeticOverrideData data) { return _overrides.TryGetValue(assetId, out data); } internal static void SetAndApply(CosmeticAsset asset, CosmeticOverrideData incoming) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value)) { value = new CosmeticOverrideData(); if (BridgeIds.IsModdedCosmetic(asset)) { value.OriginalRarity = asset.rarity; value.OriginalType = asset.type; value.OriginalTintable = asset.tintable; } } value.IsModded = incoming.IsModded; value.Rarity = incoming.Rarity; value.Type = incoming.Type; value.FixCollider = incoming.FixCollider; value.FixAnimation = incoming.FixAnimation; value.VanillaEquipAnimationMode = incoming.VanillaEquipAnimationMode; value.Tintable = incoming.Tintable; value.EnableSway = incoming.EnableSway; CosmeticOverrideData cosmeticOverrideData = value; List customTypes = incoming.CustomTypes; cosmeticOverrideData.CustomTypes = ((customTypes != null && customTypes.Count > 0) ? new List(incoming.CustomTypes) : null); CosmeticOverrideData cosmeticOverrideData2 = value; List offsets = incoming.Offsets; cosmeticOverrideData2.Offsets = ((offsets != null && offsets.Count > 0) ? new List(incoming.Offsets) : null); value.Crown = incoming.Crown; value.ShowOnDeathHead = incoming.ShowOnDeathHead; value.FloorPose = incoming.FloorPose; value.FixCrown = incoming.FixCrown; CosmeticOverrideData cosmeticOverrideData3 = value; CosmeticHideConfig hideConditions = incoming.HideConditions; cosmeticOverrideData3.HideConditions = ((hideConditions != null && hideConditions.HasAny) ? incoming.HideConditions.Clone() : null); value.EnableCustomColors = incoming.EnableCustomColors; value.EnableColorAnimations = incoming.EnableColorAnimations; value.UseIsolatedIcon = incoming.UseIsolatedIcon; value.UseFitOffsets = incoming.UseFitOffsets; _overrides[asset.assetId] = value; ApplyToAsset(asset, value); MoreHeadCosmeticMountPatch.RefreshLiveOffsets(asset); MoreHeadCosmeticMountPatch.RefreshLiveSway(asset); Save(); CustomizerSync.BroadcastAll(); BridgeLog.Trace("CosmeticOverride: '" + asset.assetName + "' → isModded=" + (value.IsModded?.ToString() ?? "Default") + ", " + $"rarity={value.Rarity}, type={value.Type}, " + "fixCollider=" + (value.FixCollider?.ToString() ?? "Default") + ", fixAnimation=" + (value.FixAnimation?.ToString() ?? "Default") + ", fixCrown=" + (value.FixCrown?.ToString() ?? "Default") + ", equipAnim=" + (value.VanillaEquipAnimationMode?.ToString() ?? "Default") + ", tintable=" + (value.Tintable?.ToString() ?? "Default") + ", sway=" + (value.EnableSway?.ToString() ?? "Default(off)") + ", " + $"customTypes={value.CustomTypes?.Count ?? 0}, crown={value.Crown != null}"); } internal static (bool fixCollider, bool fixAnimation) GetEffectiveFixes(string? assetId) { bool value = Plugin.RemoveBridgePhysics.Value; bool value2 = Plugin.LoopBridgeAnimation.Value; if (assetId != null && _overrides.TryGetValue(assetId, out CosmeticOverrideData value3)) { if (value3.FixCollider.HasValue) { value = value3.FixCollider.Value; } if (value3.FixAnimation.HasValue) { value2 = value3.FixAnimation.Value; } } return (fixCollider: value, fixAnimation: value2); } internal static bool GetEffectiveFixCrown(string? assetId) { if (assetId != null && _overrides.TryGetValue(assetId, out CosmeticOverrideData value)) { return value.FixCrown == true; } return false; } internal static VanillaEquipAnimationMode GetEffectiveEquipAnimationMode(string? assetId) { VanillaEquipAnimationMode value = Plugin.BridgeEquipAnimationMode.Value; if (assetId != null && _overrides.TryGetValue(assetId, out CosmeticOverrideData value2) && value2.VanillaEquipAnimationMode.HasValue) { value = value2.VanillaEquipAnimationMode.Value; } return value; } internal static SwayMode? GetEffectiveSway(string? assetId) { if (assetId != null && _overrides.TryGetValue(assetId, out CosmeticOverrideData value)) { return value.EnableSway; } return null; } internal static bool IsHiddenOnDeathHead(string? assetId) { if (assetId != null && _overrides.TryGetValue(assetId, out CosmeticOverrideData value)) { return value.ShowOnDeathHead == false; } return false; } internal static DeathHeadFloorPose? GetEffectiveFloorPose(string? assetId) { if (assetId == null || !_overrides.TryGetValue(assetId, out CosmeticOverrideData value)) { return null; } return value.FloorPose; } internal static bool GetEffectiveCustomColors(CosmeticAsset? asset) { if ((Object)(object)asset == (Object)null) { return false; } if (_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value) && value.EnableCustomColors.HasValue) { return value.EnableCustomColors.Value; } if (BridgeIds.IsBridgeAsset(asset)) { return Plugin.EnableBridgeCustomColors.Value; } if (BridgeIds.IsModdedCosmetic(asset)) { return Plugin.EnableModdedCustomColors.Value; } return Plugin.EnableVanillaCustomColors.Value; } internal static bool IsBridgeMeshSwitch(string? assetId) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected I4, but got Unknown if (assetId == null) { return false; } MetaManager instance = MetaManager.instance; if (instance?.cosmeticAssets == null || instance.cosmeticTypeAssets == null) { return false; } CosmeticAsset val = instance.cosmeticAssets.Find((CosmeticAsset a) => (Object)(object)a != (Object)null && a.assetId == assetId); if ((Object)(object)val == (Object)null || !BridgeIds.IsBridgeAsset(val)) { return false; } int num = (int)val.type; if (num >= 0 && num < instance.cosmeticTypeAssets.Count && (Object)(object)instance.cosmeticTypeAssets[num] != (Object)null) { return instance.cosmeticTypeAssets[num].meshSwitch; } return false; } internal static bool GetEffectiveColorAnimations(string? assetId) { if (IsBridgeMeshSwitch(assetId)) { return false; } if (assetId != null && _overrides.TryGetValue(assetId, out CosmeticOverrideData value) && value.EnableColorAnimations.HasValue) { return value.EnableColorAnimations.Value; } return Plugin.EnableBridgeColorAnimations.Value; } internal static bool GetEffectiveColorAnimations(CosmeticAsset? asset) { if ((Object)(object)asset != (Object)null) { return GetEffectiveColorAnimations(asset.assetId); } return false; } internal static bool GetEffectiveIsolatedIcon(string? assetId) { if (assetId == null || !_overrides.TryGetValue(assetId, out CosmeticOverrideData value) || !value.UseIsolatedIcon.HasValue) { return Plugin.UseIsolatedIconRender.Value; } return value.UseIsolatedIcon.Value; } internal static bool GetEffectiveUseFitOffsets(string? assetId) { if (assetId == null || !_overrides.TryGetValue(assetId, out CosmeticOverrideData value) || !value.UseFitOffsets.HasValue) { return Plugin.UseVanillaPositionFixes.Value; } return value.UseFitOffsets.Value; } internal static void ResetAll() { _overrides.Clear(); try { if (File.Exists(SavePath)) { File.Delete(SavePath); } } catch (Exception ex) { BceConsole.LogWarning("CustomizerStore: could not delete save file — " + ex.Message); } } internal static void Reset(CosmeticAsset asset) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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) if (!_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value)) { return; } _overrides.Remove(asset.assetId); if (BridgeIds.IsBridgeAsset(asset)) { HhhCosmeticLoader.ReapplyDefaults(asset); } else { if (value.OriginalRarity.HasValue) { asset.rarity = value.OriginalRarity.Value; } if (value.OriginalType.HasValue) { asset.type = value.OriginalType.Value; } if (value.OriginalTintable.HasValue) { asset.tintable = value.OriginalTintable.Value; } } MoreHeadCosmeticMountPatch.RefreshLiveOffsets(asset); MoreHeadCosmeticMountPatch.RefreshLiveSway(asset); Save(); CustomizerSync.BroadcastAll(); BridgeLog.Trace("CosmeticOverride: '" + asset.assetName + "' reset to defaults"); } internal static void ApplyIfPresent(CosmeticAsset asset) { if (_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value)) { ApplyToAsset(asset, value); } } internal static bool HasOverride(CosmeticAsset asset) { return _overrides.ContainsKey(asset.assetId); } internal static bool HasAnyOverrides() { return _overrides.Count > 0; } internal static bool HasAnyModded() { if (!Plugin.HighlightBridgeCosmetics.Value && _overrides.Count <= 0) { return BridgeIds.HasAnyNonBridgeModded(); } return true; } internal static Dictionary GetAllData() { return new Dictionary(_overrides); } internal static void ImportBatch(Dictionary batch) { foreach (KeyValuePair item in batch) { _overrides[item.Key] = item.Value; } MetaManager instance = MetaManager.instance; if ((Object)(object)instance != (Object)null) { foreach (CosmeticAsset cosmeticAsset in instance.cosmeticAssets) { if (!((Object)(object)cosmeticAsset == (Object)null) && BridgeIds.IsBridgeAsset(cosmeticAsset) && batch.ContainsKey(cosmeticAsset.assetId)) { ApplyToAsset(cosmeticAsset, _overrides[cosmeticAsset.assetId]); } } } Save(); CustomizerSync.BroadcastAll(); if ((Object)(object)instance != (Object)null) { RuntimeConfigApplier.ReinstantiateAllLocalCosmetics(); RuntimeConfigApplier.RefreshCosmeticsMenu(); } BridgeLog.Trace($"CustomizerStore: imported {batch.Count} override(s)"); } internal static MainCosmeticCategory GetMainForType(OverrideCosmeticType t) { switch (t) { case OverrideCosmeticType.Hat: case OverrideCosmeticType.HeadBottom: case OverrideCosmeticType.Ears: case OverrideCosmeticType.Eyewear: case OverrideCosmeticType.FaceTop: case OverrideCosmeticType.FaceBottom: case OverrideCosmeticType.HeadTopMesh: case OverrideCosmeticType.HeadBottomMesh: case OverrideCosmeticType.EyeLidRightMesh: case OverrideCosmeticType.EyeLidLeftMesh: return MainCosmeticCategory.Head; case OverrideCosmeticType.BodyTop: case OverrideCosmeticType.BodyBottom: case OverrideCosmeticType.BodyTopOverlay: case OverrideCosmeticType.BodyBottomOverlay: case OverrideCosmeticType.BodyTopMesh: case OverrideCosmeticType.BodyBottomMesh: return MainCosmeticCategory.Body; case OverrideCosmeticType.ArmRight: case OverrideCosmeticType.ArmLeft: case OverrideCosmeticType.ArmRightOverlay: case OverrideCosmeticType.ArmLeftOverlay: case OverrideCosmeticType.ArmRightMesh: case OverrideCosmeticType.ArmLeftMesh: return MainCosmeticCategory.Arms; case OverrideCosmeticType.LegRight: case OverrideCosmeticType.LegLeft: case OverrideCosmeticType.FootRight: case OverrideCosmeticType.FootLeft: case OverrideCosmeticType.LegRightOverlay: case OverrideCosmeticType.LegLeftOverlay: case OverrideCosmeticType.LegRightMesh: case OverrideCosmeticType.LegLeftMesh: return MainCosmeticCategory.Legs; default: return MainCosmeticCategory.World; } } internal static bool IsModdedForAsset(CosmeticAsset? asset) { if ((Object)(object)asset == (Object)null) { return false; } if (_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value) && value.IsModded.HasValue) { if (value.IsModded.Value) { return BridgeIds.IsBridgeAsset(asset); } return false; } if (BridgeIds.IsBridgeAsset(asset)) { return Plugin.HighlightBridgeCosmetics.Value; } return false; } internal static bool IsNonBridgeModdedForAsset(CosmeticAsset? asset) { if ((Object)(object)asset == (Object)null || !BridgeIds.IsModdedCosmetic(asset)) { return false; } if (_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value) && value.IsModded.HasValue) { return value.IsModded.Value; } return Plugin.HighlightModdedCosmetics.Value; } internal static OverrideCosmeticType GetEffectiveType(CosmeticAsset asset) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (HhhCosmeticLoader.IsWorldAsset(asset)) { return OverrideCosmeticType.World; } if (!VanillaToOverride.TryGetValue(asset.type, out var value)) { return OverrideCosmeticType.Hat; } return value; } internal static OverrideCosmeticType GetOriginalType(CosmeticAsset asset) { //IL_003b: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)asset == (Object)null) { return OverrideCosmeticType.Hat; } if (HhhCosmeticLoader.IsWorldAsset(asset)) { return OverrideCosmeticType.World; } CosmeticOverrideData value; CosmeticType key = ((_overrides.TryGetValue(asset.assetId, out value) && value.OriginalType.HasValue) ? value.OriginalType.Value : asset.type); if (!VanillaToOverride.TryGetValue(key, out var value2)) { return OverrideCosmeticType.Hat; } return value2; } internal static MainCosmeticCategory GetCurrentMain(CosmeticAsset asset) { return GetMainForType(GetEffectiveType(asset)); } internal static (CosmeticType cosmeticType, bool isWorld) MapOverrideToVanilla(OverrideCosmeticType t) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) CosmeticType value; CosmeticType item = (CosmeticType)(OverrideToVanilla.TryGetValue(t, out value) ? ((int)value) : 0); return (cosmeticType: item, isWorld: t == OverrideCosmeticType.World); } internal static (CosmeticType cosmeticType, bool isWorld) GetRemoteFallbackType(CosmeticAsset asset) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (BridgeIds.IsBridgeAsset(asset) && HhhCosmeticLoader.TryGetOriginalType(asset.assetId, out var type)) { return MapOverrideToVanilla(type); } if (_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value) && value.OriginalType.HasValue) { return (cosmeticType: value.OriginalType.Value, isWorld: false); } return (cosmeticType: asset.type, isWorld: HhhCosmeticLoader.IsWorldAsset(asset)); } internal static bool GetRemoteFallbackTintable(CosmeticAsset asset) { if (HhhCosmeticLoader.TryGetDefaultTintable(asset, out var tintable)) { return tintable; } if (_overrides.TryGetValue(asset.assetId, out CosmeticOverrideData value) && value.OriginalTintable.HasValue) { return value.OriginalTintable.Value; } return asset.tintable; } private static Dictionary BuildVanillaToOverride() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (KeyValuePair item in OverrideToVanilla) { if (item.Key != OverrideCosmeticType.World) { dictionary[item.Value] = item.Key; } } return dictionary; } internal static void ApplyToAsset(CosmeticAsset asset, CosmeticOverrideData data) { //IL_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_006f: 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 (data.Rarity.HasValue) { asset.rarity = data.Rarity.Value; } else if (BridgeIds.IsBridgeAsset(asset)) { asset.rarity = Plugin.BridgeDefaultRarity.Value; } if (data.Type.HasValue) { (CosmeticType cosmeticType, bool isWorld) tuple = MapOverrideToVanilla(data.Type.Value); CosmeticType item = tuple.cosmeticType; bool item2 = tuple.isWorld; asset.type = item; if (item2) { HhhCosmeticLoader.WorldAssetIds.Add(asset.assetId); } else { HhhCosmeticLoader.WorldAssetIds.Remove(asset.assetId); } } bool tintable; if (data.Tintable.HasValue) { asset.tintable = data.Tintable.Value; } else if (BridgeIds.IsBridgeAsset(asset) && HhhCosmeticLoader.TryGetDefaultTintable(asset, out tintable)) { asset.tintable = tintable; } else if (data.OriginalTintable.HasValue) { asset.tintable = data.OriginalTintable.Value; } } private static void Save() { string json = JsonConvert.SerializeObject((object)new SaveData { Overrides = _overrides }, (Formatting)1); _lastWrite = AtomicJson.QueueWrite(_lastWrite, SavePath, json, "CustomizerStore: save failed"); } internal static void FlushPendingWrites() { try { _lastWrite.Wait(TimeSpan.FromSeconds(2.0)); } catch { } } } internal static class DeathHeadFloorPosePopup { private static readonly string[] OnOffOptions = new string[2] { "On", "Off" }; private static readonly string[] ScaleOptions = BuildScaleOptions(); private static string[] BuildScaleOptions() { List list = new List(); for (float num = 0.05f; num <= 2.0001f; num += 0.05f) { list.Add(num.ToString("F2", CultureInfo.InvariantCulture)); } return list.ToArray(); } internal static void Show(DeathHeadFloorPose? existing, Action onPreview, Action onDone, Action onClose, Transform? parentPopupTransform) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowNow(existing, onPreview, onDone, onClose, parentPopupTransform); }); } private static void ShowNow(DeathHeadFloorPose? existing, Action onPreview, Action onDone, Action onClose, Transform? parentPopupTransform) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Expected O, but got Unknown DeathHeadFloorPose pose = existing?.Clone() ?? new DeathHeadFloorPose(); pose.MigrateLegacy(); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Impact Pose", false, false, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup, parentPopupTransform); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_004a: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("React when alive", "", (Action)delegate(string opt) { pose.ReactWhenAlive = opt == "On"; Preview(); }, scrollView, OnOffOptions, pose.ReactWhenAlive ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, 15f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_004a: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("React when dead", "", (Action)delegate(string opt) { pose.ReactWhenDead = opt == "On"; Preview(); }, scrollView, OnOffOptions, pose.ReactWhenDead ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, 0f, 0f); PopupUI.AddFloatSlider(popup, "Pos X", CosmeticOffsetEntryPopup.PosOptions, pose.PosX, delegate(float v) { pose.PosX = v; Preview(); }, 10f); PopupUI.AddFloatSlider(popup, "Pos Y", CosmeticOffsetEntryPopup.PosOptions, pose.PosY, delegate(float v) { pose.PosY = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Pos Z", CosmeticOffsetEntryPopup.PosOptions, pose.PosZ, delegate(float v) { pose.PosZ = v; Preview(); }); PopupUI.AddIntSlider(popup, "Rot X", CosmeticOffsetEntryPopup.RotOptions, (int)pose.RotX, delegate(float v) { pose.RotX = v; Preview(); }, 10f); PopupUI.AddIntSlider(popup, "Rot Y", CosmeticOffsetEntryPopup.RotOptions, (int)pose.RotY, delegate(float v) { pose.RotY = v; Preview(); }); PopupUI.AddIntSlider(popup, "Rot Z", CosmeticOffsetEntryPopup.RotOptions, (int)pose.RotZ, delegate(float v) { pose.RotZ = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Scale X", ScaleOptions, pose.ScaleX, delegate(float v) { pose.ScaleX = v; Preview(); }, 10f); PopupUI.AddFloatSlider(popup, "Scale Y", ScaleOptions, pose.ScaleY, delegate(float v) { pose.ScaleY = v; Preview(); }); PopupUI.AddFloatSlider(popup, "Scale Z", ScaleOptions, pose.ScaleZ, delegate(float v) { pose.ScaleZ = v; Preview(); }); PopupUI.AddIntSlider(popup, "Lerp Speed", CosmeticOffsetEntryPopup.SpeedOptions, Mathf.Clamp((int)pose.LerpSpeed, 1, 10), delegate(float v) { pose.LerpSpeed = v; Preview(); }, 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { popup.ClosePage(false); onClose(); }, (Transform)(object)val, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Done", (Action)delegate { popup.ClosePage(false); onDone(pose); onClose(); }, (Transform)(object)val, new Vector2(58f, 0f)); return val; }, 10f, 0f); Preview(); popup.OpenPage(true); void Preview() { onPreview(pose); } } } internal sealed class BridgeDeathHeadBlocked : MonoBehaviour { private const float CheckInterval = 0.1f; private const float BlockedCooldown = 0.25f; private const float SwitchDebounce = 0.1f; private const float ProbeRadiusMin = 0.03f; private const float ProbeRadiusMax = 0.1f; private const float SpringStiffness = 120f; private const float SpringDamping = 14f; private const float SpringKickVelocity = 6f; private const float MaxBlockedDuration = 4f; private PlayerDeathHead? _deathHead; private Transform _target; private Transform _anchor; private DeathHeadFloorPose _pose; private Vector3 _anchorLocalCenter; private float _worldRadius; private bool _valid; private LayerMask _layerMask; private float _springPos; private float _springVel; private bool _blocked; private float _checkTimer; private float _cooldownTimer; private float _switchTimer; private float _blockedDuration; private Vector3 _refPos; private Vector3 _refEuler; private Vector3 _refScale; internal void Init(PlayerDeathHead deathHead, Transform target, DeathHeadFloorPose pose) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: 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) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) _deathHead = deathHead; _target = target; _anchor = (Transform)(((Object)(object)target.parent != (Object)null) ? ((object)target.parent) : ((object)target)); _pose = pose; _pose.MigrateLegacy(); _refPos = target.localPosition; _refEuler = target.localEulerAngles; _refScale = target.localScale; if (TryGetWorldBounds(out var bounds)) { Vector3 val = ((Bounds)(ref bounds)).center + Vector3.up * ((Bounds)(ref bounds)).extents.y; _anchorLocalCenter = _anchor.InverseTransformPoint(val); float num = Mathf.Max(new float[3] { ((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.y, ((Bounds)(ref bounds)).extents.z }); _worldRadius = Mathf.Clamp(num * 0.25f, 0.03f, 0.1f); _valid = num > 0.0001f; } _layerMask = LayerMask.op_Implicit(LayerMask.op_Implicit(SemiFunc.LayerMaskGetPhysGrabObject()) + LayerMask.GetMask(new string[1] { "Default" }) + LayerMask.GetMask(new string[1] { "Enemy" })); } private void LateUpdate() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) if (!_valid || (Object)(object)_deathHead == (Object)null || _pose == null || !_pose.ReactWhenDead) { return; } if (!_deathHead.triggered) { if (_springPos > 0.001f || Mathf.Abs(_springVel) > 0.001f) { _target.localPosition = _refPos; _target.localRotation = Quaternion.Euler(_refEuler); _target.localScale = _refScale; } _springPos = 0f; _springVel = 0f; _blocked = false; _blockedDuration = 0f; return; } if (_cooldownTimer > 0f) { _cooldownTimer -= Time.deltaTime; } if (_switchTimer > 0f) { _switchTimer -= Time.deltaTime; } bool blocked = _blocked; if (_switchTimer <= 0f) { _checkTimer -= Time.deltaTime; if (_checkTimer <= 0f) { _checkTimer = 0.1f; if (CheckBlocked()) { _blocked = true; _cooldownTimer = 0.25f; } else if (_cooldownTimer <= 0f) { _blocked = false; } } } if (_blocked) { _blockedDuration += Time.deltaTime; if (_blockedDuration >= 4f) { _blocked = false; _cooldownTimer = 0f; _blockedDuration = 0f; } } else { _blockedDuration = 0f; } if (_blocked != blocked) { _switchTimer = 0.1f; _springVel += (_blocked ? 6f : (-6f)); } float num = (_blocked ? 1f : 0f); float num2 = (num - _springPos) * 120f - _springVel * 14f; _springVel += num2 * Time.deltaTime; _springPos += _springVel * Time.deltaTime; float num3 = Mathf.Clamp01(_springPos); if (num3 <= 0f) { _refPos = _target.localPosition; _refEuler = _target.localEulerAngles; _refScale = _target.localScale; if (!_blocked && Mathf.Abs(_springVel) < 0.05f) { _springPos = 0f; _springVel = 0f; } } else { _target.localPosition = Vector3.Lerp(_refPos, new Vector3(_pose.PosX, _pose.PosY, _pose.PosZ), num3); _target.localRotation = Quaternion.Slerp(Quaternion.Euler(_refEuler), Quaternion.Euler(_pose.RotX, _pose.RotY, _pose.RotZ), num3); _target.localScale = Vector3.Lerp(_refScale, new Vector3(_pose.ScaleX, _pose.ScaleY, _pose.ScaleZ), num3); } } private bool CheckBlocked() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = _anchor.TransformPoint(_anchorLocalCenter); Collider[] array = Physics.OverlapSphere(val, _worldRadius, LayerMask.op_Implicit(_layerMask), (QueryTriggerInteraction)2); Collider[] array2 = array; foreach (Collider val2 in array2) { if (!((Object)(object)val2 == (Object)null) && !(((Object)val2).name == "Health Grab") && !((Object)(object)((Component)val2).GetComponentInParent() != (Object)null) && !((Object)(object)((Component)val2).GetComponentInParent() != (Object)null)) { return true; } } return false; } private bool TryGetWorldBounds(out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) bounds = default(Bounds); Renderer[] componentsInChildren = ((Component)_target).GetComponentsInChildren(true); bool flag = false; Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } if (flag) { return true; } Renderer[] array2 = componentsInChildren; foreach (Renderer val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { if (!flag) { bounds = val2.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val2.bounds); } } } return flag; } } internal sealed class BridgeDeathHeadGameplayMount : MonoBehaviour { private PlayerDeathHead? _deathHead; private readonly List _mounted = new List(); internal static BridgeDeathHeadGameplayMount GetOrAdd(PlayerDeathHead deathHead) { BridgeDeathHeadGameplayMount component = ((Component)deathHead).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } component = ((Component)deathHead).gameObject.AddComponent(); component._deathHead = deathHead; return component; } internal void RecolorMountedBridge() { if ((Object)(object)_deathHead == (Object)null) { return; } PlayerCosmetics playerCosmetics = _deathHead.playerCosmetics; if ((Object)(object)playerCosmetics == (Object)null) { return; } int actorNumber; bool isRemote = AvatarIdentity.TryGetRemoteActor(playerCosmetics, out actorNumber); RecolorVanillaDeathHead(playerCosmetics, isRemote); foreach (GameObject item in _mounted) { if (!((Object)(object)item == (Object)null)) { CosmeticAsset val = item.GetComponentInChildren(true)?.cosmeticAsset; if (!((Object)(object)val == (Object)null)) { ApplyBridgeColors(item, val, isRemote); } } } } internal void Remount() { ClearMounts(); if ((Object)(object)_deathHead == (Object)null) { return; } PlayerCosmetics playerCosmetics = _deathHead.playerCosmetics; if ((Object)(object)playerCosmetics == (Object)null) { return; } int actorNumber; bool isRemote = AvatarIdentity.TryGetRemoteActor(playerCosmetics, out actorNumber); PlayerCosmetics componentInChildren = ((Component)_deathHead).GetComponentInChildren(true); PlayerCosmetics mainPc = (((Object)(object)_deathHead.playerAvatar != (Object)null) ? _deathHead.playerAvatar.playerCosmetics : null) ?? playerCosmetics; List list = CollectBridgeAssets(mainPc, isRemote, actorNumber); foreach (CosmeticAsset item in list) { MountSingle(item, componentInChildren, playerCosmetics, isRemote, actorNumber); } MoreHeadCosmeticMountPatch.InvokeConditionsSetup(playerCosmetics); RecolorVanillaDeathHead(playerCosmetics, isRemote); ApplyModdedDeathHeadVisibility(playerCosmetics, isRemote, actorNumber); } private static void ApplyModdedDeathHeadVisibility(PlayerCosmetics pc, bool isRemote, int actorNumber) { List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(pc); if (equippedCosmetics == null) { return; } foreach (Cosmetic item in equippedCosmetics) { Process(((Object)(object)item != (Object)null) ? ((Component)item).gameObject : null, ((Object)(object)item != (Object)null) ? MoreHeadCosmeticMountPatch.GetCosmeticAsset(item) : null); } void Process(GameObject? go, CosmeticAsset? asset) { if (!((Object)(object)go == (Object)null) && !((Object)(object)asset == (Object)null) && BridgeIds.IsModdedCosmetic(asset)) { bool flag = !IsHiddenOnDeathHead(asset, isRemote, actorNumber); if (go.activeSelf != flag) { go.SetActive(flag); } } } } internal void ClearMounts() { foreach (GameObject item in _mounted) { if (!((Object)(object)item == (Object)null)) { item.SetActive(false); Object.Destroy((Object)(object)item); } } _mounted.Clear(); if ((Object)(object)_deathHead?.playerCosmetics != (Object)null) { MoreHeadCosmeticMountPatch.InvokeConditionsSetup(_deathHead.playerCosmetics); } } private static List CollectBridgeAssets(PlayerCosmetics mainPc, bool isRemote, int actorNumber) { List list = new List(); List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(mainPc); if (equippedCosmetics != null) { foreach (Cosmetic item in equippedCosmetics) { if (!((Object)(object)item == (Object)null)) { CosmeticAsset cosmeticAsset = MoreHeadCosmeticMountPatch.GetCosmeticAsset(item); if (IsEligible(cosmeticAsset, isRemote, actorNumber)) { list.Add(cosmeticAsset); } } } } return list; } private static bool IsEligible(CosmeticAsset? asset, bool isRemote, int actorNumber) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)asset != (Object)null && BridgeIds.IsBridgeAsset(asset) && DeathHeadPrefabProvider.SupportedTypes.Contains(EffectiveType(asset, isRemote, actorNumber))) { return !IsHiddenOnDeathHead(asset, isRemote, actorNumber); } return false; } private static CosmeticType EffectiveType(CosmeticAsset asset, bool isRemote, int actorNumber) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (!isRemote) { return asset.type; } CustomizerSync.TryGetRemote(actorNumber, asset.assetId, out BridgeSyncPayload data); return MoreHeadCosmeticMountPatch.GetRemoteEffectiveType(asset, data).cosmeticType; } internal static bool IsHiddenOnDeathHead(CosmeticAsset asset, bool isRemote, int actorNumber) { if (isRemote) { if (CustomizerSync.TryGetRemote(actorNumber, asset.assetId, out BridgeSyncPayload data)) { if (data == null) { return false; } return data.ShowOnDeathHead == false; } return false; } return CustomizerStore.IsHiddenOnDeathHead(asset.assetId); } private void MountSingle(CosmeticAsset asset, PlayerCosmetics? dhPc, PlayerCosmetics mainPc, bool isRemote, int actorNumber) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) GameObject val = ((PrefabRef)(object)asset.prefab)?.Prefab; if ((Object)(object)val == (Object)null) { return; } try { CosmeticType val2 = EffectiveType(asset, isRemote, actorNumber); Transform val3 = null; if (dhPc?.cosmeticParents != null) { foreach (CosmeticParent cosmeticParent in dhPc.cosmeticParents) { if (cosmeticParent.cosmeticType == val2 && (Object)(object)cosmeticParent.parent != (Object)null) { val3 = cosmeticParent.parent; break; } } } if (val3 == null) { val3 = ((Component)_deathHead).transform; } GameObject val4 = Object.Instantiate(val, val3, false); MoreHeadCosmeticMountPatch.Mount(val4, val3, val); BridgeSyncPayload data = null; if (isRemote) { CustomizerSync.TryGetRemote(actorNumber, asset.assetId, out data); } CosmeticPrefabFixer.FixInstance(val4, asset.assetId, (!isRemote) ? ((bool?)null) : data?.FixAnimation, isRemote); bool? flag = (isRemote ? new bool?(data?.Tintable ?? CustomizerStore.GetRemoteFallbackTintable(asset)) : ((bool?)null)); if (flag != false) { BridgeTintHelper.InjectBridgeTintMaterials(val4, asset, flag); } ApplyBridgeColors(val4, asset, isRemote); List list = null; List customTypes = null; DeathHeadFloorPose deathHeadFloorPose = null; CosmeticOverrideData data2; if (isRemote) { list = data?.Offsets; customTypes = data?.CustomTypes; deathHeadFloorPose = data?.FloorPose; } else if (CustomizerStore.TryGet(asset.assetId, out data2)) { list = data2?.Offsets; customTypes = data2?.CustomTypes; deathHeadFloorPose = data2?.FloorPose; } List offsets = ((list != null && list.Count > 0) ? list.OrderBy((CosmeticOffsetEntry o) => ((int)o.TriggerType == 2) ? 1 : 0).ToList() : null); MoreHeadCosmeticMountPatch.InjectOffsetConditions(val4, asset, mainPc, offsets, customTypes); SwayMode? effectiveSway = CustomizerStore.GetEffectiveSway(asset.assetId); bool flag2; if (effectiveSway.HasValue) { SwayMode valueOrDefault = effectiveSway.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 2u) { flag2 = true; goto IL_0267; } } flag2 = false; goto IL_0267; IL_0267: if (flag2 && val4.GetComponentsInChildren(true).Length == 0) { Cosmetic component = val4.GetComponent(); if ((Object)(object)component != (Object)null) { BridgeSwaySpring bridgeSwaySpring = val4.AddComponent(); bridgeSwaySpring.Init(component, CosmeticSwayHelper.SwayModeToFactor(effectiveSway)); } } if ((Object)(object)_deathHead != (Object)null && deathHeadFloorPose != null && (deathHeadFloorPose.ReactWhenDead || deathHeadFloorPose.Enabled == true)) { val4.AddComponent().Init(_deathHead, val4.transform, deathHeadFloorPose); } _mounted.Add(val4); } catch (Exception ex) { BridgeLog.Trace("BridgeDeathHeadGameplayMount: failed to mount '" + asset.assetId + "': " + ex.Message); } } private void ApplyBridgeColors(GameObject go, CosmeticAsset asset, bool isRemote) { BridgeTintMaterial[] componentsInChildren = go.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return; } string assetId = asset.assetId; PerCosmeticColorSyncComponent perCosmeticColorSyncComponent = (isRemote ? ResolveOwnerSync() : null); BridgeTintMaterial[] array = componentsInChildren; foreach (BridgeTintMaterial bridgeTintMaterial in array) { if ((Object)(object)bridgeTintMaterial == (Object)null) { continue; } bool num; if (!isRemote) { num = PerCosmeticColors.ApplyLocalToBridgeTint(bridgeTintMaterial, assetId); } else { if (!((Object)(object)perCosmeticColorSyncComponent != (Object)null)) { goto IL_0060; } num = perCosmeticColorSyncComponent.ApplyRemoteToBridgeTint(bridgeTintMaterial, assetId); } if (num) { continue; } goto IL_0060; IL_0060: bridgeTintMaterial.RestoreOriginalColor(); } AttachOrRefreshAnimator(go, asset, isRemote, perCosmeticColorSyncComponent); } private static void AttachOrRefreshAnimator(GameObject go, CosmeticAsset asset, bool isRemote, PerCosmeticColorSyncComponent? ownerSync) { AnimSet set = default(AnimSet); if (PerCosmeticColors.FeatureEnabled && Plugin.EnableBridgeColorAnimations.Value) { set = ((!isRemote) ? PerCosmeticColors.GetAnimSet(asset.assetId) : (((Object)(object)ownerSync != (Object)null) ? ownerSync.GetRemoteAnimSet(asset.assetId) : default(AnimSet))); } BridgeColorAnimator component = go.GetComponent(); if (set.Any) { BridgeColorAnimator bridgeColorAnimator = component ?? go.AddComponent(); bridgeColorAnimator.Init(go, set); if (bridgeColorAnimator.IsEmpty) { bridgeColorAnimator.Stop(); } } else if ((Object)(object)component != (Object)null) { component.Stop(); } } private void RecolorVanillaDeathHead(PlayerCosmetics deathHeadPc, bool isRemote) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected I4, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) List playerMaterials = deathHeadPc.playerMaterials; if (playerMaterials == null) { return; } PerCosmeticColorSyncComponent perCosmeticColorSyncComponent = (isRemote ? ResolveOwnerSync() : null); if (isRemote) { perCosmeticColorSyncComponent?.ApplyVanillaOverridesTo(playerMaterials); } else { PerCosmeticColors.ApplyVanillaOverridesTo(playerMaterials); } List list = MetaManager.instance?.colors; if (list == null) { return; } int[] colorsEquipped = deathHeadPc.colorsEquipped; foreach (PlayerMaterial item in playerMaterials) { if ((Object)(object)item == (Object)null || (Object)(object)item.cosmetic != (Object)null || !item.tintable) { continue; } string text = FindEquippedAssetId(deathHeadPc, item.cosmeticType); if (text == null) { continue; } int num = (int)item.cosmeticType; int fallbackTypeColor = ((colorsEquipped != null && num >= 0 && num < colorsEquipped.Length) ? colorsEquipped[num] : (-1)); Color color2; if (isRemote) { if (!((Object)(object)perCosmeticColorSyncComponent == (Object)null)) { if (perCosmeticColorSyncComponent.TryGetRemoteCustomColor(text, out var color)) { VanillaTintHelper.ApplyCustomRGB(item, color); } else { ApplyIndex(item, perCosmeticColorSyncComponent.GetEffectiveRemoteColorIndex(text, fallbackTypeColor), list.Count); } } } else if (Plugin.EnableVanillaCustomColors.Value && PerCosmeticColors.TryGetCustomColor(text, out color2)) { VanillaTintHelper.ApplyCustomRGB(item, color2); } else { ApplyIndex(item, PerCosmeticColors.GetEffectiveColorIndex(text, fallbackTypeColor), list.Count); } } } private static void ApplyIndex(PlayerMaterial pm, int colorIdx, int colorCount) { if (colorIdx >= 0 && colorIdx < colorCount) { pm.Setup(); pm.ColorSet(PerCosmeticColors.PropAlbedo, PerCosmeticColors.PropEmission, PerCosmeticColors.PropFresnel, colorIdx); } } private static string? FindEquippedAssetId(PlayerCosmetics pc, CosmeticType type) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(pc); if (equippedCosmetics == null) { return null; } foreach (Cosmetic item in equippedCosmetics) { if (!((Object)(object)item == (Object)null)) { CosmeticAsset cosmeticAsset = MoreHeadCosmeticMountPatch.GetCosmeticAsset(item); if ((Object)(object)cosmeticAsset != (Object)null && cosmeticAsset.type == type) { return cosmeticAsset.assetId; } } } return null; } private PerCosmeticColorSyncComponent? ResolveOwnerSync() { PlayerCosmetics val = (((Object)(object)_deathHead != (Object)null && (Object)(object)_deathHead.playerAvatar != (Object)null) ? _deathHead.playerAvatar.playerCosmetics : null); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent(); } private void OnDestroy() { foreach (GameObject item in _mounted) { if (!((Object)(object)item == (Object)null)) { item.SetActive(false); Object.Destroy((Object)(object)item); } } _mounted.Clear(); } } internal static class DeathHeadColorizer { internal static void ApplyBodyColors(GameObject model, PlayerCosmetics? source) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected I4, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected I4, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) int[] array = source?.colorsEquipped; List list = MetaManager.instance?.colors; if (array == null || list == null) { return; } PlayerMaterial[] componentsInChildren = model.GetComponentsInChildren(true); PlayerMaterial[] array2 = componentsInChildren; foreach (PlayerMaterial val in array2) { if ((Object)(object)val == (Object)null) { continue; } int num = (int)val.cosmeticType; if (num >= 0 && num < array.Length) { int num2 = array[num]; string text = FindEquippedAssetId(source, val.cosmeticType); if (text != null) { num2 = PerCosmeticColors.GetEffectiveColorIndex(text, num2); } ApplyColor(val, num2, list.Count); } } bool flag = (Object)(object)source != (Object)null && AvatarIdentity.IsRemoteMini(source); if (flag) { ((Component)source).GetComponent()?.ApplyVanillaOverridesTo(componentsInChildren); } else { PerCosmeticColors.ApplyVanillaOverridesTo(componentsInChildren); } PerCosmeticColorSyncComponent perCosmeticColorSyncComponent = (flag ? ((Component)source).GetComponent() : null); PlayerMaterial[] array3 = componentsInChildren; foreach (PlayerMaterial val2 in array3) { if ((Object)(object)val2 == (Object)null || (Object)(object)val2.cosmetic != (Object)null) { continue; } string text2 = FindEquippedAssetId(source, val2.cosmeticType); if (text2 == null) { continue; } int num3 = (int)val2.cosmeticType; int fallbackTypeColor = ((num3 >= 0 && num3 < array.Length) ? array[num3] : (-1)); Color color2; if (flag) { if (!((Object)(object)perCosmeticColorSyncComponent == (Object)null)) { if (perCosmeticColorSyncComponent.TryGetRemoteCustomColor(text2, out var color)) { VanillaTintHelper.ApplyCustomRGB(val2, color); } else { ApplyColor(val2, perCosmeticColorSyncComponent.GetEffectiveRemoteColorIndex(text2, fallbackTypeColor), list.Count); } } } else if (Plugin.EnableVanillaCustomColors.Value && PerCosmeticColors.TryGetCustomColor(text2, out color2)) { VanillaTintHelper.ApplyCustomRGB(val2, color2); } else { ApplyColor(val2, PerCosmeticColors.GetEffectiveColorIndex(text2, fallbackTypeColor), list.Count); } } } internal static void ApplyCosmeticColor(GameObject go, CosmeticAsset asset, PlayerCosmetics? source) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected I4, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) int[] array = source?.colorsEquipped; List list = MetaManager.instance?.colors; if (list == null) { return; } int fallbackTypeColor = -1; if (array != null) { int num = (int)asset.type; if (num >= 0 && num < array.Length) { fallbackTypeColor = array[num]; } } PerCosmeticColorSyncComponent perCosmeticColorSyncComponent = (((Object)(object)source != (Object)null && AvatarIdentity.IsRemoteMini(source)) ? ((Component)source).GetComponent() : null); int colorIdx = (((Object)(object)perCosmeticColorSyncComponent != (Object)null) ? perCosmeticColorSyncComponent.GetEffectiveRemoteColorIndex(asset.assetId, fallbackTypeColor) : PerCosmeticColors.GetEffectiveColorIndex(asset.assetId, fallbackTypeColor)); PlayerMaterial[] componentsInChildren = go.GetComponentsInChildren(true); PlayerMaterial[] array2 = componentsInChildren; foreach (PlayerMaterial val in array2) { if (!((Object)(object)val == (Object)null)) { val.cosmeticType = asset.type; ApplyColor(val, colorIdx, list.Count); } } if (BridgeIds.IsBridgeAsset(asset)) { return; } Color color = default(Color); bool num2; if (!((Object)(object)perCosmeticColorSyncComponent != (Object)null)) { if (!Plugin.EnableVanillaCustomColors.Value) { return; } num2 = PerCosmeticColors.TryGetCustomColor(asset.assetId, out color); } else { num2 = perCosmeticColorSyncComponent.TryGetRemoteCustomColor(asset.assetId, out color); } if (!num2) { return; } PlayerMaterial[] array3 = componentsInChildren; foreach (PlayerMaterial val2 in array3) { if ((Object)(object)val2 != (Object)null) { VanillaTintHelper.ApplyCustomRGB(val2, color); } } } private static void ApplyColor(PlayerMaterial pm, int colorIdx, int colorCount) { if (colorIdx >= 0 && colorIdx < colorCount) { pm.Setup(); pm.ColorSet(PerCosmeticColors.PropAlbedo, PerCosmeticColors.PropEmission, PerCosmeticColors.PropFresnel, colorIdx); } } private static string? FindEquippedAssetId(PlayerCosmetics? pc, CosmeticType type) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pc == (Object)null) { return null; } List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(pc); if (equippedCosmetics == null) { return null; } foreach (Cosmetic item in equippedCosmetics) { if (!((Object)(object)item == (Object)null)) { CosmeticAsset cosmeticAsset = MoreHeadCosmeticMountPatch.GetCosmeticAsset(item); if ((Object)(object)cosmeticAsset != (Object)null && cosmeticAsset.type == type) { return cosmeticAsset.assetId; } } } return null; } } internal sealed class DeathHeadCosmeticMounter { private readonly IReadOnlyDictionary _parentByType; private readonly Transform? _fallbackAnchor; private readonly PlayerCosmetics? _colorSource; private readonly List _mounted = new List(); private readonly List _hiddenBaseMeshes = new List(); private readonly Dictionary _cloneAssetIds = new Dictionary(); internal Func? AnimOverride; internal GameObject? ConfiguredMount { get; private set; } internal DeathHeadCosmeticMounter(IReadOnlyDictionary parentByType, Transform? fallbackAnchor, PlayerCosmetics? colorSource) { _parentByType = parentByType; _fallbackAnchor = fallbackAnchor; _colorSource = colorSource; } internal void Mount(List<(GameObject liveGo, CosmeticAsset asset)> cosmetics, GameObject? configuredLiveGo) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Clear(); foreach (var (val, val2) in cosmetics) { if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { continue; } bool isConfigured = (Object)(object)val == (Object)(object)configuredLiveGo; CosmeticType val3 = OwnerType(val2); if (!_parentByType.TryGetValue(val3, out CosmeticParent value) || (Object)(object)value?.parent == (Object)null) { if ((Object)(object)_fallbackAnchor != (Object)null) { MountDecorativeClone(val, _fallbackAnchor, isConfigured); } continue; } bool flag = value.baseMeshParents != null && value.baseMeshParents.Count > 0; bool flag2 = !flag && value.baseMeshes != null && value.baseMeshes.Count > 0; if (flag) { if (BridgeIds.IsBridgeAsset(val2)) { MountBridgeMeshCosmetic(val, val3, value, isConfigured); } else { MountMeshCosmetic(val2, val3, value, isConfigured); } } else if (!flag2) { MountDecorativeClone(val, value.parent, isConfigured); } } } internal void Clear() { foreach (GameObject item in _mounted) { if ((Object)(object)item != (Object)null) { Object.Destroy((Object)(object)item); } } _mounted.Clear(); _cloneAssetIds.Clear(); foreach (GameObject hiddenBaseMesh in _hiddenBaseMeshes) { if ((Object)(object)hiddenBaseMesh != (Object)null) { hiddenBaseMesh.SetActive(true); } } _hiddenBaseMeshes.Clear(); ConfiguredMount = null; } private void MountDecorativeClone(GameObject src, Transform anchor, bool isConfigured) { //IL_000f: 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) try { GameObject val = Object.Instantiate(src, anchor, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; CosmeticAsset val2 = src.GetComponentInChildren(true)?.cosmeticAsset; DeathHeadModelStripper.StripGameplay(val); if ((Object)(object)val2 != (Object)null) { AttachPreviewAnimator(val, val2); } _mounted.Add(val); if (val2 != null && val2.assetId != null) { _cloneAssetIds[val] = val2.assetId; } if (isConfigured) { ConfiguredMount = val; } } catch (Exception ex) { BridgeLog.Debug("DeathHead: skipped a cosmetic clone \ufffd " + ex.Message); } } internal void ApplyDeathHeadOffsets(Func resolver) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair cloneAssetId in _cloneAssetIds) { GameObject key = cloneAssetId.Key; if (!((Object)(object)key == (Object)null)) { CosmeticOffsetEntry cosmeticOffsetEntry = resolver(cloneAssetId.Value); if (cosmeticOffsetEntry != null) { Transform transform = key.transform; transform.localPosition = new Vector3(cosmeticOffsetEntry.PosX, cosmeticOffsetEntry.PosY, cosmeticOffsetEntry.PosZ); transform.localEulerAngles = new Vector3(cosmeticOffsetEntry.RotX, cosmeticOffsetEntry.RotY, cosmeticOffsetEntry.RotZ); transform.localScale = new Vector3(cosmeticOffsetEntry.ScaleX, cosmeticOffsetEntry.ScaleY, cosmeticOffsetEntry.ScaleZ); } } } } private void AttachPreviewAnimator(GameObject clone, CosmeticAsset asset) { try { AnimSet set; if (AnimOverride != null) { set = AnimOverride(asset.assetId); } else { if (!PerCosmeticColors.FeatureEnabled || !Plugin.EnableBridgeColorAnimations.Value) { return; } set = PerCosmeticColors.GetAnimSet(asset.assetId); } if (set.Any) { BridgeTintHelper.InjectBridgeTintMaterials(clone, asset); BridgeColorAnimator bridgeColorAnimator = clone.AddComponent(); bridgeColorAnimator.Init(clone, set); if (bridgeColorAnimator.IsEmpty) { bridgeColorAnimator.Stop(); } } } catch (Exception ex) { BridgeLog.Debug("DeathHead: preview animation failed \ufffd " + ex.Message); } } private void MountBridgeMeshCosmetic(GameObject liveGo, CosmeticType effType, CosmeticParent cp, bool isConfigured) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) MountDecorativeClone(liveGo, cp.parent, isConfigured); if (!IsMeshSwitch(effType) || cp.baseMeshes == null) { return; } foreach (Transform baseMesh in cp.baseMeshes) { if ((Object)(object)baseMesh != (Object)null) { ((Component)baseMesh).gameObject.SetActive(false); _hiddenBaseMeshes.Add(((Component)baseMesh).gameObject); } } } private CosmeticType OwnerType(CosmeticAsset asset) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_colorSource != (Object)null && AvatarIdentity.TryGetRemoteActor(_colorSource, out var actorNumber)) { CustomizerSync.TryGetRemote(actorNumber, asset.assetId, out BridgeSyncPayload data); return MoreHeadCosmeticMountPatch.GetRemoteEffectiveType(asset, data).cosmeticType; } return asset.type; } private void MountMeshCosmetic(CosmeticAsset asset, CosmeticType effType, CosmeticParent cp, bool isConfigured) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) try { if (asset.prefab == null || !((PrefabRef)(object)asset.prefab).IsValid()) { return; } GameObject prefab = ((PrefabRef)(object)asset.prefab).Prefab; if ((Object)(object)prefab == (Object)null) { return; } GameObject val = Object.Instantiate(prefab, cp.parent); List list = val.GetComponent()?.meshParents; bool flag = IsMeshSwitch(effType); if (cp.resetTransform) { val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; } DeathHeadColorizer.ApplyCosmeticColor(val, asset, _colorSource); if (flag) { if (cp.baseMeshes != null) { foreach (Transform baseMesh in cp.baseMeshes) { if ((Object)(object)baseMesh != (Object)null) { ((Component)baseMesh).gameObject.SetActive(false); _hiddenBaseMeshes.Add(((Component)baseMesh).gameObject); } } } if (list != null) { foreach (Transform item in list) { if ((Object)(object)item != (Object)null) { ((Component)item).gameObject.SetActive(false); } } } } if (cp.baseMeshParents != null && list != null) { int num = 0; foreach (Transform baseMeshParent in cp.baseMeshParents) { if (num >= list.Count) { break; } Transform val2 = list[num]; if ((Object)(object)val2 != (Object)null && (Object)(object)baseMeshParent != (Object)null) { ((Component)val2).gameObject.SetActive(true); val2.SetParent(baseMeshParent); if (cp.resetTransform) { val2.localPosition = Vector3.zero; val2.localRotation = Quaternion.identity; val2.localScale = Vector3.one; } } num++; } } if (list != null) { foreach (Transform item2 in list) { if ((Object)(object)item2 != (Object)null && item2.IsChildOf(val.transform) && !((Component)item2).gameObject.activeSelf) { ((Component)item2).gameObject.SetActive(true); } } } DeathHeadModelStripper.StripGameplay(val); DeathHeadModelStripper.CleanVisualClutter(val); _mounted.Add(val); if (list != null) { foreach (Transform item3 in list) { if ((Object)(object)item3 != (Object)null && !item3.IsChildOf(val.transform)) { _mounted.Add(((Component)item3).gameObject); } } } if (isConfigured) { ConfiguredMount = val; } } catch (Exception ex) { BridgeLog.Debug("DeathHead: skipped a cosmetic mount — " + ex.Message); } } private static bool IsMeshSwitch(CosmeticType type) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown List list = MetaManager.instance?.cosmeticTypeAssets; if (list == null) { return false; } int num = (int)type; if (num < 0 || num >= list.Count) { return false; } return list[num]?.meshSwitch ?? false; } } internal static class DeathHeadModelStripper { internal static void StripGameplay(GameObject instance) { SemiIconMaker[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (SemiIconMaker val in componentsInChildren) { if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } } MonoBehaviour[] componentsInChildren2 = instance.GetComponentsInChildren(true); foreach (MonoBehaviour val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)val2); } } Animator[] componentsInChildren3 = instance.GetComponentsInChildren(true); foreach (Animator val3 in componentsInChildren3) { if ((Object)(object)val3 != (Object)null) { Object.DestroyImmediate((Object)(object)val3); } } Rigidbody[] componentsInChildren4 = instance.GetComponentsInChildren(true); foreach (Rigidbody val4 in componentsInChildren4) { if ((Object)(object)val4 != (Object)null) { Object.DestroyImmediate((Object)(object)val4); } } Collider[] componentsInChildren5 = instance.GetComponentsInChildren(true); foreach (Collider val5 in componentsInChildren5) { if ((Object)(object)val5 != (Object)null) { Object.DestroyImmediate((Object)(object)val5); } } } internal static void CleanVisualClutter(GameObject instance) { ParticleSystem[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (ParticleSystem val in componentsInChildren) { if ((Object)(object)val != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } } Light[] componentsInChildren2 = instance.GetComponentsInChildren(true); foreach (Light val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val2).gameObject); } } AudioSource[] componentsInChildren3 = instance.GetComponentsInChildren(true); foreach (AudioSource val3 in componentsInChildren3) { if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val3).gameObject != (Object)(object)instance) { Object.DestroyImmediate((Object)(object)((Component)val3).gameObject); } } } internal static Transform? FindDeep(Transform root, string name) { if (((Object)root).name == name) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindDeep(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } } [HarmonyPatch(typeof(LevelGenerator), "Awake")] internal static class DeathHeadPrefabProvider { internal static readonly HashSet SupportedTypes = new HashSet { (CosmeticType)0, (CosmeticType)5, (CosmeticType)24, (CosmeticType)17, (CosmeticType)18, (CosmeticType)31, (CosmeticType)32, (CosmeticType)11, (CosmeticType)12 }; internal static GameObject? Prefab { get; private set; } [HarmonyPostfix] private static void Postfix(LevelGenerator __instance) { if (!((Object)(object)Prefab != (Object)null)) { Prefab = __instance.PlayerDeathHeadPrefab; } } } internal sealed class DeathHeadPreviewInstance { private const string HeadAnchorName = "Cosmetic Parent - Head Top"; private const string FallbackAnchorName = "Cosmetics"; private const string CrownMeshName = "Crown Mesh"; private static readonly Vector3 SpawnLocalOffset = new Vector3(0f, 0.8f, 0f); private GameObject? _container; private GameObject? _instance; private Transform? _headAnchor; private Transform? _crownMesh; private DeathHeadCosmeticMounter? _mounter; internal bool IsSpawned => (Object)(object)_instance != (Object)null; internal Transform? ConfiguredMountTransform { get { if (!((Object)(object)_mounter?.ConfiguredMount != (Object)null)) { return null; } return _mounter.ConfiguredMount.transform; } } internal bool TryEnsure(Transform anchor, PlayerCosmetics? colorSource) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_instance != (Object)null) { return true; } GameObject prefab = DeathHeadPrefabProvider.Prefab; if ((Object)(object)prefab == (Object)null) { return false; } try { _container = new GameObject("MHB_DeathHeadPreview"); _container.SetActive(false); _instance = Object.Instantiate(prefab, _container.transform); DeathHeadColorizer.ApplyBodyColors(_instance, colorSource); Dictionary parentByType = ReadCosmeticParents(_instance); DeathHeadModelStripper.StripGameplay(_instance); DeathHeadModelStripper.CleanVisualClutter(_instance); _headAnchor = DeathHeadModelStripper.FindDeep(_instance.transform, "Cosmetic Parent - Head Top") ?? DeathHeadModelStripper.FindDeep(_instance.transform, "Cosmetics"); _crownMesh = DeathHeadModelStripper.FindDeep(_instance.transform, "Crown Mesh"); _container.transform.SetParent(anchor, false); _container.transform.localPosition = SpawnLocalOffset; _container.transform.localRotation = Quaternion.identity; _container.transform.localScale = Vector3.one; _mounter = new DeathHeadCosmeticMounter(parentByType, _headAnchor, colorSource); return true; } catch { Destroy(); return false; } } private static Dictionary ReadCosmeticParents(GameObject instance) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); PlayerCosmetics componentInChildren = instance.GetComponentInChildren(true); if (componentInChildren?.cosmeticParents == null) { return dictionary; } foreach (CosmeticParent cosmeticParent in componentInChildren.cosmeticParents) { if (!((Object)(object)cosmeticParent?.parent == (Object)null)) { dictionary[cosmeticParent.cosmeticType] = cosmeticParent; } } return dictionary; } internal void MountCosmetics(List<(GameObject liveGo, CosmeticAsset asset)> cosmetics, GameObject? configuredLiveGo) { _mounter?.Mount(cosmetics, configuredLiveGo); } internal void SetAnimOverride(Func? resolver) { if (_mounter != null) { _mounter.AnimOverride = resolver; } } internal void ApplyDeathHeadOffsets(Func resolver) { _mounter?.ApplyDeathHeadOffsets(resolver); } internal void ApplyOffset(CosmeticOffsetEntry? offset) { //IL_005c: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) GameObject val = _mounter?.ConfiguredMount; if (!((Object)(object)val == (Object)null)) { Transform transform = val.transform; if (offset == null) { transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one; } else { transform.localPosition = new Vector3(offset.PosX, offset.PosY, offset.PosZ); transform.localEulerAngles = new Vector3(offset.RotX, offset.RotY, offset.RotZ); transform.localScale = new Vector3(offset.ScaleX, offset.ScaleY, offset.ScaleZ); } } } internal void SetCrownVisible(bool visible) { if ((Object)(object)_crownMesh != (Object)null) { ((Component)_crownMesh).gameObject.SetActive(visible); } } internal void SetConfiguredCosmeticVisible(bool visible) { GameObject val = _mounter?.ConfiguredMount; if ((Object)(object)val != (Object)null && val.activeSelf != visible) { val.SetActive(visible); } } internal void Show(bool show) { if ((Object)(object)_container != (Object)null) { _container.SetActive(show); } } internal void SetScaleFactor(float factor) { //IL_0019: 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) if ((Object)(object)_container != (Object)null) { _container.transform.localScale = Vector3.one * factor; } } internal void Destroy() { _mounter?.Clear(); _mounter = null; if ((Object)(object)_container != (Object)null) { Object.Destroy((Object)(object)_container); _container = null; } _instance = null; _headAnchor = null; _crownMesh = null; } } internal sealed class LocalPopupOverlay : MonoBehaviour { private const float DimmerAlpha = 0.7f; private GameObject? _overlay; internal static void Add(GameObject subPopupGo, Transform parentPopupTransform) { LocalPopupOverlay localPopupOverlay = subPopupGo.AddComponent(); localPopupOverlay.CreateOverlay(parentPopupTransform); } private void CreateOverlay(Transform parentPopupTransform) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LocalDimmer", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parentPopupTransform, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; Image val3 = val.AddComponent(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.7f); ((Graphic)val3).raycastTarget = true; ((Transform)val2).SetAsLastSibling(); _overlay = val; REPOAvatarPreview val4 = ((Component)parentPopupTransform).GetComponentInChildren(true) ?? Object.FindObjectOfType(); if ((Object)(object)val4 != (Object)null) { ((Component)val4).transform.SetAsLastSibling(); } } private void OnDestroy() { if ((Object)(object)_overlay != (Object)null) { Object.Destroy((Object)(object)_overlay); } } } internal sealed class NullableSwayModeConverter : JsonConverter { public override SwayMode? ReadJson(JsonReader reader, Type objectType, SwayMode? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 if ((int)reader.TokenType == 11) { return null; } if ((int)reader.TokenType == 10) { return ((bool)reader.Value) ? SwayMode.Moderate : SwayMode.None; } if ((int)reader.TokenType == 9 && Enum.TryParse((string)reader.Value, ignoreCase: true, out var result)) { return result; } return null; } public override void WriteJson(JsonWriter writer, SwayMode? value, JsonSerializer serializer) { if (!value.HasValue) { writer.WriteNull(); } else { writer.WriteValue(value.ToString()); } } } internal static class OffsetSeedDefaults { private static readonly Dictionary Table = Build(); private static readonly HashSet FitTriggerSet = BuildFitTriggerSet(); private static readonly HashSet OptInTriggers = new HashSet { (Type)75 }; private static CosmeticOffsetEntry E(Type trigger, float px, float py, float pz, float rx, float ry, float rz, float sx, float sy, float sz, float lerp) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return new CosmeticOffsetEntry { TriggerType = trigger, PosX = px, PosY = py, PosZ = pz, RotX = rx, RotY = ry, RotZ = rz, ScaleX = sx, ScaleY = sy, ScaleZ = sz, LerpSpeed = lerp, Seeded = true }; } private static Dictionary Build() { CosmeticOffsetEntry[] value = new CosmeticOffsetEntry[3] { E((Type)3, 0f, -0.0013f, 0.0008f, 0.0216f, 0f, 3.286f, 1.027f, 1.0176f, 1.0232f, 3f), E((Type)15, -0.013f, -0.0171f, -0.0243f, 4.0828f, 0.0151f, 3.7491f, 0.932f, 0.9406f, 0.9427f, 3f), E((Type)75, -0.0163f, -0.0072f, 0.001f, 6.9458f, 14.0261f, 46.6643f, 0.9782f, 0.9836f, 0.9836f, 3f) }; CosmeticOffsetEntry[] value2 = new CosmeticOffsetEntry[4] { E((Type)3, 0f, -0.0013f, 0.0008f, 0.0216f, 0f, 3.286f, 1.027f, 1.0176f, 1.0232f, 3f), E((Type)15, -0.013f, -0.0171f, -0.0243f, 4.0828f, 0.0151f, 3.7491f, 0.932f, 0.9406f, 0.9427f, 3f), E((Type)75, -0.0163f, -0.0072f, 0.001f, 6.9458f, 14.0261f, 46.6643f, 0.9782f, 0.9836f, 0.9836f, 3f), E((Type)22, 0f, 0.0383f, 0f, 0f, 0f, 0f, 1f, 0.75f, 1f, 3f) }; CosmeticOffsetEntry[] value3 = new CosmeticOffsetEntry[2] { E((Type)37, 0f, 0f, 0.0015f, 0f, 0f, 0f, 1.0631f, 1f, 1.13f, 3f), E((Type)38, -0.0015f, 0.0004f, -0.004f, -0.8824f, 0f, 0f, 0.7842f, 0.9798f, 0.7763f, 3f) }; CosmeticOffsetEntry[] value4 = new CosmeticOffsetEntry[4] { E((Type)40, 0f, -0.0068f, 0.0116f, 0f, 0f, 0f, 1.0608f, 1.0497f, 1.0767f, 3f), E((Type)41, 0.0002f, -0.0022f, -0.0164f, 0f, 0f, 0f, 0.8696f, 0.986f, 0.8025f, 3f), E((Type)87, -0.0001f, -0.0091f, -0.0004f, 0f, 0f, 0f, 1.0293f, 1.0221f, 1.0576f, 3f), E((Type)88, 0f, -0.0215f, 0f, 0f, 0f, 0f, 1.0622f, 1.169f, 1.0689f, 3f) }; CosmeticOffsetEntry[] value5 = new CosmeticOffsetEntry[5] { E((Type)43, -0.0046f, 0.0029f, 0f, 0f, 0f, 11.2037f, 1.0496f, 1.3052f, 1.3495f, 3f), E((Type)44, -0.0007f, 0f, 0f, 0f, 0f, 0f, 0.9983f, 0.8486f, 0.8486f, 3f), E((Type)71, 0.0372f, 0.0012f, 0.0007f, 0f, 0f, 11.3588f, 0.9976f, 1.1713f, 1.2537f, 3f), E((Type)73, -0.0209f, 0.0017f, 0f, 0f, 0f, 22.7138f, 1.0088f, 1.2623f, 1.3263f, 3f), E((Type)90, 0.0057f, 0.0049f, 0f, 0f, 0f, 11.5225f, 0.9979f, 1.1146f, 1.1901f, 3f) }; CosmeticOffsetEntry[] value6 = new CosmeticOffsetEntry[5] { E((Type)46, 0.0099f, 0.0035f, 0f, 0f, 0f, 0.1834f, 1.0423f, 1.2984f, 1.3414f, 3f), E((Type)47, 0.0014f, 0.0003f, 0f, 0f, 0f, 0.0754f, 0.9981f, 0.8483f, 0.8483f, 3f), E((Type)72, -0.0376f, -0f, 0.0007f, 0f, 0f, 0.0165f, 0.9962f, 1.172f, 1.249f, 3f), E((Type)74, 0.021f, 0.001f, 0f, 0f, 0f, 10.5522f, 1.0013f, 1.2561f, 1.3181f, 3f), E((Type)89, -0.0062f, 0.0068f, 0f, 0f, 0f, 10.7012f, 0.9888f, 1.1112f, 1.1967f, 3f) }; CosmeticOffsetEntry[] value7 = new CosmeticOffsetEntry[5] { E((Type)49, -0.0002f, 0.0042f, 0f, 0f, 11.1131f, 0f, 1.1307f, 1.0117f, 1.1111f, 3f), E((Type)50, 0f, 0f, 0f, 0f, 0f, 0f, 0.8755f, 0.9957f, 0.8759f, 3f), E((Type)91, -0.0002f, -0.0028f, 0.0002f, 0f, 11.1131f, 0f, 1.1328f, 1.0156f, 1.1292f, 3f), E((Type)92, -0.0002f, 0.0028f, 0.0033f, 0f, 11.1131f, 0f, 1.1285f, 1.016f, 1.1429f, 3f), E((Type)93, -0.0002f, -0.0015f, 0f, 0f, 11.1131f, 0f, 1.1703f, 1.0213f, 1.1991f, 3f) }; CosmeticOffsetEntry[] value8 = new CosmeticOffsetEntry[5] { E((Type)52, -0.0002f, 0.0042f, 0f, 0f, 0.1369f, 0f, 1.1321f, 1.0038f, 1.1075f, 3f), E((Type)53, 0f, 0f, 0f, 0f, 0f, 0f, 0.8677f, 0.9957f, 0.8681f, 3f), E((Type)94, -0.0002f, -0.0028f, 0.0002f, 0f, 0.1369f, 0f, 1.1358f, 1.0077f, 1.1303f, 3f), E((Type)95, -0.0002f, 0.0028f, 0.0033f, 0f, 0.1369f, 0f, 1.1315f, 1.0081f, 1.144f, 3f), E((Type)96, -0.0002f, -0.0015f, 0f, 0f, 0.1369f, 0f, 1.1749f, 1.0134f, 1.2018f, 3f) }; CosmeticOffsetEntry[] value9 = new CosmeticOffsetEntry[3] { E((Type)27, 0f, 0f, 0f, -5.7143f, 0f, 0f, 1f, 1f, 1f, 3f), E((Type)26, 0f, 0f, 0f, -10.3f, 0f, 0f, 1f, 1f, 1f, 3f), E((Type)82, 0f, 0f, 0f, -5.3333f, 0f, 0f, 1f, 1f, 1f, 3f) }; return new Dictionary { [(CosmeticType)0] = value2, [(CosmeticType)5] = value, [(CosmeticType)24] = value, [(CosmeticType)18] = value9, [(CosmeticType)20] = value3, [(CosmeticType)7] = value3, [(CosmeticType)16] = value3, [(CosmeticType)21] = value4, [(CosmeticType)8] = value4, [(CosmeticType)23] = value4, [(CosmeticType)1] = value5, [(CosmeticType)9] = value5, [(CosmeticType)26] = value5, [(CosmeticType)13] = value5, [(CosmeticType)2] = value6, [(CosmeticType)10] = value6, [(CosmeticType)27] = value6, [(CosmeticType)3] = value7, [(CosmeticType)11] = value7, [(CosmeticType)28] = value7, [(CosmeticType)19] = value7, [(CosmeticType)4] = value8, [(CosmeticType)12] = value8, [(CosmeticType)29] = value8, [(CosmeticType)22] = value8 }; } internal static bool HasDefaults(CosmeticType type) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return Table.ContainsKey(type); } private static HashSet BuildFitTriggerSet() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(); foreach (CosmeticOffsetEntry[] value in Table.Values) { CosmeticOffsetEntry[] array = value; foreach (CosmeticOffsetEntry cosmeticOffsetEntry in array) { hashSet.Add(cosmeticOffsetEntry.TriggerType); } } return hashSet; } internal static bool IsFitTrigger(Type t) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return FitTriggerSet.Contains(t); } internal static bool IsOptInTrigger(Type t) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return OptInTriggers.Contains(t); } internal static IReadOnlyList SeedTriggersFor(CosmeticType type) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!Table.TryGetValue(type, out CosmeticOffsetEntry[] value)) { return Array.Empty(); } return Array.ConvertAll(value, (CosmeticOffsetEntry e) => e.TriggerType); } internal static bool TryGetSeed(CosmeticType type, Type trigger, out CosmeticOffsetEntry seed) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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) if (Table.TryGetValue(type, out CosmeticOffsetEntry[] value)) { CosmeticOffsetEntry[] array = value; foreach (CosmeticOffsetEntry cosmeticOffsetEntry in array) { if (cosmeticOffsetEntry.TriggerType == trigger) { seed = cosmeticOffsetEntry.Clone(); return true; } } } seed = null; return false; } internal static List? MergeInto(CosmeticType type, List? userOffsets) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (!Table.TryGetValue(type, out CosmeticOffsetEntry[] value) || value.Length == 0) { return userOffsets; } List list = ((userOffsets != null) ? new List(userOffsets) : new List()); CosmeticOffsetEntry[] array = value; foreach (CosmeticOffsetEntry cosmeticOffsetEntry in array) { if (OptInTriggers.Contains(cosmeticOffsetEntry.TriggerType)) { continue; } bool flag = false; foreach (CosmeticOffsetEntry item in list) { if (item.TriggerType == cosmeticOffsetEntry.TriggerType) { flag = true; break; } } if (!flag) { list.Add(cosmeticOffsetEntry.Clone()); } } if (list.Count <= 0) { return userOffsets; } return list; } } internal static class OverridePreviewContext { internal static PlayerCosmetics? Pc { get; private set; } internal static string? AssetId { get; private set; } internal static CosmeticOverrideData? Data { get; private set; } internal static void Set(PlayerCosmetics pc, string assetId, CosmeticOverrideData? data) { Pc = pc; AssetId = assetId; Data = data; } internal static void Clear() { Pc = null; AssetId = null; Data = null; } internal static bool IsActiveFor(PlayerCosmetics? pc, string? assetId) { if ((Object)(object)pc != (Object)null && (Object)(object)pc == (Object)(object)Pc) { return assetId == AssetId; } return false; } internal static bool IsPreviewActiveForAsset(string? assetId) { if ((Object)(object)Pc != (Object)null) { return assetId == AssetId; } return false; } } [HarmonyPatch] internal static class CosmeticsBulkActionRefreshPatch { private static IEnumerable TargetMethods() { yield return AccessTools.Method(typeof(MenuPageCosmetics), "RandomizeAllButton", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(MenuPageCosmetics), "RandomizeBodyButton", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(MenuPageCosmetics), "RandomizeCosmeticsButton", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(MenuPageCosmetics), "ResetAllButton", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(MenuPageCosmetics), "ResetBodyButton", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(MenuPageCosmetics), "ResetCosmeticsButton", (Type[])null, (Type[])null); } [HarmonyPostfix] private static void Postfix(MenuPageCosmetics __instance, MethodBase __originalMethod) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if ((int)__instance.selectedTab == 0 && CosmeticsMenuState.IsSelected(__instance.selectedCategory)) { int frames = (__originalMethod.Name.StartsWith("Randomize") ? 3 : 2); ((MonoBehaviour)__instance).StartCoroutine(DeferredRefresh(__instance, frames)); } } private static IEnumerator DeferredRefresh(MenuPageCosmetics page, int frames) { for (int i = 0; i < frames; i++) { yield return null; } if (!((Object)(object)page == (Object)null) && (int)page.selectedTab == 0 && CosmeticsMenuState.IsSelected(page.selectedCategory)) { page.RefreshScrollContent(); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "RefreshScrollContent")] internal static class CosmeticsFilterPatch { internal const float SectionSpacing = 10f; internal const float SectionHeader = 40f; internal const string WorldSectionName = "MHB_WorldSection"; internal const CosmeticType WorldSubCategory = (CosmeticType)2147483646; private static readonly Dictionary _lowerNameCache = new Dictionary(); private static bool _xuResolved; private static object? _xuTranslator; private static MethodInfo? _xuTryTranslate; private static readonly Dictionary _lowerTranslatedCache = new Dictionary(); [HarmonyPrefix] private static bool Prefix(MenuPageCosmetics __instance, ref bool __state) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (BridgePatcher.MenuTakeoverBroken) { return true; } if ((int)__instance.selectedTab != 0) { return true; } if (WorldCosmeticsMenuState.IsWorldCategory(__instance.selectedCategory)) { CosmeticsScrollBuilder.BuildWorldScrollContent(__instance); __state = true; return false; } if (CosmeticsMenuState.IsVirtual(__instance.selectedCategory)) { CosmeticsScrollBuilder.BuildVirtualScrollContent(__instance); __state = true; return false; } if (CosmeticsScrollBuilder.ShouldUseVanillaPerfPath(__instance.selectedCategory)) { CosmeticsScrollBuilder.BuildVanillaScrollContent(__instance); __state = true; return false; } return true; } [HarmonyPostfix] private static void Postfix(MenuPageCosmetics __instance, bool __state) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Invalid comparison between Unknown and I4 //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Invalid comparison between Unknown and I4 //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Expected O, but got Unknown //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04ae: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) if (__state) { return; } if ((int)__instance.selectedTab == 1) { CosmeticsSearchHelper.UpdateSearchFieldVisibility(isSearch: false); CosmeticsScrollBuilder.HideEmptyState(); return; } CosmeticCategoryAsset selectedCategory = __instance.selectedCategory; if ((Object)(object)selectedCategory == (Object)null) { return; } if (CosmeticsMenuState.IsPresetsCategory(selectedCategory)) { CosmeticsSearchHelper.UpdateSearchFieldVisibility(isSearch: false); CosmeticsScrollBuilder.HideEmptyState(); return; } bool flag = CosmeticsMenuState.IsSelected(selectedCategory); bool flag2 = CosmeticsMenuState.IsSearch(selectedCategory); bool flag3 = CosmeticsMenuState.IsFavCategory(selectedCategory); bool flag4 = CosmeticsMenuState.IsHideCategory(selectedCategory); bool flag5 = CosmeticsMenuState.IsVirtual(selectedCategory); CosmeticsSearchHelper.UpdateSearchFieldVisibility(flag2); string text = CosmeticsSearchHelper.FoldText(CosmeticsMenuState.SearchText?.Trim() ?? ""); bool flag6 = flag2 && text.Length > 0; BridgeFavoritesManager.EnsureLoaded(); bool flag7 = !flag4 && !flag && BridgeFavoritesManager.HasAnyHidden(); if (!flag5 && !flag6 && !flag7) { CosmeticsSortHelper.SortFavoritesInCategory(__instance); CosmeticsScrollBuilder.HideEmptyState(); } else { if ((Object)(object)MetaManager.instance == (Object)null) { return; } HashSet equippedSet = new HashSet(MetaManager.instance.cosmeticEquipped); HashSet unlocksSet = new HashSet(MetaManager.instance.cosmeticUnlocks); Dictionary dictionary = new Dictionary(); foreach (Transform item in __instance.subCategoriesTransform) { Transform val = item; MenuElementButtonCosmeticCategory component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && (int)component.buttonType == 1) { dictionary[component.subCategory] = ((Component)val).gameObject; } } foreach (GameObject value in dictionary.Values) { value.SetActive(!flag5); } float num = 0f; int num2 = 0; bool flag8 = flag5 && HhhCosmeticLoader.WorldAssetIds.Count > 0; MenuElementCosmeticSection val2 = null; foreach (MenuElementCosmeticSection item2 in __instance.sections.ToList()) { if (item2.isStickyHeader) { continue; } bool flag9 = flag8 && (int)item2.subCategory == 0; MenuElementCosmeticButton[] componentsInChildren = ((Component)item2.cosmeticListTransform).GetComponentsInChildren(true); MenuElementCosmeticButton[] array = componentsInChildren.Where((MenuElementCosmeticButton b) => (Object)(object)b != (Object)null && (Object)(object)b.cosmeticAsset != (Object)null).ToArray(); int num3 = 0; MenuElementCosmeticButton[] array2 = array; foreach (MenuElementCosmeticButton val3 in array2) { if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).gameObject == (Object)null) { continue; } bool flag10; if (flag9 && HhhCosmeticLoader.IsWorldAsset(val3.cosmeticAsset)) { flag10 = false; } else { if (!flag5 && flag7) { if (BridgeFavoritesManager.IsHidden(val3.cosmeticAsset) && ((Component)val3).gameObject.activeSelf) { ((Component)val3).gameObject.SetActive(false); } if (((Component)val3).gameObject.activeSelf) { FavHideMarkerHelper.UpdateMarker(val3); } continue; } flag10 = Matches(val3.cosmeticAsset, flag, flag2, flag3, flag4, flag7, flag6, text, equippedSet, unlocksSet); } if (((Component)val3).gameObject.activeSelf != flag10) { ((Component)val3).gameObject.SetActive(flag10); } if (flag10) { FavHideMarkerHelper.UpdateMarker(val3); } else { num3++; } } int num5 = array.Length - num3; if (num5 == 0) { if (flag5) { __instance.sections.Remove(item2); Object.Destroy((Object)(object)((Component)item2).gameObject); } continue; } num2 += num5; if (flag5) { if (!((Component)item2).gameObject.activeSelf) { ((Component)item2).gameObject.SetActive(true); } if ((Object)(object)item2.highlightObj != (Object)null) { ((Component)item2.highlightObj).gameObject.SetActive(false); } GridLayoutGroup component2 = ((Component)item2.cosmeticListTransform).GetComponent(); ((LayoutGroup)component2).padding = new RectOffset(((LayoutGroup)component2).padding.left, ((LayoutGroup)component2).padding.right, ((LayoutGroup)component2).padding.top, 0); int num6 = Mathf.Max(1, component2.constraintCount); int num7 = Mathf.Max(1, Mathf.CeilToInt((float)(num5 + 1) / (float)num6)); float num8 = component2.cellSize.y * (float)num7 + component2.spacing.y * (float)(num7 - 1) + (float)((LayoutGroup)component2).padding.top + (float)((LayoutGroup)component2).padding.bottom; float num9 = 40f + num8; RectTransform component3 = ((Component)item2).GetComponent(); ((Transform)component3).localPosition = new Vector3(((Transform)component3).localPosition.x, num, ((Transform)component3).localPosition.z); component3.sizeDelta = new Vector2(component3.sizeDelta.x, num9); RectTransform component4 = ((Component)item2.cosmeticListTransform).GetComponent(); component4.sizeDelta = new Vector2(component4.sizeDelta.x, num8); val2 = item2; num -= num9 + 10f; } } if (!flag5 || flag2 || flag || flag3 || flag4) { CosmeticsSortHelper.SortFavoritesInCategory(__instance, flag, flag5); } int num10 = (flag8 ? CosmeticsScrollBuilder.InjectWorldSection(__instance, num, flag, flag2, flag3, flag4, flag7, flag6, text, equippedSet, unlocksSet) : 0); num2 += num10; if (flag5) { MenuElementCosmeticSection obj; if (num10 <= 0) { obj = val2; } else { List sections = __instance.sections; obj = sections[sections.Count - 1]; } MenuElementCosmeticSection section = obj; CosmeticsScrollBuilder.ApplyStickyPadding(__instance, section); } if (flag5 && num2 == 0) { string message = (flag3 ? "Add a favorite with Ctrl+click :)" : (flag4 ? "Hide cosmetics with Alt+click :P" : ((!flag2) ? "Equip a cosmetic to see it here :3" : (string.IsNullOrWhiteSpace(CosmeticsMenuState.SearchText) ? "Type to search cosmetics here :)" : "No cosmetics found :'(")))); CosmeticsScrollBuilder.ShowEmptyState(message); } else { CosmeticsScrollBuilder.HideEmptyState(); } if (flag5) { CosmeticsScrollBuilder.RebuildScroll(__instance); } } } internal static bool Matches(CosmeticAsset asset, bool isSelected, bool isSearch, bool isFav, bool isHide, bool suppressHidden, bool applySearch, string search, HashSet equippedSet, HashSet unlocksSet) { if (isSearch && !applySearch) { return false; } int assetIndex = CosmeticsMenuState.GetAssetIndex(asset); if (isHide) { return BridgeFavoritesManager.IsHidden(asset); } if (isFav) { return BridgeFavoritesManager.IsFavorite(asset); } if (suppressHidden && BridgeFavoritesManager.IsHidden(asset)) { return false; } if (isSelected && !equippedSet.Contains(assetIndex)) { return false; } if (isSearch && assetIndex >= 0 && !unlocksSet.Contains(assetIndex)) { return false; } if (applySearch && !MatchesSearch(asset, search)) { return false; } return true; } private static string GetLowerName(CosmeticAsset asset) { if (_lowerNameCache.TryGetValue(asset, out string value)) { return value; } string text = CosmeticsSearchHelper.FoldText(asset.assetName ?? ((Object)asset).name ?? ""); _lowerNameCache[asset] = text; return text; } private static bool MatchesSearch(CosmeticAsset asset, string search) { if (GetLowerName(asset).Contains(search)) { return true; } return GetLowerTranslatedName(asset)?.Contains(search) ?? false; } private static string? GetLowerTranslatedName(CosmeticAsset asset) { if (_lowerTranslatedCache.TryGetValue(asset, out string value)) { return value; } if (!_xuResolved) { _xuResolved = true; try { _xuTranslator = Type.GetType("XUnity.AutoTranslator.Plugin.Core.AutoTranslator, XUnity.AutoTranslator.Plugin.Core")?.GetProperty("Default")?.GetValue(null); Type type = Type.GetType("XUnity.AutoTranslator.Plugin.Core.ITranslator, XUnity.AutoTranslator.Plugin.Core"); _xuTryTranslate = (type ?? _xuTranslator?.GetType())?.GetMethod("TryTranslate", new Type[2] { typeof(string), typeof(string).MakeByRefType() }); } catch { _xuTranslator = null; _xuTryTranslate = null; } } if (_xuTranslator == null || _xuTryTranslate == null) { return null; } string text = asset.assetName ?? ((Object)asset).name ?? ""; if (text.Length == 0) { return null; } try { object[] array = new object[2] { text, null }; object obj2 = _xuTryTranslate.Invoke(_xuTranslator, array); if (obj2 is bool && (bool)obj2 && array[1] is string { Length: >0 } text2 && text2 != text) { string text3 = CosmeticsSearchHelper.FoldText(text2); _lowerTranslatedCache[asset] = text3; return text3; } } catch { _xuTryTranslate = null; } return null; } internal static bool IsUnlocked(MenuElementCosmeticButton btn) { if ((Object)(object)MetaManager.instance == (Object)null) { return true; } int assetIndex = CosmeticsMenuState.GetAssetIndex(btn.cosmeticAsset); if (assetIndex < 0) { return true; } return MetaManager.instance.cosmeticUnlocks.Contains(assetIndex); } } [HarmonyPatch(typeof(MenuButton), "OnSelect")] internal static class ToolsButtonOnSelectPatch { [HarmonyPrefix] private static bool Prefix(MenuButton __instance) { if (!CosmeticsMenuStartPatch._buttonActions.TryGetValue(__instance, out Action value)) { return true; } try { value?.Invoke(); } catch (Exception ex) { BceConsole.LogWarning("ToolsButton action error: " + ex.Message); } return false; } } [HarmonyPatch(typeof(MenuPageCosmetics), "TogglePopupColor")] internal static class TogglePopupColorPatch { [HarmonyPostfix] private static void Postfix() { MenuElementCosmeticButtonPopup toolsPopupRef = CosmeticsMenuStartPatch._toolsPopupRef; if ((Object)(object)toolsPopupRef != (Object)null) { toolsPopupRef.SetState(false, false); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "TogglePopupRandomize")] internal static class TogglePopupRandomizePatch { [HarmonyPostfix] private static void Postfix() { MenuElementCosmeticButtonPopup toolsPopupRef = CosmeticsMenuStartPatch._toolsPopupRef; if ((Object)(object)toolsPopupRef != (Object)null) { toolsPopupRef.SetState(false, false); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "TogglePopupReset")] internal static class TogglePopupResetPatch { [HarmonyPostfix] private static void Postfix() { MenuElementCosmeticButtonPopup toolsPopupRef = CosmeticsMenuStartPatch._toolsPopupRef; if ((Object)(object)toolsPopupRef != (Object)null) { toolsPopupRef.SetState(false, false); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "LateUpdate")] internal static class CosmeticsMenuLateUpdatePatch { private const string HintBase = "Ctrl+click = Fav\nAlt+click = Hide"; private const string HintOverride = "\nShift+click = Edit"; private const float HintDelay = 2f; private const float HintFade = 0.5f; private const float HintAlpha = 0.4f; private static readonly Color NormalColor = Color.white; private static readonly Color GeneratingColor = new Color(1f, 0.8f, 0.2f, 1f); private static readonly List GeneratingAllowedKeys = new List { (InputKey)18 }; private static string _lastText = ""; private static float _noHoverTime; private static string Hint { get { if (!Plugin.EnableCosmeticCustomizer.Value) { return "Ctrl+click = Fav\nAlt+click = Hide"; } return "Ctrl+click = Fav\nAlt+click = Hide\nShift+click = Edit"; } } internal static void OnMenuClosed() { _noHoverTime = 0f; _lastText = ""; } [HarmonyPostfix] private static void Postfix(MenuPageCosmetics __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI statusLabel = CosmeticsMenuState.StatusLabel; if ((Object)(object)statusLabel == (Object)null) { return; } if ((int)__instance.selectedTab != 0) { _noHoverTime = 0f; ((Component)((TMP_Text)statusLabel).transform.parent).gameObject.SetActive(false); return; } ((Component)((TMP_Text)statusLabel).transform.parent).gameObject.SetActive(true); CanvasGroup statusLabelGroup = CosmeticsMenuState.StatusLabelGroup; if (BatchIconGenerator.IsGenerating) { if ((Object)(object)InputManager.instance != (Object)null) { InputManager.instance.DisableControlsExcept(0.1f, GeneratingAllowedKeys); } _noHoverTime = 0f; if ((Object)(object)statusLabelGroup != (Object)null) { statusLabelGroup.alpha = 1f; } ApplyText(statusLabel, BatchIconGenerator.ProgressText, GeneratingColor); return; } MenuElementCosmeticButton hoveredCosmeticButton = __instance.hoveredCosmeticButton; bool flag = false; if ((Object)(object)hoveredCosmeticButton != (Object)null) { flag = (Object)(object)hoveredCosmeticButton.cosmeticAsset != (Object)null || IsLocked(hoveredCosmeticButton); } CosmeticHoverPatch.HoverTick(flag ? hoveredCosmeticButton.cosmeticAsset : null); if (flag) { _noHoverTime = 0f; if ((Object)(object)statusLabelGroup != (Object)null) { statusLabelGroup.alpha = 1f; } if (!IsLocked(hoveredCosmeticButton)) { CosmeticAsset cosmeticAsset = hoveredCosmeticButton.cosmeticAsset; if (cosmeticAsset != null && BridgeIds.IsBridgeAsset(cosmeticAsset) && !IconCapture.HasCache(cosmeticAsset) && (Object)(object)MetaManager.instance != (Object)null) { int assetIndex = CosmeticsMenuState.GetAssetIndex(cosmeticAsset); if (assetIndex >= 0 && MetaManager.instance.cosmeticEquipped.Contains(assetIndex)) { CosmeticHoverPatch.TryScheduleCapture(cosmeticAsset, (MonoBehaviour)(object)__instance); } } } string text; if (IsLocked(hoveredCosmeticButton)) { text = "Locked"; } else { CosmeticAsset cosmeticAsset2 = hoveredCosmeticButton.cosmeticAsset; string text2 = cosmeticAsset2?.assetName ?? ((cosmeticAsset2 != null) ? ((Object)cosmeticAsset2).name : null) ?? ""; BridgeFavoritesManager.EnsureLoaded(); bool flag2 = BridgeFavoritesManager.IsFavorite(cosmeticAsset2); bool flag3 = BridgeFavoritesManager.IsHidden(cosmeticAsset2); string text3 = ""; if (flag2 && flag3) { text3 = "[FAV] [HIDE] "; } else if (flag2) { text3 = "[FAV] "; } else if (flag3) { text3 = "[HIDE] "; } text = text3 + text2; } ApplyText(statusLabel, text, NormalColor); } else { _noHoverTime += Time.unscaledDeltaTime; float alpha = Mathf.Clamp01((_noHoverTime - 2f) / 0.5f); if ((Object)(object)statusLabelGroup != (Object)null) { statusLabelGroup.alpha = alpha; } if (Hint != _lastText) { ApplyText(statusLabel, Hint, new Color(1f, 1f, 1f, 0.4f)); } else { ((TMP_Text)statusLabel).text = Hint; } } } private static void ApplyText(TextMeshProUGUI label, string text, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ((Graphic)label).color = color; if (text == _lastText) { ((TMP_Text)label).text = text; return; } _lastText = text; ((TMP_Text)label).text = text; ((TMP_Text)label).ForceMeshUpdate(false, false); ResizeStatusPanel(label); } private static void ResizeStatusPanel(TextMeshProUGUI label) { //IL_003b: 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) Transform parent = ((TMP_Text)label).transform.parent; RectTransform val = ((parent != null) ? ((Component)parent).GetComponent() : null); if (!((Object)(object)val == (Object)null)) { float num = Mathf.Max(17f, ((TMP_Text)label).preferredHeight + 2f); val.sizeDelta = new Vector2(val.sizeDelta.x, num); } } private static bool IsLocked(MenuElementCosmeticButton? btn) { CosmeticAsset val = btn?.cosmeticAsset; if ((Object)(object)val == (Object)null || (Object)(object)MetaManager.instance == (Object)null) { return false; } int assetIndex = CosmeticsMenuState.GetAssetIndex(val); if (assetIndex < 0) { return false; } return !MetaManager.instance.cosmeticUnlocks.Contains(assetIndex); } } [HarmonyPatch(typeof(MenuPageCosmetics), "Start")] internal static class CosmeticsMenuStartPatch { private const float StatusLabelOffsetX = -270f; private const float StatusLabelOffsetY = -330f; private const float StatusLabelSizeDeltaX = -610f; internal const float StatusLabelMinHeight = 17f; private const float StatusLabelFontSize = 16f; internal const float StatusLabelPadding = 6f; internal const float StatusLabelVerticalPadding = 1f; private const float StatusLabelCenterY = -338.5f; private const float SearchTopOffsetX = 60f; private const float SearchTopOffsetY = -60f; private const float SearchTopSizeDeltaX = -330f; private const float SearchTopHeight = 26f; private const float SearchBottomOffsetX = -255f; private const float SearchBottomOffsetY = -290f; private const float SearchBottomSizeDeltaX = -580f; private const float SearchBottomHeight = 25f; private const float SearchBottomCCOffsetY = -280f; private const float SearchFontSize = 17f; private const float EmptyStateLabelOffsetX = 40f; private const float EmptyStateLabelOffsetY = 75f; private const float EmptyStateLabelHeight = 30f; private const float EmptyStateLabelFontSize = 24f; private const float ToolsButtonOffsetX = 40f; internal static MenuElementCosmeticButtonPopup? _toolsPopupRef; internal static Dictionary _buttonActions = new Dictionary(); internal static Action? RefreshToolsButtons; private static Color? _dropdownBgDefaultColor; [HarmonyPostfix] [HarmonyPriority(600)] private static void Postfix(MenuPageCosmetics __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if ((int)__instance.selectedTab != 0) { return; } try { HhhCosmeticLoader.OnMenuOpen(__instance); CosmeticsMenuState.SetActivePage(__instance); if (Plugin.EnableMenuEnhancements.Value && !BridgePatcher.MenuTakeoverBroken) { CosmeticsMenuState.EnsureCategories(); InjectVirtualCategoryButtons(__instance); ReorderCategoryStrip(__instance); InjectSecondDivider(__instance); BuildVirtualCategoryTypeList(__instance); InjectStatusLabel(__instance); InjectSearchField(__instance); InjectEmptyStateLabel(__instance); } if (Plugin.ShowToolsButton.Value && !BridgePatcher.MenuTakeoverBroken) { InjectToolsButton(__instance); } MiniSemibotIconCapture.TryStart((MonoBehaviour)(object)__instance); } catch (Exception ex) { BceConsole.LogWarning("Menu injection error: " + ex.Message + "\n" + ex.StackTrace); } } private static void InjectVirtualCategoryButtons(MenuPageCosmetics page) { (CosmeticCategoryAsset, string)[] array = new(CosmeticCategoryAsset, string)[4] { (CosmeticsMenuState.SearchCategory, "SEARCH"), (CosmeticsMenuState.SelectedCategory, "SELECTED"), (CosmeticsMenuState.FavoritesCategory, "FAV"), (CosmeticsMenuState.HiddenCategory, "HIDE") }; (CosmeticCategoryAsset, string)[] array2 = array; for (int i = 0; i < array2.Length; i++) { (CosmeticCategoryAsset, string) tuple = array2[i]; CosmeticCategoryAsset cat = tuple.Item1; string item = tuple.Item2; if (!((Object)(object)cat == (Object)null) && !((Component)page.categoriesTransform).GetComponentsInChildren(true).Any((MenuElementButtonCosmeticCategory b) => (Object)(object)b.category == (Object)(object)cat)) { GameObject val = Object.Instantiate(page.categoryButtonPrefab, page.categoriesTransform); MenuElementButtonCosmeticCategory component = val.GetComponent(); component.category = cat; MenuElementCosmeticHighlight badgeHighlight = val.GetComponentInChildren(); TextMeshProUGUI val2 = (TextMeshProUGUI)(((Object)(object)badgeHighlight != (Object)null) ? ((object)(((IEnumerable)val.GetComponentsInChildren()).FirstOrDefault((Func)((TextMeshProUGUI t) => (Object)(object)t != (Object)(object)badgeHighlight.text)) ?? val.GetComponentInChildren())) : ((object)val.GetComponentInChildren())); ((TMP_Text)val2).fontSize = 20f; ((TMP_Text)val2).text = item; } } page.categoriesHolder.UpdateButtons(); } private static void ReorderCategoryStrip(MenuPageCosmetics page) { (string[], bool)[] array = new(string[], bool)[11] { (new string[4] { "PRESETS", "PRESET", "OUTFITS", "OUTFIT" }, false), (new string[1] { "|" }, true), (new string[1] { "SEARCH" }, false), (new string[2] { "SELECTED", "EQUIPPED" }, false), (new string[1] { "FAV" }, false), (new string[1] { "HEAD" }, false), (new string[1] { "BODY" }, false), (new string[1] { "ARMS" }, false), (new string[1] { "LEGS" }, false), (new string[1] { "WORLD" }, false), (new string[1] { "HIDE" }, false) }; List source = ((Component)page.categoriesTransform).GetComponentsInChildren(true).ToList(); Transform val = FindDivider(page); int num = 0; (string[], bool)[] array2 = array; for (int i = 0; i < array2.Length; i++) { (string[], bool) tuple = array2[i]; string[] keys; (keys, _) = tuple; if (tuple.Item2) { if ((Object)(object)val != (Object)null) { val.SetSiblingIndex(num++); } continue; } MenuElementButtonCosmeticCategory val2 = ((IEnumerable)source).FirstOrDefault((Func)((MenuElementButtonCosmeticCategory b) => MatchesAnyLabel(b, keys))); if ((Object)(object)val2 != (Object)null) { ((Component)val2).transform.SetSiblingIndex(num++); } } } private static void InjectSecondDivider(MenuPageCosmetics page) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown Transform val = FindDivider(page); if ((Object)(object)val == (Object)null) { return; } MenuElementButtonCosmeticCategory val2 = ((IEnumerable)((Component)page.categoriesTransform).GetComponentsInChildren(true)).FirstOrDefault((Func)((MenuElementButtonCosmeticCategory b) => (Object)(object)b.category == (Object)(object)CosmeticsMenuState.SelectedCategory)); if ((Object)(object)val2 == (Object)null) { return; } foreach (Transform item in page.categoriesTransform) { Transform val3 = item; if ((Object)(object)val3 != (Object)(object)val && (Object)(object)((Component)val3).GetComponent() == (Object)null && ((Object)val3).name == ((Object)val).name + "_MHB") { return; } } Transform val4 = Object.Instantiate(val, page.categoriesTransform); ((Object)val4).name = ((Object)val).name + "_MHB"; val4.SetSiblingIndex(((Component)val2).transform.GetSiblingIndex() + 1); } internal static Transform? FindDivider(MenuPageCosmetics page) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown foreach (Transform item in page.categoriesTransform) { Transform val = item; if ((Object)(object)((Component)val).GetComponent() == (Object)null) { return val; } } return null; } private static void BuildVirtualCategoryTypeList(MenuPageCosmetics page) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) CosmeticCategoryAsset searchCategory = CosmeticsMenuState.SearchCategory; CosmeticCategoryAsset selectedCategory = CosmeticsMenuState.SelectedCategory; if ((Object)(object)searchCategory == (Object)null || (Object)(object)selectedCategory == (Object)null) { return; } HashSet hashSet = new HashSet(); List list = new List(); foreach (Transform item in page.categoriesTransform) { Transform val = item; MenuElementButtonCosmeticCategory component = ((Component)val).GetComponent(); if ((Object)(object)component?.category == (Object)null) { continue; } CosmeticCategoryAsset category = component.category; if (CosmeticsMenuState.IsVirtual(category) || WorldCosmeticsMenuState.IsWorldCategory(category) || CosmeticsMenuState.IsPresetsCategory(category) || category.typeList == null) { continue; } foreach (CosmeticType type in category.typeList) { if (hashSet.Add(type)) { list.Add(type); } } } searchCategory.typeList = new List(list); selectedCategory.typeList = new List(list); if ((Object)(object)CosmeticsMenuState.FavoritesCategory != (Object)null) { CosmeticsMenuState.FavoritesCategory.typeList = new List(list); } if ((Object)(object)CosmeticsMenuState.HiddenCategory != (Object)null) { CosmeticsMenuState.HiddenCategory.typeList = new List(list); } } private static void InjectStatusLabel(MenuPageCosmetics page) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)CosmeticsMenuState.StatusLabel != (Object)null)) { TextMeshProUGUI componentInChildren = ((Component)page).GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { GameObject val = new GameObject("MHB_StatusLabel"); val.transform.SetParent(((Component)page).transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0f, 1f); val2.anchorMax = new Vector2(1f, 1f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = new Vector2(-270f, -338.5f); val2.sizeDelta = new Vector2(-610f, 17f); Image val3 = val.AddComponent(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.55f); GameObject val4 = new GameObject("Text"); val4.transform.SetParent(val.transform, false); RectTransform val5 = val4.AddComponent(); val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; val5.offsetMin = new Vector2(6f, 0f); val5.offsetMax = new Vector2(-6f, 0f); TextMeshProUGUI val6 = val4.AddComponent(); ((TMP_Text)val6).font = ((TMP_Text)componentInChildren).font; ((TMP_Text)val6).fontSize = 16f; ((Graphic)val6).color = Color.white; ((TMP_Text)val6).alignment = (TextAlignmentOptions)4097; ((TMP_Text)val6).text = ""; ((Graphic)val6).raycastTarget = false; CanvasGroup val7 = val.AddComponent(); val7.alpha = 0f; val.SetActive(false); CosmeticsMenuState.SetStatusLabel(val6); CosmeticsMenuState.SetStatusLabelGroup(val7); } } } private static void InjectSearchField(MenuPageCosmetics page) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)CosmeticsMenuState.SearchField != (Object)null) { ApplySearchFieldLayout(CosmeticsMenuState.SearchField); return; } TextMeshProUGUI componentInChildren = ((Component)page).GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { GameObject val = new GameObject("MHB_SearchField"); val.transform.SetParent(((Component)page).transform, false); val.AddComponent(); CanvasGroup val2 = val.AddComponent(); val2.alpha = 0f; Image val3 = val.AddComponent(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.65f); GameObject val4 = new GameObject("Text"); val4.transform.SetParent(val.transform, false); RectTransform val5 = val4.AddComponent(); val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; val5.offsetMin = new Vector2(6f, 2f); val5.offsetMax = new Vector2(-6f, -2f); TextMeshProUGUI val6 = val4.AddComponent(); ((TMP_Text)val6).font = ((TMP_Text)componentInChildren).font; ((Graphic)val6).color = Color.white; ((TMP_Text)val6).alignment = (TextAlignmentOptions)4097; GameObject val7 = new GameObject("Placeholder"); val7.transform.SetParent(val.transform, false); RectTransform val8 = val7.AddComponent(); val8.anchorMin = Vector2.zero; val8.anchorMax = Vector2.one; val8.offsetMin = new Vector2(6f, 2f); val8.offsetMax = new Vector2(-6f, -2f); TextMeshProUGUI val9 = val7.AddComponent(); ((TMP_Text)val9).font = ((TMP_Text)componentInChildren).font; ((Graphic)val9).color = new Color(1f, 1f, 1f, 0.45f); ((TMP_Text)val9).alignment = (TextAlignmentOptions)4097; ((TMP_Text)val9).text = "Type to Search..."; TMP_InputField val10 = val.AddComponent(); val10.textComponent = (TMP_Text)(object)val6; val10.placeholder = (Graphic)(object)val9; val10.characterLimit = 64; val10.lineType = (LineType)0; ((UnityEvent)(object)val10.onValueChanged).AddListener((UnityAction)delegate(string value) { CosmeticsMenuState.SetSearchText(value ?? ""); CosmeticsMenuState.ScheduleSearchRefresh(); }); ApplySearchFieldLayout(val10); val.SetActive(false); CosmeticsMenuState.SetSearchField(val10); } } private static void ApplySearchFieldLayout(TMP_InputField field) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)field).GetComponent(); if (!((Object)(object)component == (Object)null)) { component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); if (Plugin.SearchFieldPosition.Value == SearchBarPosition.Top) { component.anchoredPosition = new Vector2(60f, -60f); component.sizeDelta = new Vector2(-330f, 26f); } else if (Plugin.EnableCosmeticCustomizer.Value) { component.anchoredPosition = new Vector2(-255f, -280f); component.sizeDelta = new Vector2(-580f, 25f); } else { component.anchoredPosition = new Vector2(-255f, -290f); component.sizeDelta = new Vector2(-580f, 25f); } if ((Object)(object)field.textComponent != (Object)null) { field.textComponent.fontSize = 17f; } Graphic placeholder = field.placeholder; TextMeshProUGUI val = (TextMeshProUGUI)(object)((placeholder is TextMeshProUGUI) ? placeholder : null); if (val != null) { ((TMP_Text)val).fontSize = 17f; } } } private static void InjectEmptyStateLabel(MenuPageCosmetics page) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)CosmeticsMenuState.EmptyStateLabel != (Object)null) { ApplyEmptyStateLabelLayout(CosmeticsMenuState.EmptyStateLabel); return; } TextMeshProUGUI componentInChildren = ((Component)page).GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { GameObject val = new GameObject("MHB_EmptyState"); val.transform.SetParent(((Component)page).transform, false); val.AddComponent(); TextMeshProUGUI val2 = val.AddComponent(); ((TMP_Text)val2).font = ((TMP_Text)componentInChildren).font; ((Graphic)val2).color = new Color(1f, 1f, 1f, 0.45f); ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).text = "No items selected"; ((Graphic)val2).raycastTarget = false; ApplyEmptyStateLabelLayout(val); val.SetActive(false); CosmeticsMenuState.SetEmptyStateLabel(val); } } private static void ApplyEmptyStateLabelLayout(GameObject go) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_005b: 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) RectTransform component = go.GetComponent(); if (!((Object)(object)component == (Object)null)) { component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(40f, 75f); component.sizeDelta = new Vector2(0f, 30f); TextMeshProUGUI component2 = go.GetComponent(); if ((Object)(object)component2 != (Object)null) { ((TMP_Text)component2).fontSize = 24f; } } } private static void InjectToolsButton(MenuPageCosmetics page) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Expected O, but got Unknown //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)page.resetPopup == (Object)null) { return; } Transform parent = ((Component)page.resetPopup).transform.parent; if ((Object)(object)parent == (Object)null || (Object)(object)parent.Find("MHB_ToolsBtn") != (Object)null) { return; } MenuElementCosmeticButtonPopup resetPopup = page.resetPopup; GameObject val = Object.Instantiate(((Component)resetPopup).gameObject, parent); ((Object)val).name = "MHB_ToolsBtn"; Vector3 localPosition = ((Component)resetPopup).transform.localPosition; val.transform.localPosition = new Vector3(localPosition.x + 40f, localPosition.y, localPosition.z); MenuElementCosmeticButtonPopup toolsPopup = val.GetComponent(); if ((Object)(object)toolsPopup == (Object)null || (Object)(object)resetPopup.dropdownObj == (Object)null) { return; } GameObject val2 = Object.Instantiate(resetPopup.dropdownObj, parent); ((Object)val2).name = "MHB_ToolsDropdown"; Vector3 localPosition2 = resetPopup.dropdownObj.transform.localPosition; val2.transform.localPosition = new Vector3(localPosition2.x + 40f, localPosition2.y, localPosition2.z); toolsPopup.dropdownObj = val2; Transform transform = ((Component)resetPopup).transform; Transform transform2 = val.transform; MenuButton toggleButton = resetPopup.toggleButton; RelinkField(transform, transform2, (toggleButton != null) ? ((Component)toggleButton).transform : null, delegate(Transform t) { toolsPopup.toggleButton = ((Component)t).GetComponent(); }); Transform transform3 = ((Component)resetPopup).transform; Transform transform4 = val.transform; GameObject mainBgObj = resetPopup.mainBgObj; RelinkField(transform3, transform4, (mainBgObj != null) ? mainBgObj.transform : null, delegate(Transform t) { toolsPopup.mainBgObj = ((Component)t).gameObject; }); Transform transform5 = ((Component)resetPopup).transform; Transform transform6 = val.transform; SemiUI toggleSemiUI = resetPopup.toggleSemiUI; RelinkField(transform5, transform6, (toggleSemiUI != null) ? ((Component)toggleSemiUI).transform : null, delegate(Transform t) { toolsPopup.toggleSemiUI = ((Component)t).GetComponent(); }); toolsPopup.dropdownButtons.Clear(); MenuButton[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (MenuButton item in componentsInChildren) { toolsPopup.dropdownButtons.Add(item); } _toolsPopupRef = toolsPopup; toolsPopup.SetState(false, true); MenuButton toggleButton2 = toolsPopup.toggleButton; if ((Object)(object)toggleButton2 != (Object)null) { MenuElementCosmeticButtonPopup capturedPopup = toolsPopup; MenuPageCosmetics capturedPage = page; _buttonActions[toggleButton2] = delegate { MenuElementCosmeticButtonPopup colorPopup = capturedPage.colorPopup; if (colorPopup != null) { colorPopup.SetState(false, false); } MenuElementCosmeticButtonPopup randomizePopup = capturedPage.randomizePopup; if (randomizePopup != null) { randomizePopup.SetState(false, false); } MenuElementCosmeticButtonPopup resetPopup2 = capturedPage.resetPopup; if (resetPopup2 != null) { resetPopup2.SetState(false, false); } capturedPopup.SetState(!capturedPopup.dropdownActive, false); }; } Sprite val3 = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)((Sprite s) => ((Object)s).name == "clothes_icon")); Image val4 = ((toggleButton2 != null) ? ((IEnumerable)((Component)toggleButton2).GetComponentsInChildren(true)).FirstOrDefault((Func)((Image img) => ((Object)((Component)img).gameObject).name == "Icon")) : null); Image val5 = ((toggleButton2 != null) ? ((IEnumerable)((Component)toggleButton2).GetComponentsInChildren(true)).FirstOrDefault((Func)((Image img) => ((Object)((Component)img).gameObject).name == "Background")) : null); Color color = (((Object)(object)val5 != (Object)null) ? ((Graphic)val5).color : Color.black); if ((Object)(object)val4 != (Object)null) { if ((Object)(object)val3 != (Object)null) { val4.sprite = val3; } GameObject val6 = new GameObject("MHB_M"); val6.transform.SetParent(((Component)val4).transform, false); RectTransform val7 = val6.AddComponent(); val7.anchorMin = Vector2.zero; val7.anchorMax = Vector2.one; val7.offsetMin = Vector2.zero; val7.offsetMax = Vector2.zero; val7.anchoredPosition = new Vector2(0f, 6f); TextMeshProUGUI val8 = val6.AddComponent(); TextMeshProUGUI componentInChildren = ((Component)page).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)val8).font = ((TMP_Text)componentInChildren).font; } ((TMP_Text)val8).text = "M"; ((TMP_Text)val8).fontSize = 9f; ((TMP_Text)val8).fontStyle = (FontStyles)1; ((TMP_Text)val8).alignment = (TextAlignmentOptions)514; ((Graphic)val8).color = color; ((Graphic)val8).raycastTarget = false; } if (toolsPopup.dropdownButtons.Count < 3) { return; } MenuButton btn0 = toolsPopup.dropdownButtons[0]; MenuButton btn1 = toolsPopup.dropdownButtons[1]; MenuButton btn2 = toolsPopup.dropdownButtons[2]; MenuPageCosmetics capturedPage2 = page; Action generateAction = delegate { if (!((Object)(object)capturedPage2 == (Object)null)) { Plugin.GenerateAllIcons.Value = true; BatchIconGenerator.OnBatchCompleted = delegate { RefreshToolsButtons?.Invoke(); }; BatchIconGenerator.TryStart((MonoBehaviour)(object)capturedPage2); } }; Action clearAction = delegate { Plugin.DeleteIconCache.Value = true; IconCacheCleaner.Run(); RefreshToolsButtons?.Invoke(); }; Action settingsAction = delegate { if (Plugin.MenuLibAvailable) { CosmeticSettingsPopup.Show(); } }; WireDropdownButton(btn0, "Generate\nIcons", generateAction, !HasIconsToGenerate(), 10f); WireDropdownButton(btn1, "Clear All\nIcons", clearAction, !HasIconsToDelete(), 10f); WireDropdownButton(btn2, "Sync\nCustomizer", settingsAction, !HasCosmeticSettingsData() || !Plugin.MenuLibAvailable, 8.75f); RefreshToolsButtons = delegate { UpdateToolsButton(btn0, generateAction, HasIconsToGenerate()); UpdateToolsButton(btn1, clearAction, HasIconsToDelete()); UpdateToolsButton(btn2, settingsAction, HasCosmeticSettingsData()); }; } private static void RelinkField(Transform origRoot, Transform cloneRoot, Transform? target, Action assign) { if ((Object)(object)target == (Object)null) { return; } string relativePath = GetRelativePath(origRoot, target); if (relativePath != null) { Transform val = (Transform)(string.IsNullOrEmpty(relativePath) ? ((object)cloneRoot) : ((object)cloneRoot.Find(relativePath))); if ((Object)(object)val != (Object)null) { assign(val); } } } private static string? GetRelativePath(Transform root, Transform target) { if ((Object)(object)target == (Object)(object)root) { return ""; } List list = new List(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } if ((Object)(object)val != (Object)(object)root) { return null; } list.Reverse(); return string.Join("/", list); } private static void WireDropdownButton(MenuButton btn, string label, Action action, bool startDisabled = false, float fontSizeMin = 8f, float fontSizeMax = 11f) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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) Image[] componentsInChildren = ((Component)btn).GetComponentsInChildren(true); foreach (Image val in componentsInChildren) { if (((Object)((Component)val).gameObject).name == "Icon") { ((Component)val).gameObject.SetActive(false); } } TextMeshProUGUI componentInChildren = ((Component)btn).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).enableAutoSizing = true; ((TMP_Text)componentInChildren).fontSizeMin = fontSizeMin; ((TMP_Text)componentInChildren).fontSizeMax = fontSizeMax; ((TMP_Text)componentInChildren).overflowMode = (TextOverflowModes)0; ((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)514; } btn.buttonTextString = label; Image val2 = ((IEnumerable)((Component)btn).GetComponentsInChildren(true)).FirstOrDefault((Func)((Image img) => ((Object)((Component)img).gameObject).name == "Background")); if ((Object)(object)val2 != (Object)null) { Color valueOrDefault = _dropdownBgDefaultColor.GetValueOrDefault(); if (!_dropdownBgDefaultColor.HasValue) { valueOrDefault = ((Graphic)val2).color; _dropdownBgDefaultColor = valueOrDefault; } } if ((Object)(object)btn.menuButtonPopUp != (Object)null) { btn.menuButtonPopUp.disabled = true; } if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = label; } ApplyToolsButtonState(btn, val2, action, !startDisabled); } private static void UpdateToolsButton(MenuButton btn, Action action, bool canExecute) { Image bgImg = ((IEnumerable)((Component)btn).GetComponentsInChildren(true)).FirstOrDefault((Func)((Image img) => ((Object)((Component)img).gameObject).name == "Background")); ApplyToolsButtonState(btn, bgImg, action, canExecute); } private static void ApplyToolsButtonState(MenuButton btn, Image? bgImg, Action action, bool canExecute) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) btn.disabled = !canExecute; if (canExecute) { _buttonActions[btn] = action; } else { _buttonActions.Remove(btn); } if (!((Object)(object)bgImg == (Object)null)) { ((Graphic)bgImg).color = (Color)((!canExecute) ? new Color(0.38f, 0.38f, 0.38f, 0.55f) : (((??)_dropdownBgDefaultColor) ?? ((Graphic)bgImg).color)); } } private static bool HasIconsToGenerate() { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return false; } foreach (string id in HhhCosmeticLoader.RegisteredAssetIds) { if (!(id == MiniSemibotCosmetic.AssetId)) { CosmeticAsset val = instance.cosmeticAssets.Find((CosmeticAsset a) => (Object)(object)a != (Object)null && a.assetId == id); if ((Object)(object)val != (Object)null && !IconCapture.HasCache(val)) { return true; } } } return false; } private static bool HasIconsToDelete() { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return false; } foreach (string id in HhhCosmeticLoader.RegisteredAssetIds) { if (!(id == MiniSemibotCosmetic.AssetId)) { CosmeticAsset val = instance.cosmeticAssets.Find((CosmeticAsset a) => (Object)(object)a != (Object)null && a.assetId == id); if ((Object)(object)val != (Object)null && IconCapture.HasCache(val)) { return true; } } } return false; } private static bool HasCosmeticSettingsData() { return CustomizerSync.GetRemotePlayersWithData().Count > 0; } private static bool MatchesAnyLabel(MenuElementButtonCosmeticCategory btn, string[] keys) { foreach (string buttonLabel in GetButtonLabels(btn)) { string n = Normalize(buttonLabel); if (n.Length != 0 && keys.Any((string k) => Normalize(k) == n)) { return true; } } return false; } private static IEnumerable GetButtonLabels(MenuElementButtonCosmeticCategory btn) { if (btn.category?.categoryName != null) { yield return btn.category.categoryName; } MenuButton val = ((Component)btn).GetComponentInChildren() ?? ((Component)btn).GetComponentInParent(); if ((Object)(object)val != (Object)null && !string.IsNullOrWhiteSpace(val.buttonTextString)) { yield return val.buttonTextString; } TextMeshProUGUI componentInChildren = ((Component)btn).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null && !string.IsNullOrWhiteSpace(((TMP_Text)componentInChildren).text)) { yield return ((TMP_Text)componentInChildren).text; } } private static string Normalize(string s) { return new string(s.ToUpperInvariant().Where(char.IsLetterOrDigit).ToArray()); } } [HarmonyPatch(typeof(MenuPageCosmetics), "Update")] internal static class CosmeticsMenuUpdatePatch { private static readonly List SearchAllowedKeys = new List { (InputKey)18, (InputKey)6, (InputKey)17, (InputKey)10 }; [HarmonyPostfix] private static void Postfix(MenuPageCosmetics __instance) { MenuElementCosmeticButtonPopup toolsPopupRef = CosmeticsMenuStartPatch._toolsPopupRef; if ((Object)(object)toolsPopupRef != (Object)null && toolsPopupRef.dropdownActive && Input.GetMouseButtonDown(0) && !ToolsPopupHovered(toolsPopupRef)) { toolsPopupRef.SetState(false, false); } if (BatchIconGenerator.IsGenerating) { MenuPage menuPage = __instance.menuPage; if (menuPage != null) { PlayerAvatarMenu playerAvatarMenu = menuPage.playerAvatarMenu; if (playerAvatarMenu != null) { PlayerAvatarVisuals playerVisuals = playerAvatarMenu.playerVisuals; if (playerVisuals != null) { PlayerEyes playerEyes = playerVisuals.playerEyes; if (playerEyes != null) { playerEyes.OverrideDisableMenuLookAt(0.1f); } } } } } if (!CosmeticsMenuState.SearchMode || (Object)(object)CosmeticsMenuState.ActivePage != (Object)(object)__instance) { return; } if ((Object)(object)CosmeticsMenuState.SearchField != (Object)null) { if (!CosmeticsMenuState.SearchField.isFocused) { CosmeticsMenuState.SearchField.ActivateInputField(); } if ((Object)(object)InputManager.instance != (Object)null) { InputManager.instance.DisableControlsExcept(0.1f, SearchAllowedKeys); } return; } if (Input.GetKeyDown((KeyCode)27)) { CosmeticsMenuState.ClearSearch(); __instance.RefreshScrollContent(); return; } bool flag = false; string inputString = Input.inputString; for (int i = 0; i < inputString.Length; i++) { char c = inputString[i]; if (c == '\b') { if (CosmeticsMenuState.SearchText.Length > 0) { string searchText = CosmeticsMenuState.SearchText; CosmeticsMenuState.SetSearchText(searchText.Substring(0, searchText.Length - 1)); flag = true; } continue; } if (c == '\r' || c == '\n') { CosmeticsMenuState.SetSearchMode(v: false); break; } if (c >= ' ') { CosmeticsMenuState.SetSearchText(CosmeticsMenuState.SearchText + c); flag = true; } } if (flag) { __instance.RefreshScrollContent(); } } private static bool ToolsPopupHovered(MenuElementCosmeticButtonPopup popup) { if ((Object)(object)popup.toggleButton != (Object)null && popup.toggleButton.hovering) { return true; } foreach (MenuButton dropdownButton in popup.dropdownButtons) { if ((Object)(object)dropdownButton != (Object)null && dropdownButton.hovering) { return true; } } return false; } } [HarmonyPatch(typeof(MenuElementCosmeticPreset), "GetIcon")] internal static class MoreHeadPresetIconPatch { private static readonly LazyFieldRef _spawnedAvatar = new LazyFieldRef("spawnedAvatar", "preset-icon decoration hiding"); [HarmonyPostfix] private static void Postfix(MenuElementCosmeticPreset __instance) { if (Plugin.ExcludeMoreHeadFromPresetIcons.Value && _spawnedAvatar.TryGet(__instance, out GameObject value) && !((Object)(object)value == (Object)null) && (Object)(object)value.GetComponent() == (Object)null) { value.AddComponent().Init(value.transform, everyFrame: true); } } } [HarmonyPatch] internal static class RandomizeHiddenFilterPatch { private static readonly List _removed = new List(); private static IEnumerable TargetMethods() { yield return AccessTools.Method(typeof(MenuPageCosmetics), "RandomizeAllButton", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(MenuPageCosmetics), "RandomizeBodyButton", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(MenuPageCosmetics), "RandomizeCosmeticsButton", (Type[])null, (Type[])null); } [HarmonyPrefix] private static void Prefix() { _removed.Clear(); BridgeFavoritesManager.EnsureLoaded(); if (!BridgeFavoritesManager.HasAnyHidden()) { return; } MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } try { for (int num = instance.cosmeticUnlocks.Count - 1; num >= 0; num--) { int num2 = instance.cosmeticUnlocks[num]; if (num2 >= 0 && num2 < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[num2]; if ((Object)(object)val != (Object)null && BridgeFavoritesManager.IsHidden(val)) { _removed.Add(num2); instance.cosmeticUnlocks.RemoveAt(num); } } } } catch (Exception ex) { instance.cosmeticUnlocks.AddRange(_removed); _removed.Clear(); BceConsole.LogWarning("RandomizeHiddenFilterPatch: failed to filter hidden cosmetics, skipping: " + ex.Message); } } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix() { if (_removed.Count != 0) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance != (Object)null) { instance.cosmeticUnlocks.AddRange(_removed); instance.Save(); } _removed.Clear(); } } [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception) { if (_removed.Count > 0) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance != (Object)null) { instance.cosmeticUnlocks.AddRange(_removed); } _removed.Clear(); BceConsole.LogWarning("RandomizeHiddenFilterPatch: vanilla threw during Randomize — hidden cosmetics restored to unlock record via Finalizer"); } return __exception; } } [HarmonyPatch(typeof(MenuElementButtonCosmeticCategory), "UpdateHighlight")] internal static class VirtualCategoryHighlightPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(MenuElementButtonCosmeticCategory __instance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 bool flag = CosmeticsMenuState.IsVirtual(__instance.category); bool flag2 = (int)__instance.buttonType == 1 && CosmeticsMenuState.IsVirtual(((Component)__instance).GetComponentInParent()?.selectedCategory); if (!flag && !flag2) { return true; } MenuElementCosmeticHighlight componentInChildren = ((Component)__instance).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren.text).text = "0"; } return false; } } [HarmonyPatch(typeof(MenuElementCosmeticSection), "UpdateHighlight")] internal static class VirtualCategorySectionHighlightPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(MenuElementCosmeticSection __instance) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!CosmeticsMenuState.IsVirtual(__instance.menuPageCosmetics?.selectedCategory)) { return true; } if ((Object)(object)__instance.highlightObj?.text != (Object)null) { ((TMP_Text)__instance.highlightObj.text).text = "0"; } if ((Object)(object)__instance.menuPageCosmetics != (Object)null && __instance.menuPageCosmetics.selectedSubCategory == __instance.subCategory && (Object)(object)__instance.menuPageCosmetics.stickyHeader?.highlightObj?.text != (Object)null) { ((TMP_Text)__instance.menuPageCosmetics.stickyHeader.highlightObj.text).text = "0"; } return false; } } internal sealed class PopupInputGuard : MonoBehaviour { private static readonly Dictionary MenuButtonLocks = new Dictionary(); private static readonly Dictionary MenuButtonEnabledState = new Dictionary(); private static readonly Dictionary MenuSliderLocks = new Dictionary(); private static readonly Dictionary MenuSliderEnabledState = new Dictionary(); private static readonly Dictionary RepoSliderLocks = new Dictionary(); private static readonly Dictionary RepoSliderEnabledState = new Dictionary(); private static readonly Dictionary HoverLocks = new Dictionary(); private static readonly Dictionary HoverEnabledState = new Dictionary(); private readonly List _menuButtons = new List(); private readonly List _menuSliders = new List(); private readonly List _repoSliders = new List(); private readonly List _hoverTargets = new List(); private string _popupName = "Unknown"; internal void Init(Transform popupRoot) { _menuButtons.Clear(); _menuSliders.Clear(); _repoSliders.Clear(); _hoverTargets.Clear(); _popupName = ((Object)((Component)popupRoot).gameObject).name; _menuButtons.AddRange(from b in Object.FindObjectsOfType(true) where (Object)(object)b != (Object)null && !((Component)b).transform.IsChildOf(popupRoot) select b); _menuSliders.AddRange(from s in Object.FindObjectsOfType(true) where (Object)(object)s != (Object)null && !((Component)s).transform.IsChildOf(popupRoot) select s); _repoSliders.AddRange(from s in Object.FindObjectsOfType(true) where (Object)(object)s != (Object)null && !((Component)s).transform.IsChildOf(popupRoot) select s); _hoverTargets.AddRange(from h in Object.FindObjectsOfType(true) where (Object)(object)h != (Object)null && !((Component)h).transform.IsChildOf(popupRoot) && (Object)(object)((Component)h).GetComponent() == (Object)null select h); foreach (MenuButton menuButton in _menuButtons) { if (MenuButtonLocks.TryGetValue(menuButton, out var value)) { MenuButtonLocks[menuButton] = value + 1; continue; } MenuButtonLocks[menuButton] = 1; MenuButtonEnabledState[menuButton] = ((Behaviour)menuButton).enabled; ((Behaviour)menuButton).enabled = false; } foreach (MenuSlider menuSlider in _menuSliders) { if (MenuSliderLocks.TryGetValue(menuSlider, out var value2)) { MenuSliderLocks[menuSlider] = value2 + 1; continue; } MenuSliderLocks[menuSlider] = 1; MenuSliderEnabledState[menuSlider] = ((Behaviour)menuSlider).enabled; ((Behaviour)menuSlider).enabled = false; } foreach (REPOSlider repoSlider in _repoSliders) { if (RepoSliderLocks.TryGetValue(repoSlider, out var value3)) { RepoSliderLocks[repoSlider] = value3 + 1; continue; } RepoSliderLocks[repoSlider] = 1; RepoSliderEnabledState[repoSlider] = ((Behaviour)repoSlider).enabled; ((Behaviour)repoSlider).enabled = false; } foreach (MenuElementHover hoverTarget in _hoverTargets) { if (HoverLocks.TryGetValue(hoverTarget, out var value4)) { HoverLocks[hoverTarget] = value4 + 1; continue; } HoverLocks[hoverTarget] = 1; HoverEnabledState[hoverTarget] = ((Behaviour)hoverTarget).enabled; ((Behaviour)hoverTarget).enabled = false; } } private void OnDisable() { Restore(); } private void OnDestroy() { Restore(); } private void Restore() { foreach (MenuButton menuButton in _menuButtons) { if (!((Object)(object)menuButton == (Object)null) && MenuButtonLocks.TryGetValue(menuButton, out var value)) { if (value <= 1) { MenuButtonLocks.Remove(menuButton); bool value2; bool enabled = MenuButtonEnabledState.TryGetValue(menuButton, out value2) && value2; MenuButtonEnabledState.Remove(menuButton); ((Behaviour)menuButton).enabled = enabled; } else { MenuButtonLocks[menuButton] = value - 1; } } } foreach (MenuSlider menuSlider in _menuSliders) { if (!((Object)(object)menuSlider == (Object)null) && MenuSliderLocks.TryGetValue(menuSlider, out var value3)) { if (value3 <= 1) { MenuSliderLocks.Remove(menuSlider); bool value4; bool enabled2 = MenuSliderEnabledState.TryGetValue(menuSlider, out value4) && value4; MenuSliderEnabledState.Remove(menuSlider); ((Behaviour)menuSlider).enabled = enabled2; } else { MenuSliderLocks[menuSlider] = value3 - 1; } } } foreach (REPOSlider repoSlider in _repoSliders) { if (!((Object)(object)repoSlider == (Object)null) && RepoSliderLocks.TryGetValue(repoSlider, out var value5)) { if (value5 <= 1) { RepoSliderLocks.Remove(repoSlider); bool value6; bool enabled3 = RepoSliderEnabledState.TryGetValue(repoSlider, out value6) && value6; RepoSliderEnabledState.Remove(repoSlider); ((Behaviour)repoSlider).enabled = enabled3; } else { RepoSliderLocks[repoSlider] = value5 - 1; } } } foreach (MenuElementHover hoverTarget in _hoverTargets) { if (!((Object)(object)hoverTarget == (Object)null) && HoverLocks.TryGetValue(hoverTarget, out var value7)) { if (value7 <= 1) { HoverLocks.Remove(hoverTarget); bool value8; bool enabled4 = HoverEnabledState.TryGetValue(hoverTarget, out value8) && value8; HoverEnabledState.Remove(hoverTarget); ((Behaviour)hoverTarget).enabled = enabled4; } else { HoverLocks[hoverTarget] = value7 - 1; } } } _menuButtons.Clear(); _menuSliders.Clear(); _repoSliders.Clear(); _hoverTargets.Clear(); } } internal sealed class PopupScrollGuard : MonoBehaviour { private MenuScrollBox[] _targets = Array.Empty(); internal void Init(Transform popupRoot) { _targets = (from sb in Object.FindObjectsOfType(true) where ((Behaviour)sb).enabled && !((Component)sb).transform.IsChildOf(popupRoot) select sb).ToArray(); MenuScrollBox[] targets = _targets; foreach (MenuScrollBox val in targets) { ((Behaviour)val).enabled = false; } } private void OnDisable() { Restore(); } private void OnDestroy() { Restore(); } private void Restore() { MenuScrollBox[] targets = _targets; foreach (MenuScrollBox val in targets) { if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = true; } } _targets = Array.Empty(); } } internal static class PopupUI { internal const float PopupX = -120f; internal const float TitleGap = 15f; internal const float BtnTopGap = 10f; internal const float BtnRowH = 30f; internal const float ButtonLeftX = -137f; internal const float ButtonRightX = 58f; internal static RectTransform MakeRow(Transform parent) { //IL_0018: 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) RectTransform component = new GameObject("Button Row", new Type[1] { typeof(RectTransform) }).GetComponent(); ((Transform)component).SetParent(parent, false); component.sizeDelta = new Vector2(0f, 30f); return component; } internal static void AttachGuards(REPOPopupPage popup, Transform? parentPopupTransform = null, bool inputGuard = true) { ((Component)popup).gameObject.AddComponent().Init(((Component)popup).transform); if (inputGuard) { ((Component)popup).gameObject.AddComponent().Init(((Component)popup).transform); } if ((Object)(object)parentPopupTransform != (Object)null) { LocalPopupOverlay.Add(((Component)popup).gameObject, parentPopupTransform); } } internal static float ParseFloat(string s) { if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return 0f; } return result; } internal static string ClosestFloat(string[] options, float target) { string result = options[0]; float num = float.MaxValue; foreach (string text in options) { float num2 = Mathf.Abs(ParseFloat(text) - target); if (num2 < num) { num = num2; result = text; } } return result; } internal static string ClosestInt(string[] options, int target) { string result = options[0]; int num = int.MaxValue; foreach (string text in options) { if (int.TryParse(text, out var result2)) { int num2 = Math.Abs(result2 - target); if (num2 < num) { num = num2; result = text; } } } return result; } internal static void AddFloatSlider(REPOPopupPage popup, string label, string[] options, float current, Action onChange, float topPadding = 0f) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider(label, "", (Action)delegate(string opt) { onChange(ParseFloat(opt)); }, scrollView, options, ClosestFloat(options, current), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, topPadding, 0f); } internal static void AddIntSlider(REPOPopupPage popup, string label, string[] options, int current, Action onChange, float topPadding = 0f) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider(label, "", (Action)delegate(string opt) { onChange(ParseFloat(opt)); }, scrollView, options, ClosestInt(options, current), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, topPadding, 0f); } internal static void AfterMouseRelease(MonoBehaviour host, Action open) { if ((Object)(object)host == (Object)null) { open(); } else { host.StartCoroutine(AfterMouseReleaseRoutine(open)); } } private static IEnumerator AfterMouseReleaseRoutine(Action open) { while (Input.GetMouseButton(0)) { yield return null; } yield return null; open(); } } internal sealed class VariantCell : MonoBehaviour { internal MenuButton? Button; internal RawImage? Border; internal RawImage? BgMain; internal Color BaseColor = Color.white; internal bool Equipped; internal Action? OnClick; internal Action? OnHoverEnter; internal Action? OnHoverExit; private bool _lastHover; private bool _init; private void Update() { bool flag = (Object)(object)Button != (Object)null && Button.hovering; if (!_init) { _init = true; _lastHover = flag; Apply(flag); } else if (flag != _lastHover) { _lastHover = flag; Apply(flag); if (flag) { OnHoverEnter?.Invoke(); } else { OnHoverExit?.Invoke(); } } } internal void Refresh() { Apply(_lastHover); } private void Apply(bool hover) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Border != (Object)null) { float num = (Equipped ? 1f : (hover ? 0.65f : 0.3f)); ((Graphic)Border).color = new Color(BaseColor.r * num, BaseColor.g * num, BaseColor.b * num, BaseColor.a); } if ((Object)(object)BgMain != (Object)null) { ((Graphic)BgMain).color = Color32.op_Implicit(Equipped ? new Color32((byte)0, (byte)0, (byte)0, (byte)175) : new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)); } } } internal sealed class VariantPreviewCleaner : MonoBehaviour { private void OnDisable() { CosmeticVariantPopup.ClearPreview(); } private void OnDestroy() { CosmeticVariantPopup.ClearPreview(); } } internal static class MoreHeadDecorations { internal const string ContainerName = "HeadDecorations"; internal static void SetContainersActive(Transform? root, bool active) { if ((Object)(object)root == (Object)null) { return; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(((Object)val).name != "HeadDecorations") && ((Component)val).gameObject.activeSelf != active) { ((Component)val).gameObject.SetActive(active); } } } } internal sealed class MoreHeadDecorationHider : MonoBehaviour { private const float Interval = 0.1f; private Transform _root; private bool _everyFrame; private float _timer; internal void Init(Transform root, bool everyFrame = false) { _root = root; _everyFrame = everyFrame; _timer = 0f; Apply(); } private void OnEnable() { Apply(); } private void LateUpdate() { if (!_everyFrame) { _timer -= Time.deltaTime; if (_timer > 0f) { return; } _timer = 0.1f; } Apply(); } private void Apply() { if ((Object)(object)_root != (Object)null) { MoreHeadDecorations.SetContainersActive(_root, active: false); } } private void OnDestroy() { if ((Object)(object)_root != (Object)null) { MoreHeadDecorations.SetContainersActive(_root, active: true); } } } internal static class MyPluginInfo { public const string PLUGIN_GUID = "Xuaun.MoreHeadBridge"; public const string PLUGIN_NAME = "MoreHead Bridge"; public const string PLUGIN_VERSION = "3.0.0"; } internal sealed class AnimatorLooper : MonoBehaviour { private Animator? _animator; private void Awake() { _animator = ((Component)this).GetComponent(); } private void Update() { //IL_0027: 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) if ((Object)(object)_animator == (Object)null || !((Behaviour)_animator).isActiveAndEnabled) { return; } for (int i = 0; i < _animator.layerCount; i++) { AnimatorStateInfo currentAnimatorStateInfo = _animator.GetCurrentAnimatorStateInfo(i); if (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).loop && ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime >= 1f) { _animator.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash, i, 0f); } } } } internal sealed class BridgeSwapMeshHider : MonoBehaviour { private readonly List _disabled = new List(); internal void Track(Renderer r) { r.enabled = false; _disabled.Add(r); } internal void Restore() { foreach (Renderer item in _disabled) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } _disabled.Clear(); } } internal static class CosmeticPrefabFixer { private static Type? _partShrinkerType; private static bool _partShrinkerResolved; private static bool _inBatch; private static int _batchFixed; private static int _batchCols; private static int _batchRbs; private static int _batchAnimLoops; private static int _batchAnimrLoops; private static int _batchMissingScriptPrefabs; internal static void BeginBatch() { _inBatch = true; _batchFixed = (_batchCols = (_batchRbs = (_batchAnimLoops = (_batchAnimrLoops = (_batchMissingScriptPrefabs = 0))))); } internal static void EndBatch() { _inBatch = false; if (_batchFixed > 0) { BceConsole.LogInfo($"CosmeticPrefabFixer: fixed {_batchFixed} prefab(s) — " + $"removed {_batchCols} collider(s), {_batchRbs} rigidbody(s); " + $"looped {_batchAnimLoops} Animation clip(s), {_batchAnimrLoops} Animator(s).", ConsoleColor.Gray); } if (_batchMissingScriptPrefabs > 0) { BceConsole.LogWarning($"CosmeticPrefabFixer: {_batchMissingScriptPrefabs} prefab(s) have missing " + "MonoBehaviour script(s) — install MoreHeadUtilities if body-part hiding is needed."); } } internal static void Fix(GameObject prefab, string label = "", string? assetId = null) { FixCore(prefab, label, assetId, !_inBatch); } internal static void FixInstance(GameObject instance, string? assetId, bool? remoteFixAnimation = null, bool isRemote = false) { //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Invalid comparison between Unknown and I4 //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Invalid comparison between Unknown and I4 bool flag; bool flag2; if (OverridePreviewContext.IsPreviewActiveForAsset(assetId)) { CosmeticOverrideData data = OverridePreviewContext.Data; if (data != null) { (bool fixCollider, bool fixAnimation) effectiveFixes = CustomizerStore.GetEffectiveFixes(assetId); bool item = effectiveFixes.fixCollider; bool item2 = effectiveFixes.fixAnimation; flag = data.FixCollider ?? item; flag2 = data.FixAnimation ?? item2; goto IL_0094; } } if (!isRemote) { (flag, flag2) = CustomizerStore.GetEffectiveFixes(assetId); } else { bool item3 = CustomizerStore.GetEffectiveFixes(assetId).fixCollider; flag = item3; flag2 = remoteFixAnimation ?? Plugin.LoopBridgeAnimation.Value; } goto IL_0094; IL_0094: int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; if (flag) { Collider[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { num++; Object.Destroy((Object)(object)val); } Rigidbody[] componentsInChildren2 = instance.GetComponentsInChildren(true); foreach (Rigidbody val2 in componentsInChildren2) { num2++; Object.Destroy((Object)(object)val2); } } if (flag2) { Animation[] componentsInChildren3 = instance.GetComponentsInChildren(true); Animator[] componentsInChildren4 = instance.GetComponentsInChildren(true); Animation[] array = componentsInChildren3; foreach (Animation val3 in array) { if ((int)val3.wrapMode != 2) { val3.wrapMode = (WrapMode)2; num3++; } foreach (AnimationState item4 in val3) { AnimationState val4 = item4; if (!((TrackedReference)(object)val4 == (TrackedReference)null) && (int)val4.wrapMode != 2) { val4.wrapMode = (WrapMode)2; } } } Animator[] array2 = componentsInChildren4; foreach (Animator val5 in array2) { if ((Object)(object)val5.runtimeAnimatorController == (Object)null) { continue; } bool flag3 = false; AnimationClip[] animationClips = val5.runtimeAnimatorController.animationClips; foreach (AnimationClip val6 in animationClips) { if ((Object)(object)val6 != (Object)null && !((Motion)val6).isLooping) { flag3 = true; break; } } if (flag3 && (Object)(object)((Component)val5).GetComponent() == (Object)null) { ((Component)val5).gameObject.AddComponent(); num4++; } } } else { AnimatorLooper[] componentsInChildren5 = instance.GetComponentsInChildren(true); foreach (AnimatorLooper animatorLooper in componentsInChildren5) { Object.Destroy((Object)(object)animatorLooper); } } if (num > 0 || num2 > 0 || num3 > 0 || num4 > 0) { BridgeLog.Trace($"FixInstance '{((Object)instance).name}': removed {num} Collider(s), {num2} Rigidbody(s); " + $"looped {num3} Animation(s), {num4} Animator(s)."); } } internal static IEnumerator TryFixMoreHeadPrefabsAsync(int batchSize = 25) { IList list; PropertyInfo prefabProp; try { Type type = Type.GetType("MoreHead.HeadDecorationManager, MoreHead"); if (type == null) { yield break; } PropertyInfo property = type.GetProperty("Decorations", BindingFlags.Static | BindingFlags.Public); if (property == null) { yield break; } list = property.GetValue(null) as IList; if (list == null || list.Count == 0) { yield break; } prefabProp = list[0].GetType().GetProperty("Prefab"); if (prefabProp == null) { yield break; } } catch (Exception ex) { BridgeLog.Trace("MoreHead prefab fix pass skipped: " + ex.Message); yield break; } int count = 0; int processedThisFrame = 0; BeginBatch(); try { foreach (object item in list) { try { object? value = prefabProp.GetValue(item); GameObject val = (GameObject)((value is GameObject) ? value : null); if (val != null) { Fix(val); count++; processedThisFrame++; } } catch (Exception ex2) { BridgeLog.Trace("MoreHead prefab fix item skipped: " + ex2.Message); } if (processedThisFrame >= batchSize) { processedThisFrame = 0; yield return null; } } } finally { EndBatch(); BceConsole.LogInfo($"CosmeticPrefabFixer: scanned {count} MoreHead prefab(s).", ConsoleColor.Gray); } } private static Type? GetPartShrinkerType() { if (!_partShrinkerResolved) { _partShrinkerResolved = true; _partShrinkerType = MoreHeadUtilitiesTypes.FindType("MoreHeadUtilities.PartShrinker"); } return _partShrinkerType; } private static void FixCore(GameObject prefab, string label, string? assetId, bool verbose) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Invalid comparison between Unknown and I4 (bool fixCollider, bool fixAnimation) effectiveFixes = CustomizerStore.GetEffectiveFixes(assetId); bool item = effectiveFixes.fixCollider; bool item2 = effectiveFixes.fixAnimation; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; if (item) { Collider[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { num++; try { Object.DestroyImmediate((Object)(object)val); } catch { try { val.enabled = false; } catch { } } } Rigidbody[] componentsInChildren2 = prefab.GetComponentsInChildren(true); foreach (Rigidbody val2 in componentsInChildren2) { num2++; try { Object.DestroyImmediate((Object)(object)val2); } catch { try { val2.isKinematic = true; val2.useGravity = false; } catch { } } } } if (item2) { Animation[] componentsInChildren3 = prefab.GetComponentsInChildren(true); foreach (Animation val3 in componentsInChildren3) { if ((Object)(object)val3.clip != (Object)null && (int)val3.clip.wrapMode != 2) { val3.clip.wrapMode = (WrapMode)2; num3++; } val3.wrapMode = (WrapMode)2; } Animator[] componentsInChildren4 = prefab.GetComponentsInChildren(true); foreach (Animator val4 in componentsInChildren4) { if ((Object)(object)val4.runtimeAnimatorController == (Object)null) { continue; } bool flag = false; AnimationClip[] animationClips = val4.runtimeAnimatorController.animationClips; foreach (AnimationClip val5 in animationClips) { if ((Object)(object)val5 != (Object)null && !((Motion)val5).isLooping) { flag = true; break; } } if (flag && (Object)(object)((Component)val4).GetComponent() == (Object)null) { ((Component)val4).gameObject.AddComponent(); num4++; } } } string arg = (string.IsNullOrEmpty(label) ? ((Object)prefab).name : label); if (num > 0 || num2 > 0 || num3 > 0 || num4 > 0) { string msg = $"'{arg}': removed {num} Collider(s), {num2} Rigidbody(s); " + $"looped {num3} Animation clip(s), {num4} Animator(s)."; if (verbose) { BceConsole.LogInfo(msg, ConsoleColor.Gray); } else { BridgeLog.Trace(msg); } if (_inBatch) { _batchFixed++; _batchCols += num; _batchRbs += num2; _batchAnimLoops += num3; _batchAnimrLoops += num4; } } Type partShrinkerType = GetPartShrinkerType(); if (partShrinkerType != null) { Component[] componentsInChildren5 = prefab.GetComponentsInChildren(partShrinkerType, true); if (componentsInChildren5.Length != 0) { string msg2 = $"'{arg}': {componentsInChildren5.Length} PartShrinker component(s) — body-part hiding active."; if (verbose) { BceConsole.LogInfo(msg2, ConsoleColor.Gray); } else { BridgeLog.Trace(msg2); } } return; } int num5 = 0; MonoBehaviour[] componentsInChildren6 = prefab.GetComponentsInChildren(true); foreach (MonoBehaviour val6 in componentsInChildren6) { if ((Object)(object)val6 == (Object)null) { num5++; } } if (num5 > 0) { if (!_inBatch) { BceConsole.LogWarning($"'{arg}': {num5} missing script(s) — " + "install MoreHeadUtilities if body-part hiding is needed."); return; } BridgeLog.Trace($"'{arg}': {num5} missing script(s)"); _batchMissingScriptPrefabs++; } } } internal static class MoreHeadUtilitiesTypes { internal static Type? FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == "MoreHeadUtilities") { return assembly.GetType(fullName); } } return null; } } internal static class PartShrinkerBridge { private static bool _initialized; private static bool _available; private static Type? _shrinkerType; private static Type? _hiddenType; private static FieldInfo? _partField; private static FieldInfo? _hideChildrenField; private static MethodInfo? _addMethod; private static MethodInfo? _removeMethod; private static FieldInfo? _hiddenPartsListField; private static MethodInfo? _updateMethod; private static object? _eyeLeftValue; private static object? _eyeRightValue; private static readonly List<(object part, CosmeticType type)> _swapMap = new List<(object, CosmeticType)>(); private static void AddSwapMap(Type partEnum, string name, CosmeticType type) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) try { _swapMap.Add((Enum.Parse(partEnum, name), type)); } catch { } } private static void EnsureInit() { if (_initialized) { return; } _initialized = true; try { _shrinkerType = MoreHeadUtilitiesTypes.FindType("MoreHeadUtilities.PartShrinker"); _hiddenType = MoreHeadUtilitiesTypes.FindType("MoreHeadUtilities.HiddenParts"); if (_shrinkerType == null || _hiddenType == null) { BridgeLog.Trace("MoreHeadUtilities not loaded — PartShrinker bridge inactive"); return; } _partField = AccessTools.Field(_shrinkerType, "partToHide"); _hideChildrenField = AccessTools.Field(_shrinkerType, "hideChildren"); _addMethod = AccessTools.Method(_hiddenType, "AddHiddenPart", (Type[])null, (Type[])null); _removeMethod = AccessTools.Method(_hiddenType, "RemoveHiddenPart", (Type[])null, (Type[])null); _hiddenPartsListField = AccessTools.Field(_hiddenType, "hiddenParts"); _updateMethod = AccessTools.Method(_hiddenType, "UpdateHiddenParts", (Type[])null, (Type[])null); Type nestedType = _hiddenType.GetNestedType("Part"); if (nestedType != null) { _eyeLeftValue = Enum.Parse(nestedType, "EyeLeft"); _eyeRightValue = Enum.Parse(nestedType, "EyeRight"); _swapMap.Clear(); AddSwapMap(nestedType, "LeftArm", (CosmeticType)10); AddSwapMap(nestedType, "RightArm", (CosmeticType)9); AddSwapMap(nestedType, "LeftLeg", (CosmeticType)12); AddSwapMap(nestedType, "RightLeg", (CosmeticType)11); AddSwapMap(nestedType, "Head", (CosmeticType)5); AddSwapMap(nestedType, "Neck", (CosmeticType)6); AddSwapMap(nestedType, "Body", (CosmeticType)7); AddSwapMap(nestedType, "Hips", (CosmeticType)8); } _available = _partField != null && _hideChildrenField != null && _addMethod != null && _removeMethod != null; if (_available) { BceConsole.LogInfo("PartShrinker bridge loaded"); } else { BceConsole.LogWarning("PartShrinker types found but reflection failed — disabled"); } } catch (Exception ex) { BceConsole.LogWarning("PartShrinker bridge init error: " + ex.Message); } } internal static void ResyncFromMountedCosmetics(PlayerAvatarVisuals? avatar) { EnsureInit(); if (!_available || (Object)(object)avatar == (Object)null || _hiddenType == null) { return; } Component component = ((Component)avatar).GetComponent(_hiddenType); if ((Object)(object)component == (Object)null) { return; } try { if (_hiddenPartsListField?.GetValue(component) is IList list) { list.Clear(); } Component[] componentsInChildren = ((Component)avatar).GetComponentsInChildren(_shrinkerType, false); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { object value = _partField.GetValue(val); bool flag = (bool)_hideChildrenField.GetValue(val); _addMethod.Invoke(component, new object[3] { value, flag, false }); } } _updateMethod?.Invoke(component, null); EnforceSwapHiding(avatar); } catch (Exception ex) { BridgeLog.Trace("PartShrinker resync failed: " + ex.Message); } } internal static void EnforceSwapHiding(PlayerAvatarVisuals? avatar) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) EnsureInit(); if (!_available || (Object)(object)avatar == (Object)null || _hiddenType == null) { return; } PlayerCosmetics playerCosmetics = avatar.playerCosmetics; if ((Object)(object)playerCosmetics == (Object)null || playerCosmetics.cosmeticParents == null) { return; } BridgeSwapMeshHider bridgeSwapMeshHider = ((Component)avatar).GetComponent(); bridgeSwapMeshHider?.Restore(); Component component = ((Component)avatar).GetComponent(_hiddenType); if ((Object)(object)component == (Object)null || !(_hiddenPartsListField?.GetValue(component) is IList { Count: not 0 } list)) { return; } foreach (object item in list) { if (item == null) { continue; } CosmeticType type = (CosmeticType)0; bool flag = false; foreach (var item2 in _swapMap) { if (item.Equals(item2.part)) { type = item2.type; flag = true; break; } } if (!flag) { continue; } CosmeticParent val = playerCosmetics.cosmeticParents.Find((CosmeticParent x) => x != null && x.cosmeticType == type); if (val != null) { if (bridgeSwapMeshHider == null) { bridgeSwapMeshHider = ((Component)avatar).gameObject.AddComponent(); } HideSwapRenderers(val, bridgeSwapMeshHider); } } } private static void HideSwapRenderers(CosmeticParent cp, BridgeSwapMeshHider tracker) { if (cp.baseMeshParents == null) { return; } foreach (Transform baseMeshParent in cp.baseMeshParents) { if ((Object)(object)baseMeshParent == (Object)null) { continue; } Renderer[] componentsInChildren = ((Component)baseMeshParent).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled && !IsBaseMesh(cp, ((Component)val).transform)) { tracker.Track(val); } } } } private static bool IsBaseMesh(CosmeticParent cp, Transform t) { if (cp.baseMeshes == null) { return false; } foreach (Transform baseMesh in cp.baseMeshes) { if ((Object)(object)baseMesh != (Object)null && ((Object)(object)t == (Object)(object)baseMesh || t.IsChildOf(baseMesh))) { return true; } } return false; } internal static void SetAllHiddenPartsEnabled(bool enabled) { EnsureInit(); if (_hiddenType == null) { return; } Object[] array = Object.FindObjectsOfType(_hiddenType); foreach (Object val in array) { Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if (val2 != null) { val2.enabled = enabled; } } } internal static void OnSpawn(GameObject cosmetic, PlayerAvatarVisuals? avatar, PlayerCosmetics? pc = null) { Apply(cosmetic, avatar, pc, isAdd: true); } internal static void OnRemove(GameObject cosmetic, PlayerAvatarVisuals? avatar, PlayerCosmetics? pc = null) { Apply(cosmetic, avatar, pc, isAdd: false); } private static void Apply(GameObject cosmetic, PlayerAvatarVisuals? avatar, PlayerCosmetics? pc, bool isAdd) { EnsureInit(); if (_shrinkerType == null || (Object)(object)cosmetic == (Object)null) { return; } Component[] componentsInChildren; try { componentsInChildren = cosmetic.GetComponentsInChildren(_shrinkerType, true); } catch (Exception ex) { BridgeLog.Debug("PartShrinker: component scan failed — " + ex.Message); return; } if (componentsInChildren == null || componentsInChildren.Length == 0) { return; } Component val = null; if (_available && (Object)(object)avatar != (Object)null) { val = ((Component)avatar).GetComponent(_hiddenType); if ((Object)(object)val == (Object)null) { try { val = ((Component)avatar).gameObject.AddComponent(_hiddenType); } catch (Exception ex2) { BridgeLog.Trace("Could not add HiddenParts: " + ex2.Message); } } } MethodInfo methodInfo = (isAdd ? _addMethod : _removeMethod); bool flag = false; bool flag2 = false; Component[] array = componentsInChildren; foreach (Component val2 in array) { if ((Object)(object)val2 == (Object)null) { continue; } try { if (!((Object)(object)val != (Object)null) || !(methodInfo != null)) { continue; } object value = _partField.GetValue(val2); bool flag3 = (bool)_hideChildrenField.GetValue(val2); methodInfo.Invoke(val, new object[3] { value, flag3, true }); if (isAdd) { if (_eyeLeftValue != null && value.Equals(_eyeLeftValue)) { flag = true; } if (_eyeRightValue != null && value.Equals(_eyeRightValue)) { flag2 = true; } } } catch (Exception ex3) { BridgeLog.Trace("PartShrinker " + (isAdd ? "Add" : "Remove") + " failed: " + ex3.Message); } finally { if (isAdd) { MonoBehaviour val3 = (MonoBehaviour)(object)((val2 is MonoBehaviour) ? val2 : null); if (val3 != null) { ((Behaviour)val3).enabled = false; } } } } if (isAdd && (Object)(object)pc != (Object)null && (flag || flag2)) { BridgeCustomTypesBroadcaster bridgeCustomTypesBroadcaster = cosmetic.GetComponent() ?? cosmetic.AddComponent(); bridgeCustomTypesBroadcaster.OwnerPc = pc; if (flag && !bridgeCustomTypesBroadcaster.Types.Contains((Type)17)) { bridgeCustomTypesBroadcaster.Types.Add((Type)17); pc.ConditionCustomSet((Type)17, 0.1f); } if (flag2 && !bridgeCustomTypesBroadcaster.Types.Contains((Type)16)) { bridgeCustomTypesBroadcaster.Types.Add((Type)16); pc.ConditionCustomSet((Type)16, 0.1f); } } EnforceSwapHiding(avatar); } } internal static class PartShrinkerSuppressor { private sealed class PartShrinkerLogFilter : ILogHandler { private readonly ILogHandler _inner; private bool _suppressNext; internal PartShrinkerLogFilter(ILogHandler inner) { _inner = inner; } public void LogException(Exception exception, Object context) { _suppressNext = false; _inner.LogException(exception, context); } public void LogFormat(LogType logType, Object context, string format, params object[] args) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_006e: Unknown result type (might be due to invalid IL or missing references) if ((int)logType == 2) { string text = ((args == null || args.Length == 0) ? null : args[0]?.ToString()) ?? format ?? ""; if (text.Contains("MoreHeadUtilities.PartShrinker")) { _suppressNext = true; return; } if (_suppressNext && text.Contains("referenced script on this Behaviour")) { _suppressNext = false; return; } } _suppressNext = false; _inner.LogFormat(logType, context, format, args); } } private static bool _suppressNextUnityLog; private static int _suppressedCount; private static readonly HashSet _suppressedGoNames = new HashSet(); internal static void InstallWarningFilter() { try { if (!(Debug.unityLogger.logHandler is PartShrinkerLogFilter)) { Debug.unityLogger.logHandler = (ILogHandler)(object)new PartShrinkerLogFilter(Debug.unityLogger.logHandler); BridgeLog.Trace("PartShrinker ILogHandler filter installed"); } } catch (Exception ex) { BceConsole.LogWarning("Could not install PartShrinker ILogHandler filter: " + ex.Message); } } internal static void InstallNativeWarningFilter(Harmony harmony) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("BepInEx.Logging.UnityLogSource"); MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "OnUnityLogMessageReceived", (Type[])null, (Type[])null) : null); if (methodInfo == null) { BridgeLog.Trace("BepInEx.Logging.UnityLogSource.OnUnityLogMessageReceived not found — native PartShrinker warning filter unavailable"); return; } MethodInfo method = typeof(PartShrinkerSuppressor).GetMethod("UnityLogSourcePrefix", BindingFlags.Static | BindingFlags.NonPublic); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); BridgeLog.Trace("PartShrinker native warning filter installed (BepInEx log source patched)"); } catch (Exception ex) { BceConsole.LogWarning("Could not install PartShrinker native warning filter: " + ex.Message); } } internal static void TryApply(Harmony harmony) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown try { Type type = MoreHeadUtilitiesTypes.FindType("MoreHeadUtilities.PartShrinker"); if (type == null) { BridgeLog.Trace("MoreHeadUtilities not loaded — PartShrinker NRE suppressor skipped"); return; } MethodInfo method = typeof(PartShrinkerSuppressor).GetMethod("NreFinalizer", BindingFlags.Static | BindingFlags.NonPublic); int num = 0; string[] array = new string[2] { "OnDisable", "Update" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.Method(type, text, (Type[])null, (Type[])null); if (!(methodInfo == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null); num++; } } if (num > 0) { BridgeLog.Trace($"PartShrinker NRE suppressor loaded ({num} method(s))"); } } catch (Exception ex) { BceConsole.LogWarning("Could not install PartShrinker suppressor: " + ex.Message); } } internal static void FlushSuppressedLog() { if (_suppressedCount == 0) { return; } BceConsole.LogWarning($"Suppressed {_suppressedCount} PartShrinker 'missing script' warning(s) " + "— MoreHeadUtilities is not installed. Install it to fix this (no gameplay impact)."); foreach (string suppressedGoName in _suppressedGoNames) { BridgeLog.Trace(" PartShrinker missing on GO: '" + suppressedGoName + "'"); } _suppressedCount = 0; _suppressedGoNames.Clear(); } private static bool UnityLogSourcePrefix(string message, LogType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)type == 2 && message != null) { if (message.Contains("MoreHeadUtilities.PartShrinker")) { _suppressedCount++; _suppressNextUnityLog = true; return false; } if (_suppressNextUnityLog && message.Contains("referenced script on this Behaviour")) { _suppressNextUnityLog = false; string text = ExtractGoName(message); if (text != null) { _suppressedGoNames.Add(text); } return false; } if (message.Contains("referenced script on this Behaviour") && message.Contains("''")) { return false; } } _suppressNextUnityLog = false; return true; } private static string? ExtractGoName(string message) { int num = message.IndexOf("(Game Object '", StringComparison.Ordinal); if (num < 0) { return null; } num += "(Game Object '".Length; int num2 = message.IndexOf("')", num, StringComparison.Ordinal); if (num2 <= num) { return null; } string text = message.Substring(num, num2 - num); if (!string.IsNullOrEmpty(text) && !(text == "")) { return text; } return null; } private static Exception? NreFinalizer(Exception? __exception) { if (__exception is NullReferenceException) { return null; } return __exception; } } [HarmonyPatch(typeof(PlayerCosmetics), "InstantiateCosmetic")] internal static class PartShrinkerSpawnPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance, CosmeticAsset _cosmeticAsset, GameObject __result) { if (!((Object)(object)__result == (Object)null) && !((Object)(object)__instance == (Object)null) && BridgeIds.IsBridgeAsset(_cosmeticAsset)) { PartShrinkerBridge.OnSpawn(__result, __instance.playerAvatarVisuals, __instance); } } } [HarmonyPatch(typeof(Cosmetic), "Remove")] internal static class PartShrinkerRemovePatch { [HarmonyPrefix] private static void Prefix(Cosmetic __instance) { if (!((Object)(object)__instance == (Object)null) && BridgeIds.IsBridgeAsset(__instance.cosmeticAsset) && !((Object)(object)__instance.playerCosmetics == (Object)null)) { PartShrinkerBridge.OnRemove(((Component)__instance).gameObject, __instance.playerCosmetics.playerAvatarVisuals, __instance.playerCosmetics); } } } [HarmonyPatch(typeof(Cosmetic), "Remove")] internal static class MeshSwitchRemoveResyncPatch { [HarmonyPostfix] private static void Postfix(Cosmetic __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.cosmeticTypeAsset == (Object)null) && __instance.cosmeticTypeAsset.meshSwitch && !((Object)(object)__instance.playerCosmetics == (Object)null)) { PartShrinkerBridge.EnforceSwapHiding(__instance.playerCosmetics.playerAvatarVisuals); } } } internal static class BridgePatcher { private static readonly HashSet MenuTakeoverCluster = new HashSet { "CosmeticsFilterPatch", "CosmeticsMenuStartPatch", "CosmeticsMenuUpdatePatch", "CosmeticsMenuLateUpdatePatch", "ToolsButtonOnSelectPatch", "TogglePopupColorPatch", "TogglePopupRandomizePatch", "TogglePopupResetPatch", "VirtualCategoryHighlightPatch", "WorldCosmeticsMenuStartPatch" }; internal static bool MenuTakeoverBroken { get; private set; } internal static void ApplyAll(Harmony harmony) { int num = 0; List list = null; Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()); foreach (Type type in typesFromAssembly) { try { if (harmony.CreateClassProcessor(type).Patch() != null) { num++; } } catch (Exception ex) { (list ?? (list = new List())).Add(type.Name); BceConsole.LogWarning("Patch " + type.Name + " failed to apply (game update?) — its feature is disabled: " + ex.Message); if (MenuTakeoverCluster.Contains(type.Name)) { MenuTakeoverBroken = true; } } } if (MenuTakeoverBroken) { BceConsole.LogWarning("A cosmetics-menu patch failed — menu enhancements disabled, using the vanilla menu."); } BridgeLog.Debug($"BridgePatcher: {num} patch classes applied" + ((list != null) ? string.Format(", {0} failed: {1}", list.Count, string.Join(", ", list)) : "")); } } [HarmonyPatch(typeof(MetaManager), "CosmeticEquip")] internal static class CosmeticHoverPatch { private enum AnimState { StillRunning, Done, Gone } private static readonly HashSet _scheduled = new HashSet(); private static FieldInfo? _equipLerpField; private static bool _equipLerpWarned; private static string? _suppressedHoverId; private static string? _currentHoverId; private static readonly HashSet _meshlessNoted = new HashSet(); private static bool _captureFailWarned; private static AnimState CheckEquipAnim(CosmeticAsset asset, ref Cosmetic? cached) { if (_equipLerpField == null && !_equipLerpWarned) { _equipLerpField = AccessTools.Field(typeof(Cosmetic), "equipLerp"); if (_equipLerpField == null) { _equipLerpWarned = true; BceConsole.LogWarning("CosmeticHoverPatch: Cosmetic.equipLerp not found — will capture without waiting for animation"); } } if (_equipLerpField == null) { return AnimState.Done; } if ((Object)(object)cached == (Object)null || (Object)(object)cached.cosmeticAsset != (Object)(object)asset) { cached = null; Cosmetic[] array = Object.FindObjectsOfType(); foreach (Cosmetic val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.cosmeticAsset == (Object)(object)asset) { cached = val; break; } } } if ((Object)(object)cached == (Object)null) { return AnimState.Gone; } if (!((float)(_equipLerpField.GetValue(cached) ?? ((object)1f)) >= 1f)) { return AnimState.StillRunning; } return AnimState.Done; } internal static void OnMenuClosed() { _scheduled.Clear(); _suppressedHoverId = null; } internal static void Invalidate(CosmeticAsset asset) { _scheduled.Remove(asset.assetId); } internal static void SuppressWhileHovered(CosmeticAsset asset) { if ((Object)(object)asset != (Object)null) { _suppressedHoverId = asset.assetId; } } internal static void HoverTick(CosmeticAsset? hovered) { _currentHoverId = hovered?.assetId; if (_suppressedHoverId != null && hovered?.assetId != _suppressedHoverId) { _suppressedHoverId = null; } } internal static void TryScheduleCapture(CosmeticAsset asset, MonoBehaviour host) { if (Plugin.AutoCaptureIcons.Value && !((Object)(object)asset == (Object)null) && BridgeIds.IsBridgeAsset(asset) && !IconCapture.HasCache(asset) && !(asset.assetId == _suppressedHoverId) && _scheduled.Add(asset.assetId)) { host.StartCoroutine(CaptureAfterAnimation(asset)); } } [HarmonyPostfix] private static void Postfix(MetaManager __instance, CosmeticAsset _cosmeticAssetNew, bool _isPreview) { if (_isPreview && Plugin.AutoCaptureIcons.Value) { if (!((Object)(object)_cosmeticAssetNew == (Object)null) && BridgeIds.IsBridgeAsset(_cosmeticAssetNew) && !IconCapture.HasCache(_cosmeticAssetNew) && !(_cosmeticAssetNew.assetId == _suppressedHoverId) && _scheduled.Add(_cosmeticAssetNew.assetId)) { ((MonoBehaviour)__instance).StartCoroutine(CaptureAfterAnimation(_cosmeticAssetNew)); } } } private static IEnumerator CaptureAfterAnimation(CosmeticAsset asset) { yield return null; float elapsed = 0f; bool everSeen = false; bool meshless = false; Cosmetic animCosmetic = null; while (elapsed < 3f) { AnimState animState = CheckEquipAnim(asset, ref animCosmetic); if (animState == AnimState.Done) { break; } if (animState == AnimState.StillRunning) { everSeen = true; } else { if (asset.assetId != _currentHoverId) { _scheduled.Remove(asset.assetId); yield break; } if (!everSeen && elapsed >= 0.4f) { meshless = true; WarnMeshlessOnce(asset); break; } } elapsed += Time.unscaledDeltaTime; yield return null; } if (meshless) { yield return null; yield return null; if (asset.assetId != _currentHoverId) { _scheduled.Remove(asset.assetId); yield break; } } else if (CheckEquipAnim(asset, ref animCosmetic) == AnimState.Gone) { _scheduled.Remove(asset.assetId); yield break; } yield return (object)new WaitForEndOfFrame(); if (meshless ? (asset.assetId != _currentHoverId) : (CheckEquipAnim(asset, ref animCosmetic) == AnimState.Gone)) { _scheduled.Remove(asset.assetId); yield break; } bool flag = false; try { flag = IconCapture.TryCapture(asset); } finally { if (!flag) { _scheduled.Remove(asset.assetId); WarnCaptureFailedOnce(); } } } private static void WarnMeshlessOnce(CosmeticAsset asset) { if (_meshlessNoted.Add(asset.assetId)) { BceConsole.LogInfo("Hover icon: '" + ((Object)asset).name + "' spawned no mesh of its own (hide-only effect or failed to mount) — capturing from the avatar."); } } private static void WarnCaptureFailedOnce() { if (!_captureFailWarned) { _captureFailWarned = true; BceConsole.LogWarning("Could not generate an icon on hover for a Bridge cosmetic."); } } } [HarmonyPatch(typeof(CosmeticOffsetCondition), "AnimateInstant")] internal static class CosmeticOffsetConditionGuardPatch { [HarmonyPrefix] private static bool Prefix(CosmeticOffsetCondition __instance) { return (Object)(object)__instance != (Object)null; } } [HarmonyPatch(typeof(Cosmetic), "Setup")] internal static class CosmeticSetupFixCrownPatch { [HarmonyPrefix] private static void Prefix(Cosmetic __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 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown if (((int)__instance.type == 0 || (int)__instance.type == 5) && CustomizerStore.GetEffectiveFixCrown(__instance.cosmeticAsset?.assetId) && !BridgeIds.IsBridgeAsset(__instance.cosmeticAsset) && !((Object)(object)((Component)__instance).GetComponentInChildren(true) != (Object)null)) { GameObject val = new GameObject("Crown Fix (Bridge)"); val.transform.SetParent(((Component)__instance).transform, false); val.AddComponent(); } } } [HarmonyPatch(typeof(Cosmetic), "Setup")] internal static class CosmeticSetupPatch { [HarmonyPrefix] private static void Prefix(Cosmetic __instance) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Invalid comparison between Unknown and I4 //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected I4, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown if ((Object)(object)__instance == (Object)null) { return; } CosmeticAsset cosmeticAsset = __instance.cosmeticAsset; if (BridgeIds.IsCustomizable(cosmeticAsset)) { PlayerCosmetics playerCosmetics = __instance.playerCosmetics; if ((Object)(object)playerCosmetics != (Object)null && AvatarIdentity.TryGetRemoteActor(playerCosmetics, out var actorNumber)) { CustomizerSync.TryGetRemote(actorNumber, cosmeticAsset.assetId, out BridgeSyncPayload data); CosmeticType ownerType = MoreHeadCosmeticMountPatch.GetRemoteEffectiveType(cosmeticAsset, data).cosmeticType; if (ownerType != __instance.type) { MetaManager instance = MetaManager.instance; int num = (int)ownerType; if (instance?.cosmeticTypeAssets != null && num >= 0 && num < instance.cosmeticTypeAssets.Count) { __instance.cosmeticTypeAsset = instance.cosmeticTypeAssets[num]; } CosmeticParent val = playerCosmetics.cosmeticParents?.Find((CosmeticParent x) => x.cosmeticType == ownerType); if (val != null) { __instance.cosmeticParent = val; } __instance.type = ownerType; } } } if (!BridgeIds.IsBridgeAsset(cosmeticAsset)) { return; } if ((Object)(object)__instance.cosmeticTypeAsset != (Object)null && __instance.cosmeticTypeAsset.customTypeList == null) { __instance.cosmeticTypeAsset.customTypeList = new List(); } if (((int)__instance.type == 0 || (int)__instance.type == 5) && (Object)(object)((Component)__instance).GetComponentInChildren(true) == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } if (__instance.meshParents == null) { __instance.meshParents = new List(); } if (((Object)(object)__instance.cosmeticTypeAsset != (Object)null && __instance.cosmeticTypeAsset.meshSwitch) || __instance.meshParents.Count != 0) { return; } foreach (Transform item2 in ((Component)__instance).transform) { Transform item = item2; __instance.meshParents.Add(item); } } [HarmonyPostfix] private static void Postfix(Cosmetic __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.cosmeticTypeAsset == (Object)null) && __instance.cosmeticTypeAsset.meshSwitch) { PlayerAvatarVisuals avatar = (((Object)(object)__instance.playerCosmetics != (Object)null) ? __instance.playerCosmetics.playerAvatarVisuals : null); PartShrinkerBridge.EnforceSwapHiding(avatar); } } } [HarmonyPatch(typeof(CosmeticSprings), "Awake")] internal static class CosmeticSpringGuardPatch { [HarmonyPostfix] private static void Postfix(CosmeticSprings __instance) { if (__instance.springs == null) { return; } foreach (CosmeticSpring spring in __instance.springs) { if (spring != null) { SpringQuaternionSystem springSystem = spring.springSystem; if (springSystem == null || (Object)(object)springSystem.target == (Object)null || (Object)(object)springSystem.transform == (Object)null) { spring.disabled = true; } } } } } [HarmonyPatch(typeof(CosmeticSpring), "JumpImpulse")] internal static class CosmeticSpringJumpImpulseGuardPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSpring __instance) { return (Object)(object)__instance?.springSystem?.target != (Object)null; } } [HarmonyPatch(typeof(Cosmetic), "CustomTypesLogic")] internal static class CustomTypesLogicNpeGuardPatch { private static readonly HashSet _skipAssets = new HashSet(); [HarmonyPrefix] private static bool Prefix(Cosmetic __instance) { BridgeCustomTypesBroadcaster bridgeCustomTypesBroadcaster = default(BridgeCustomTypesBroadcaster); if ((Object)(object)__instance != (Object)null && ((Component)__instance).TryGetComponent(ref bridgeCustomTypesBroadcaster) && bridgeCustomTypesBroadcaster.SuppressNative) { return false; } string text = __instance?.cosmeticAsset?.assetId; if (text == null) { return true; } if (!_skipAssets.Contains(text)) { return true; } int valueOrDefault = (__instance.cosmeticAsset?.customTypeList?.Count).GetValueOrDefault(); if (valueOrDefault > 0) { _skipAssets.Remove(text); return true; } return false; } [HarmonyFinalizer] private static Exception? Finalizer(Cosmetic __instance, Exception? __exception) { if (!(__exception is NullReferenceException)) { return __exception; } string text = __instance?.cosmeticAsset?.assetId; if (text != null) { _skipAssets.Add(text); } if (!Plugin.ShowBridgeDebugLogs.Value || !BridgeIds.IsBridgeAsset(__instance?.cosmeticAsset)) { return null; } return __exception; } } [HarmonyPatch(typeof(Cosmetic), "EquipAnimation")] internal static class EquipAnimationNpeGuardPatch { [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception) { if (__exception is NullReferenceException) { return null; } return __exception; } } [HarmonyPatch(typeof(MetaManager), "GetCosmeticsToUnequip")] internal static class GetCosmeticsToUnequipPatch { [HarmonyPostfix] private static void Postfix(CosmeticAsset _cosmeticAssetNew, List __result) { if (__result.Count == 0 || (Object)(object)_cosmeticAssetNew == (Object)null || HhhCosmeticLoader.WorldAssetIds.Count == 0) { return; } bool flag = HhhCosmeticLoader.IsWorldAsset(_cosmeticAssetNew); for (int num = __result.Count - 1; num >= 0; num--) { CosmeticAsset val = __result[num]; if (!((Object)(object)val == (Object)null) && flag != HhhCosmeticLoader.IsWorldAsset(val)) { __result.RemoveAt(num); } } } } internal static class MoreHeadButtonId { internal const string Prefix = "Button - M"; internal const string LabelPrefix = "M"; } internal static class HideMoreHeadButtonCreatePatch { internal static void TryApply(Harmony harmony) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(MenuAPI), "CreateREPOButton", (Type[])null, (Type[])null); if (methodInfo == null) { BridgeLog.Trace("MenuAPI.CreateREPOButton not found — MoreHead button zero-flash hide skipped"); return; } MethodInfo method = typeof(HideMoreHeadButtonCreatePatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.NonPublic); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); BridgeLog.Trace("MoreHead button zero-flash hide applied"); } catch (Exception ex) { BceConsole.LogWarning("Could not apply MoreHead button zero-flash hide: " + ex.Message); } } private static void Postfix(REPOButton __result, string text) { if (Plugin.HideMoreHeadButton.Value && !((Object)(object)__result == (Object)null) && text != null && text.StartsWith("M", StringComparison.Ordinal)) { ((Component)__result).gameObject.SetActive(false); } } } [HarmonyPatch(typeof(MenuButton), "OnEnable")] internal static class HideMoreHeadButtonOnEnablePatch { [HarmonyPostfix] private static void Postfix(MenuButton __instance) { if (Plugin.HideMoreHeadButton.Value && !((Object)(object)__instance == (Object)null) && ((Object)((Component)__instance).gameObject).name.StartsWith("Button - M")) { ((Component)__instance).gameObject.SetActive(false); } } } [HarmonyPatch(typeof(MenuManager), "Start")] internal static class HideMoreHeadUIPatch { [HarmonyPriority(200)] [HarmonyPostfix] private static void Postfix() { Apply(Plugin.HideMoreHeadButton.Value); } internal static void Apply(bool hide) { MenuButton[] array = Object.FindObjectsOfType(true); foreach (MenuButton val in array) { if (((Object)((Component)val).gameObject).name.StartsWith("Button - M")) { ((Component)val).gameObject.SetActive(!hide); } } } } [HarmonyPatch(typeof(MenuPage), "PageStateSet")] internal static class HideMoreHeadUIPageStatePatch { [HarmonyPostfix] private static void Postfix(PageState pageState) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 if (Plugin.HideMoreHeadButton.Value && (((int)pageState <= 1 || (int)pageState == 4) ? true : false)) { RuntimeConfigApplier.HideMoreHeadButtonsSoon(); } } } [HarmonyPatch(typeof(MenuElementCosmeticButton), "UpdateIcon")] internal static class MenuIconNpeGuardPatch { [HarmonyFinalizer] private static Exception? Finalizer(MenuElementCosmeticButton __instance, Exception? __exception) { if (!(__exception is NullReferenceException)) { return __exception; } if (!BridgeIds.IsBridgeAsset(__instance?.cosmeticAsset)) { return __exception; } if (!Plugin.ShowBridgeDebugLogs.Value) { return null; } return __exception; } } [HarmonyPatch(typeof(CosmeticAsset), "GetRarityColor")] internal static class ModdedRarityBorderPatch { private static readonly Color OrangeColor = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)77, (byte)0, byte.MaxValue)); private static readonly Color PurpleColor = Color32.op_Implicit(new Color32((byte)168, (byte)26, (byte)235, byte.MaxValue)); [HarmonyPostfix] private static void Postfix(CosmeticAsset __instance, ref Color __result) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) if (BorderTheme.TryResolve(__instance, out var theme)) { __result = (theme.HasSolid ? theme.Solid : Color.white); } else if (CustomizerStore.IsModdedForAsset(__instance)) { __result = OrangeColor; } else if (CustomizerStore.IsNonBridgeModdedForAsset(__instance)) { __result = PurpleColor; } } } [HarmonyPatch(typeof(PlayerCosmetics), "InstantiateCosmetic")] internal static class MoreHeadCosmeticMountPatch { private readonly struct ResolvedOverride { public readonly List? Offsets; public readonly List? CustomTypes; public readonly CosmeticCrownConfig? Crown; public readonly CosmeticHideConfig? Hide; public readonly DeathHeadFloorPose? FloorPose; public readonly bool HasRecord; public readonly CosmeticType EffectiveType; public readonly bool IsWorld; public readonly bool? Tintable; public ResolvedOverride(List? offsets, List? customTypes, CosmeticCrownConfig? crown, CosmeticHideConfig? hide, DeathHeadFloorPose? floorPose, bool hasRecord, CosmeticType effectiveType, bool isWorld, bool? tintable) { //IL_002e: 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) Offsets = offsets; CustomTypes = customTypes; Crown = crown; Hide = hide; FloorPose = floorPose; HasRecord = hasRecord; EffectiveType = effectiveType; IsWorld = isWorld; Tintable = tintable; } } private static readonly FieldInfo? _conditionsCustomField = AccessTools.Field(typeof(PlayerCosmetics), "conditionsCustom"); private static readonly FieldInfo? _hccTimerField = AccessTools.Field(typeof(HideConditionCustom), "timer"); private static readonly FieldInfo? _cosmeticEquippedField = AccessTools.Field(typeof(PlayerCosmetics), "cosmeticEquipped"); private static readonly FieldInfo? _cosmeticEquippedRawField = AccessTools.Field(typeof(PlayerCosmetics), "cosmeticEquippedRaw"); private static readonly FieldInfo? _cosmeticAssetField = AccessTools.Field(typeof(Cosmetic), "cosmeticAsset"); private static readonly MethodInfo? _conditionsSetupMethod = AccessTools.Method(typeof(PlayerCosmetics), "ConditionsSetup", (Type[])null, (Type[])null); private static readonly MethodInfo? _setupColorsLogicMethod = AccessTools.Method(typeof(PlayerCosmetics), "SetupColorsLogic", (Type[])null, (Type[])null); private static readonly FieldInfo? _positionDefaultField = AccessTools.Field(typeof(CosmeticOffsetCondition), "positionDefault"); private static readonly FieldInfo? _rotationDefaultField = AccessTools.Field(typeof(CosmeticOffsetCondition), "rotationDefault"); private static readonly FieldInfo? _scaleDefaultField = AccessTools.Field(typeof(CosmeticOffsetCondition), "scaleDefault"); private static readonly HashSet _pendingRefresh = new HashSet(); private static readonly Dictionary<(int, string), Transform?> _boneCache = new Dictionary<(int, string), Transform>(); private static readonly ConditionalWeakTable> _reconcileHidden = new ConditionalWeakTable>(); [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance, CosmeticAsset _cosmeticAsset, GameObject __result) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Invalid comparison between Unknown and I4 if ((Object)(object)__result == (Object)null || !BridgeIds.IsCustomizable(_cosmeticAsset)) { return; } bool flag = BridgeIds.IsBridgeAsset(_cosmeticAsset); int actorNumber; bool flag2 = AvatarIdentity.TryGetRemoteActor(__instance, out actorNumber); BridgeSyncPayload data = null; if (flag2) { CustomizerSync.TryGetRemote(actorNumber, _cosmeticAsset.assetId, out data); } if (flag && (Object)(object)__instance.playerAvatarVisuals == (Object)null && (Object)(object)__instance.deathHead != (Object)null) { __result.SetActive(false); return; } bool flag3 = OverridePreviewContext.IsActiveFor(__instance, _cosmeticAsset.assetId); ResolvedOverride resolvedOverride = Resolve(_cosmeticAsset, flag3, flag2, data); CosmeticPrefabFixer.FixInstance(__result, _cosmeticAsset.assetId, (!flag2) ? ((bool?)null) : data?.FixAnimation, flag2); if (resolvedOverride.Tintable != false) { BridgeTintHelper.InjectBridgeTintMaterials(__result, _cosmeticAsset, resolvedOverride.Tintable); } if (flag) { TryMount(__instance, __result, _cosmeticAsset, resolvedOverride.EffectiveType, resolvedOverride.IsWorld); } else { ReparentToVanillaAnchor(__instance, __result, resolvedOverride.EffectiveType); } bool suppressNativeCustomTypes = resolvedOverride.HasRecord && NativeCustomTypeImport.HasNativeAnnounceList(_cosmeticAsset); InjectOffsetConditions(__result, _cosmeticAsset, __instance, resolvedOverride.Offsets, resolvedOverride.CustomTypes, suppressNativeCustomTypes); if ((int)resolvedOverride.EffectiveType == 0 || (int)resolvedOverride.EffectiveType == 5) { ApplyCrownConfig(__result, resolvedOverride.Crown); } if (flag) { DeathHeadFloorPose floorPose = resolvedOverride.FloorPose; if (floorPose != null && floorPose.ReactWhenAlive && (Object)(object)__result.GetComponent() == (Object)null) { Cosmetic component = __result.GetComponent(); if ((Object)(object)component != (Object)null) { __result.AddComponent().Init(component, resolvedOverride.FloorPose); } } } CosmeticHideConfig hide = resolvedOverride.Hide; if (hide != null && hide.HasAny && (Object)(object)__result.GetComponent() == (Object)null) { Cosmetic component2 = __result.GetComponent(); if ((Object)(object)component2 != (Object)null) { __result.AddComponent().Init(component2, resolvedOverride.Hide); } } SwayMode? mode; bool hasValue; CosmeticSprings[] componentsInChildren; bool flag4; if (!flag2) { mode = ((flag3 && OverridePreviewContext.Data != null) ? OverridePreviewContext.Data.EnableSway : CustomizerStore.GetEffectiveSway(_cosmeticAsset.assetId)); hasValue = mode.HasValue; componentsInChildren = __result.GetComponentsInChildren(true); if (hasValue && componentsInChildren.Length != 0) { CosmeticSprings[] array = componentsInChildren; foreach (CosmeticSprings val in array) { ((Behaviour)val).enabled = false; } } if (mode.HasValue) { SwayMode valueOrDefault = mode.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 2u) { flag4 = true; goto IL_0270; } } flag4 = false; goto IL_0270; } if (BridgeIds.IsBridgeAsset(_cosmeticAsset) || data == null) { return; } SwayMode? enableSway = data.EnableSway; bool hasValue2 = enableSway.HasValue; CosmeticSprings[] componentsInChildren2 = __result.GetComponentsInChildren(true); if (hasValue2 && componentsInChildren2.Length != 0) { CosmeticSprings[] array2 = componentsInChildren2; foreach (CosmeticSprings val2 in array2) { ((Behaviour)val2).enabled = false; } } if (enableSway.HasValue) { SwayMode valueOrDefault = enableSway.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 2u) { flag4 = true; goto IL_033d; } } flag4 = false; goto IL_033d; IL_0270: if (flag4 && (hasValue || componentsInChildren.Length == 0)) { Cosmetic component3 = __result.GetComponent(); if ((Object)(object)component3 != (Object)null && (Object)(object)__result.GetComponent() == (Object)null) { BridgeSwaySpring bridgeSwaySpring = __result.AddComponent(); bridgeSwaySpring.Init(component3, CosmeticSwayHelper.SwayModeToFactor(mode)); } } return; IL_033d: if (flag4 && (hasValue2 || componentsInChildren2.Length == 0)) { Cosmetic component4 = __result.GetComponent(); if ((Object)(object)component4 != (Object)null && (Object)(object)__result.GetComponent() == (Object)null) { BridgeSwaySpring bridgeSwaySpring2 = __result.AddComponent(); bridgeSwaySpring2.Init(component4, CosmeticSwayHelper.SwayModeToFactor(enableSway)); } } } private static ResolvedOverride Resolve(CosmeticAsset asset, bool isPreview, bool isRemote, BridgeSyncPayload? remoteData) { //IL_0024: 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_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) CosmeticType effectiveType; bool isWorld; if (isRemote) { (effectiveType, isWorld) = GetRemoteEffectiveType(asset, remoteData); } else { CosmeticType type = asset.type; bool flag = HhhCosmeticLoader.IsWorldAsset(asset); isWorld = flag; effectiveType = type; } bool? tintable = (isRemote ? new bool?(remoteData?.Tintable ?? CustomizerStore.GetRemoteFallbackTintable(asset)) : ((bool?)null)); if (isPreview) { CosmeticOverrideData data = OverridePreviewContext.Data; if (data != null) { return new ResolvedOverride(data.Offsets, data.CustomTypes, data.Crown, data.HideConditions, data.FloorPose, hasRecord: true, effectiveType, isWorld, tintable); } CustomizerStore.TryGet(asset.assetId, out CosmeticOverrideData data2); return new ResolvedOverride(data2?.Offsets, data2?.CustomTypes, data2?.Crown, data2?.HideConditions, data2?.FloorPose, data2 != null, effectiveType, isWorld, tintable); } if (isRemote) { return new ResolvedOverride(remoteData?.Offsets, remoteData?.CustomTypes, remoteData?.Crown, remoteData?.HideConditions, remoteData?.FloorPose, remoteData != null, effectiveType, isWorld, tintable); } CustomizerStore.TryGet(asset.assetId, out CosmeticOverrideData data3); return new ResolvedOverride(data3?.Offsets, data3?.CustomTypes, data3?.Crown, data3?.HideConditions, data3?.FloorPose, data3 != null, effectiveType, isWorld, tintable); } internal static bool IsWorldFor(CosmeticAsset asset, int remoteActor) { if (remoteActor > 0) { CustomizerSync.TryGetRemote(remoteActor, asset.assetId, out BridgeSyncPayload data); return GetRemoteEffectiveType(asset, data).isWorld; } return HhhCosmeticLoader.IsWorldAsset(asset); } internal static (CosmeticType cosmeticType, bool isWorld) GetRemoteEffectiveType(CosmeticAsset asset, BridgeSyncPayload? remoteData) { if (remoteData == null || !remoteData.Type.HasValue) { return CustomizerStore.GetRemoteFallbackType(asset); } return CustomizerStore.MapOverrideToVanilla(remoteData.Type.Value); } private static void TryMount(PlayerCosmetics instance, GameObject result, CosmeticAsset asset, CosmeticType effectiveType, bool isWorld) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarVisuals == (Object)null) { return; } GameObject val = ((PrefabRef)(object)asset.prefab)?.Prefab; if ((Object)(object)val == (Object)null) { return; } if (isWorld) { MountWorldCosmetic(result, ((Component)instance.playerAvatarVisuals).transform, val, asset.assetId); return; } string boneName; if ((int)effectiveType == 1) { boneName = "ANIM ARM R SCALE"; } else { if ((int)effectiveType != 2) { if (effectiveType != asset.type) { ReparentToVanillaAnchor(instance, result, effectiveType); } return; } boneName = "code_arm_l"; } Transform val2 = FindByName(((Component)instance.playerAvatarVisuals).transform, boneName); if ((Object)(object)val2 != (Object)null) { Mount(result, val2, val); } } private static void ReparentToVanillaAnchor(PlayerCosmetics instance, GameObject result, CosmeticType effectiveType) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0089: Unknown result type (might be due to invalid IL or missing references) if (instance?.cosmeticParents == null) { return; } CosmeticParent val = instance.cosmeticParents.Find((CosmeticParent p) => p.cosmeticType == effectiveType); if (!((Object)(object)val?.parent == (Object)null)) { result.transform.SetParent(val.parent, false); if (val.resetTransform) { result.transform.localPosition = Vector3.zero; result.transform.localRotation = Quaternion.identity; result.transform.localScale = Vector3.one; } } } internal static List? GetEquippedCosmetics(PlayerCosmetics pc) { return _cosmeticEquippedField?.GetValue(pc) as List; } internal static CosmeticAsset? GetCosmeticAsset(Cosmetic c) { object? obj = _cosmeticAssetField?.GetValue(c); return (CosmeticAsset?)((obj is CosmeticAsset) ? obj : null); } internal static void InvokeConditionsSetup(PlayerCosmetics pc) { _conditionsSetupMethod?.Invoke(pc, null); } internal static void InvokeSetupColorsLogic(PlayerCosmetics pc) { if (pc?.colorsEquipped != null) { _setupColorsLogicMethod?.Invoke(pc, new object[1] { pc.colorsEquipped }); } } internal static void ResetAndDestroy(Transform t, CosmeticOffsetCondition comp) { ResetTransformToDefault(t, (CosmeticOffsetCondition[])(object)new CosmeticOffsetCondition[1] { comp }); Object.DestroyImmediate((Object)(object)comp); } internal static void ResetAndDestroyAll(Transform t, CosmeticOffsetCondition[] comps) { ResetTransformToDefault(t, comps); foreach (CosmeticOffsetCondition val in comps) { Object.DestroyImmediate((Object)(object)val); } } internal static void InjectOffsetConditions(GameObject instance, CosmeticAsset asset, PlayerCosmetics? ownerPc, List? offsets, List? customTypes = null, bool suppressNativeCustomTypes = false) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: 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_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) if (((!OverridePreviewContext.IsActiveFor(ownerPc, asset.assetId)) ? CustomizerStore.GetEffectiveUseFitOffsets(asset.assetId) : (OverridePreviewContext.Data?.UseFitOffsets ?? Plugin.UseVanillaPositionFixes.Value)) && BridgeIds.IsBridgeAsset(asset) && !HhhCosmeticLoader.IsWorldAsset(asset) && OffsetSeedDefaults.HasDefaults(asset.type)) { offsets = OffsetSeedDefaults.MergeInto(asset.type, offsets); } if ((offsets == null || offsets.Count <= 0) && (customTypes == null || customTypes.Count <= 0) && !suppressNativeCustomTypes) { return; } if (offsets != null && offsets.Count > 0) { Vector3 localPosition = instance.transform.localPosition; Quaternion localRotation = instance.transform.localRotation; Vector3 localScale = instance.transform.localScale; Vector3 center = Vector3.zero; if (HasFit(offsets)) { GameObject val = ((PrefabRef)(object)asset.prefab)?.Prefab; if (val != null) { TryGetMeshCenterRootLocal(val, out center); } } Vector3 val2 = localPosition + localRotation * Vector3.Scale(localScale, center); CosmeticOffsetCondition val3 = instance.AddComponent(); val3.offsets = new List(); Vector3 val4 = default(Vector3); Vector3 eulerAngles = default(Vector3); Vector3 val5 = default(Vector3); foreach (CosmeticOffsetEntry offset in offsets) { ((Vector3)(ref val4))..ctor(offset.PosX, offset.PosY, offset.PosZ); ((Vector3)(ref eulerAngles))..ctor(offset.RotX, offset.RotY, offset.RotZ); ((Vector3)(ref val5))..ctor(offset.ScaleX, offset.ScaleY, offset.ScaleZ); if (OffsetSeedDefaults.IsFitTrigger(offset.TriggerType)) { Quaternion val6 = localRotation * Quaternion.Euler(eulerAngles); Vector3 val7 = Vector3.Scale(localScale, val5); val4 = val2 - val6 * Vector3.Scale(val7, center) + val4; eulerAngles = ((Quaternion)(ref val6)).eulerAngles; val5 = val7; } val3.offsets.Add(new Offset { setupName = ((object)offset.TriggerType/*cast due to .constrained prefix*/).ToString(), cosmeticTypes = new List(), customTypes = new List { offset.TriggerType }, playerPoses = new List(), cosmetics = new List(), position = val4, rotation = eulerAngles, scale = val5, lerpSpeed = Mathf.Max(0.1f, offset.LerpSpeed) }); } if (!BridgeIds.IsBridgeAsset(asset)) { NativeOffsetImport.AbsorbAndStrip(instance, val3); } } if (!((customTypes != null && customTypes.Count > 0) || suppressNativeCustomTypes)) { return; } BridgeCustomTypesBroadcaster bridgeCustomTypesBroadcaster = instance.AddComponent(); bridgeCustomTypesBroadcaster.Types = ((customTypes != null && customTypes.Count > 0) ? new List(customTypes) : new List()); bridgeCustomTypesBroadcaster.OwnerPc = ownerPc; bridgeCustomTypesBroadcaster.SuppressNative = suppressNativeCustomTypes; if ((Object)(object)ownerPc != (Object)null && customTypes != null && customTypes.Count > 0) { foreach (Type customType in customTypes) { PrimeCustomCondition(ownerPc, customType); } } NativeCustomTypeImport.AbsorbAndStrip(instance, asset, bridgeCustomTypesBroadcaster); } private static void PrimeCustomCondition(PlayerCosmetics pc, Type type) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown if (!(_conditionsCustomField?.GetValue(pc) is IList list)) { return; } foreach (object item in list) { HideConditionCustom val = (HideConditionCustom)((item is HideConditionCustom) ? item : null); if (val != null && val.type == type) { _hccTimerField?.SetValue(val, 0.1f); return; } } HideConditionCustom val2 = new HideConditionCustom { type = type }; _hccTimerField?.SetValue(val2, 0.1f); list.Add(val2); } private static bool HasFit(List list) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) foreach (CosmeticOffsetEntry item in list) { if (OffsetSeedDefaults.IsFitTrigger(item.TriggerType)) { return true; } } return false; } private static bool TryGetMeshCenterRootLocal(GameObject root, out Vector3 center) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) center = Vector3.zero; Matrix4x4 worldToLocalMatrix = root.transform.worldToLocalMatrix; Bounds b = default(Bounds); bool any = false; MeshFilter[] componentsInChildren = root.GetComponentsInChildren(true); foreach (MeshFilter val in componentsInChildren) { if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMesh != (Object)null) { EncapsulateMesh(ref b, ref any, worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix, val.sharedMesh); } } SkinnedMeshRenderer[] componentsInChildren2 = root.GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sharedMesh != (Object)null) { EncapsulateMesh(ref b, ref any, worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix, val2.sharedMesh); } } if (any) { center = ((Bounds)(ref b)).center; } return any; } private static void EncapsulateMesh(ref Bounds b, ref bool any, Matrix4x4 toRoot, Mesh mesh) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_001d: 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_0032: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = mesh.bounds; Vector3 center = ((Bounds)(ref bounds)).center; bounds = mesh.bounds; Vector3 extents = ((Bounds)(ref bounds)).extents; for (int i = 0; i < 8; i++) { Vector3 val = ((Matrix4x4)(ref toRoot)).MultiplyPoint3x4(center + new Vector3(((i & 1) == 0) ? (0f - extents.x) : extents.x, ((i & 2) == 0) ? (0f - extents.y) : extents.y, ((i & 4) == 0) ? (0f - extents.z) : extents.z)); if (!any) { b = new Bounds(val, Vector3.zero); any = true; } else { ((Bounds)(ref b)).Encapsulate(val); } } } internal static void ApplyCrownConfig(GameObject instance, CosmeticCrownConfig? crown) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if (crown == null) { Transform val = instance.transform.Find("Crown Target Bridge"); if ((Object)(object)val != (Object)null) { CosmeticPlayerCrown componentInChildren = instance.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.targetMain == (Object)(object)val) { componentInChildren.targetMain = null; } Object.Destroy((Object)(object)((Component)val).gameObject); } return; } Transform val2 = instance.transform.Find("Crown Target Bridge"); if ((Object)(object)val2 == (Object)null) { GameObject val3 = new GameObject("Crown Target Bridge"); val3.transform.SetParent(instance.transform, false); val2 = val3.transform; } val2.localPosition = new Vector3(crown.PosX, crown.PosY, crown.PosZ); val2.localRotation = Quaternion.Euler(crown.RotX, crown.RotY, crown.RotZ); val2.localScale = new Vector3(crown.ScaleX, crown.ScaleY, crown.ScaleZ); CosmeticPlayerCrown val4 = instance.GetComponentInChildren(true); if ((Object)(object)val4 == (Object)null) { val4 = instance.AddComponent(); } val4.targetMain = val2; val4.priority = crown.Priority; val4.disableSpring = crown.DisableSpring; } internal static void Mount(GameObject instance, Transform parent, GameObject sourcePrefab) { //IL_0019: 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_0045: Unknown result type (might be due to invalid IL or missing references) instance.transform.SetParent(parent, false); instance.transform.localPosition = sourcePrefab.transform.localPosition; instance.transform.localRotation = sourcePrefab.transform.localRotation; instance.transform.localScale = sourcePrefab.transform.localScale; } private static void ResetTransformToDefault(Transform t, CosmeticOffsetCondition[] conditions) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (conditions.Length != 0) { CosmeticOffsetCondition obj = conditions[0]; if (_positionDefaultField?.GetValue(obj) is Vector3 localPosition) { t.localPosition = localPosition; } if (_rotationDefaultField?.GetValue(obj) is Vector3 localEulerAngles) { t.localEulerAngles = localEulerAngles; } if (_scaleDefaultField?.GetValue(obj) is Vector3 localScale) { t.localScale = localScale; } } } internal static void ReinstantiateCosmetic(CosmeticAsset asset) { PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { if (!IsLocalPlayerCosmetics(val) || !(_cosmeticEquippedField?.GetValue(val) is List list)) { continue; } bool flag = false; foreach (Cosmetic item in list) { object? obj = _cosmeticAssetField?.GetValue(item); CosmeticAsset val2 = (CosmeticAsset)((obj is CosmeticAsset) ? obj : null); if ((Object)(object)item != (Object)null && (Object)(object)val2 == (Object)(object)asset) { flag = true; break; } } if (!flag) { PlayerAvatarVisuals playerAvatarVisuals = val.playerAvatarVisuals; if (playerAvatarVisuals != null && playerAvatarVisuals.isMenuAvatar) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance != (Object)null) { int num = instance.cosmeticAssets.IndexOf(asset); if (num >= 0 && instance.cosmeticEquipped.Contains(num)) { flag = true; } if (!flag && instance.cosmeticPreviewEnabled && instance.cosmeticEquippedPreview.Contains(num)) { flag = true; } } } } if (flag && !MiniSemibotSpawner.TryRedressMini(val)) { val.SetupCosmetics(false, true, (List)null); val.SetupColors(false, (int[])null); } } } private static void ReinjectHide(GameObject go, Cosmetic? cosmetic, CosmeticHideConfig? cfg) { BridgeHideCondition[] components = go.GetComponents(); foreach (BridgeHideCondition bridgeHideCondition in components) { Object.DestroyImmediate((Object)(object)bridgeHideCondition); } if ((Object)(object)cosmetic != (Object)null && cfg != null && cfg.HasAny) { go.AddComponent().Init(cosmetic, cfg); } } private static void ReinjectLiveBlocked(GameObject go, Cosmetic? cosmetic, DeathHeadFloorPose? pose) { BridgeLiveBlocked[] components = go.GetComponents(); foreach (BridgeLiveBlocked bridgeLiveBlocked in components) { Object.DestroyImmediate((Object)(object)bridgeLiveBlocked); } if ((Object)(object)cosmetic != (Object)null && pose != null && pose.ReactWhenAlive && BridgeIds.IsBridgeAsset(cosmetic.cosmeticAsset)) { go.AddComponent().Init(cosmetic, pose); } } internal static void RefreshLiveOffsets(CosmeticAsset asset) { CustomizerStore.TryGet(asset.assetId, out CosmeticOverrideData data); bool suppressNativeCustomTypes = data != null && NativeCustomTypeImport.HasNativeAnnounceList(asset); PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { if (!IsLocalPlayerCosmetics(val) || !(_cosmeticEquippedField?.GetValue(val) is List list)) { continue; } bool flag = false; foreach (Cosmetic item in list) { if ((Object)(object)item == (Object)null) { continue; } object? obj = _cosmeticAssetField?.GetValue(item); CosmeticAsset val2 = (CosmeticAsset)((obj is CosmeticAsset) ? obj : null); if (!((Object)(object)val2 != (Object)(object)asset)) { CosmeticOffsetCondition[] components = ((Component)item).GetComponents(); ResetTransformToDefault(((Component)item).transform, components); CosmeticOffsetCondition[] array2 = components; foreach (CosmeticOffsetCondition val3 in array2) { Object.DestroyImmediate((Object)(object)val3); } BridgeCustomTypesBroadcaster[] components2 = ((Component)item).GetComponents(); foreach (BridgeCustomTypesBroadcaster bridgeCustomTypesBroadcaster in components2) { Object.DestroyImmediate((Object)(object)bridgeCustomTypesBroadcaster); } InjectOffsetConditions(((Component)item).gameObject, asset, val, data?.Offsets, data?.CustomTypes, suppressNativeCustomTypes); ReinjectHide(((Component)item).gameObject, item, data?.HideConditions); ReinjectLiveBlocked(((Component)item).gameObject, item, data?.FloorPose); flag = true; } } if (flag) { _conditionsSetupMethod?.Invoke(val, null); } } } internal static void RefreshLiveSway(CosmeticAsset asset) { SwayMode? effectiveSway = CustomizerStore.GetEffectiveSway(asset.assetId); bool hasValue = effectiveSway.HasValue; bool flag; if (effectiveSway.HasValue) { SwayMode valueOrDefault = effectiveSway.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 2u) { flag = true; goto IL_0035; } } flag = false; goto IL_0035; IL_0035: bool flag2 = flag; float intensityFactor = CosmeticSwayHelper.SwayModeToFactor(effectiveSway); PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { if (!IsLocalPlayerCosmetics(val) || !(_cosmeticEquippedField?.GetValue(val) is List list)) { continue; } foreach (Cosmetic item in list) { if ((Object)(object)item == (Object)null) { continue; } object? obj = _cosmeticAssetField?.GetValue(item); CosmeticAsset val2 = (CosmeticAsset)((obj is CosmeticAsset) ? obj : null); if ((Object)(object)val2 != (Object)(object)asset) { continue; } CosmeticSprings[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); CosmeticSprings[] array2 = componentsInChildren; foreach (CosmeticSprings val3 in array2) { ((Behaviour)val3).enabled = !hasValue; } bool flag3 = hasValue || componentsInChildren.Length == 0; if (flag2 && flag3) { BridgeSwaySpring bridgeSwaySpring = ((Component)item).GetComponent() ?? ((Component)item).gameObject.AddComponent(); bridgeSwaySpring.Init(item, intensityFactor); continue; } BridgeSwaySpring[] components = ((Component)item).GetComponents(); foreach (BridgeSwaySpring bridgeSwaySpring2 in components) { Object.DestroyImmediate((Object)(object)bridgeSwaySpring2); } } } } internal static void RefreshRemoteCosmetics(int actorNumber) { if (_cosmeticEquippedRawField == null) { BceConsole.LogWarning("RefreshRemoteCosmetics: cosmeticEquippedRaw reflection failed — cannot refresh"); return; } int num = 0; bool flag = false; PlayerCosmetics[] array = Object.FindObjectsOfType(); foreach (PlayerCosmetics val in array) { if (IsRemoteAvatarForActor(val, actorNumber)) { num++; if (_cosmeticEquippedRawField.GetValue(val) is List { Count: not 0 } list) { flag = true; val.SetupCosmeticsLogic(list.ToArray(), true); val.SetupColorsLogic(val.colorsEquipped); } } } if (num == 0 || !flag) { ScheduleDeferredRefresh(actorNumber); } } private static bool IsRemoteAvatarForActor(PlayerCosmetics pc, int actorNumber) { if ((Object)(object)pc == (Object)null) { return false; } if ((Object)(object)pc.playerAvatarVisuals != (Object)null && pc.playerAvatarVisuals.isMenuAvatar) { return MiniSemibotSpawner.RemoteMiniActorOf(pc) == actorNumber; } PhotonView val = ((Object.op_Implicit((Object)(object)pc.deathHead) && pc.deathHead.setup && Object.op_Implicit((Object)(object)pc.deathHead.playerAvatar)) ? pc.deathHead.playerAvatar.photonView : pc.photonView); if ((Object)(object)val == (Object)null || val.IsMine) { return false; } Player owner = val.Owner; if (owner == null) { return false; } return owner.ActorNumber == actorNumber; } private static void ScheduleDeferredRefresh(int actorNumber) { if (_pendingRefresh.Add(actorNumber)) { if ((Object)(object)Plugin.Instance == (Object)null) { _pendingRefresh.Remove(actorNumber); } else { ((MonoBehaviour)Plugin.Instance).StartCoroutine(DeferredRefreshRoutine(actorNumber)); } } } private static IEnumerator DeferredRefreshRoutine(int actorNumber) { float remaining = 10f; while (remaining > 0f) { yield return (object)new WaitForSeconds(0.25f); remaining -= 0.25f; bool flag = false; bool flag2 = false; PlayerCosmetics[] array = Object.FindObjectsOfType(); foreach (PlayerCosmetics val in array) { if (IsRemoteAvatarForActor(val, actorNumber)) { flag = true; if (_cosmeticEquippedRawField?.GetValue(val) is List { Count: >0 }) { flag2 = true; break; } } } if (!flag) { break; } if (flag2) { _pendingRefresh.Remove(actorNumber); if (CustomizerSync.GetRemotePlayerData(actorNumber) != null) { RefreshRemoteCosmetics(actorNumber); } yield break; } } _pendingRefresh.Remove(actorNumber); } private static bool IsLocalPlayerCosmetics(PlayerCosmetics pc) { if (AvatarIdentity.IsRemoteMini(pc)) { return false; } PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if (playerAvatarVisuals != null && playerAvatarVisuals.isMenuAvatar) { return true; } if ((Object)(object)pc.photonView == (Object)null) { return true; } if (pc.photonView.IsMine) { return true; } if ((Object)(object)pc.deathHead != (Object)null && pc.deathHead.setup) { PlayerAvatar playerAvatar = pc.deathHead.playerAvatar; if (playerAvatar == null) { return false; } PhotonView photonView = playerAvatar.photonView; return ((photonView != null) ? new bool?(photonView.IsMine) : ((bool?)null)) == true; } return false; } internal static void PurgeActor(int actorNumber) { _pendingRefresh.Remove(actorNumber); _boneCache.Clear(); } internal static void PurgeAll() { _pendingRefresh.Clear(); _boneCache.Clear(); } private static Transform? FindByName(Transform root, string boneName) { int instanceID = ((Object)root).GetInstanceID(); if (_boneCache.TryGetValue((instanceID, boneName), out Transform value)) { return value; } Transform val = FindByNameRecursive(root, boneName); _boneCache[(instanceID, boneName)] = val; return val; } private static Transform? FindByNameRecursive(Transform root, string name) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (((Object)root).name == name) { return root; } foreach (Transform item in root) { Transform root2 = item; Transform val = FindByNameRecursive(root2, name); if ((Object)(object)val != (Object)null) { return val; } } return null; } internal static void MountWorldCosmetic(GameObject instance, Transform avatarVisuals, GameObject sourcePrefab, string? assetId) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("WorldDecorationFollower"); val.transform.SetParent(avatarVisuals, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; val.AddComponent().Configure(avatarVisuals, assetId, ((Component)avatarVisuals).GetComponent(), instance); Mount(instance, val.transform, sourcePrefab); instance.AddComponent().Node = val; } internal static void ReconcileMeshSwitchBaseMeshes(PlayerCosmetics pc) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pc == (Object)null || pc.cosmeticParents == null) { return; } MetaManager meta = MetaManager.instance; if ((Object)(object)meta == (Object)null || !AvatarIdentity.TryGetRemoteActor(pc, out var actor)) { return; } HashSet ownerWorn = new HashSet(); List equippedCosmetics = GetEquippedCosmetics(pc); if (equippedCosmetics != null) { foreach (Cosmetic item in equippedCosmetics) { if ((Object)(object)item != (Object)null) { Consider(GetCosmeticAsset(item)); } } } HashSet orCreateValue = _reconcileHidden.GetOrCreateValue(pc); foreach (CosmeticParent cosmeticParent in pc.cosmeticParents) { if (cosmeticParent?.baseMeshes == null || !IsMeshSwitchType(meta, cosmeticParent.cosmeticType)) { continue; } CosmeticType cosmeticType = cosmeticParent.cosmeticType; if (ownerWorn.Contains(cosmeticType)) { foreach (Transform baseMesh in cosmeticParent.baseMeshes) { if ((Object)(object)baseMesh != (Object)null) { ((Component)baseMesh).gameObject.SetActive(false); } } orCreateValue.Add(cosmeticType); } else { if (!orCreateValue.Remove(cosmeticType)) { continue; } foreach (Transform baseMesh2 in cosmeticParent.baseMeshes) { if ((Object)(object)baseMesh2 != (Object)null) { ((Component)baseMesh2).gameObject.SetActive(true); } } } } void Consider(CosmeticAsset? asset) { //IL_0036: 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_002d: 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_0042: 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) if (!((Object)(object)asset == (Object)null)) { CosmeticType val; if (BridgeIds.IsCustomizable(asset)) { CustomizerSync.TryGetRemote(actor, asset.assetId, out BridgeSyncPayload data); val = GetRemoteEffectiveType(asset, data).cosmeticType; } else { val = asset.type; } if (IsMeshSwitchType(meta, val)) { ownerWorn.Add(val); } } } } private static bool IsMeshSwitchType(MetaManager meta, CosmeticType type) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected I4, but got Unknown List cosmeticTypeAssets = meta.cosmeticTypeAssets; if (cosmeticTypeAssets == null) { return false; } int num = (int)type; if (num < 0 || num >= cosmeticTypeAssets.Count) { return false; } return cosmeticTypeAssets[num]?.meshSwitch ?? false; } } internal static class NativeCrownImport { internal static void MergeIntoPending(CosmeticAsset asset, ref CosmeticCrownConfig? pending) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) if (pending != null || BridgeIds.IsBridgeAsset(asset)) { return; } CosmeticType type = asset.type; if (((int)type != 0 && (int)type != 5) || 1 == 0) { return; } GameObject val = ((PrefabRef)(object)asset.prefab)?.Prefab; if (val != null) { CosmeticPlayerCrown componentInChildren = val.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren.targetMain == (Object)null)) { Matrix4x4 val2 = val.transform.worldToLocalMatrix * componentInChildren.targetMain.localToWorldMatrix; Vector3 val3 = Vector4.op_Implicit(((Matrix4x4)(ref val2)).GetColumn(3)); Quaternion rotation = ((Matrix4x4)(ref val2)).rotation; Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; Vector3 lossyScale = ((Matrix4x4)(ref val2)).lossyScale; pending = new CosmeticCrownConfig { PosX = val3.x, PosY = val3.y, PosZ = val3.z, RotX = Wrap180(eulerAngles.x), RotY = Wrap180(eulerAngles.y), RotZ = Wrap180(eulerAngles.z), ScaleX = lossyScale.x, ScaleY = lossyScale.y, ScaleZ = lossyScale.z, Priority = componentInChildren.priority, DisableSpring = componentInChildren.disableSpring }; } } } private static float Wrap180(float deg) { if (!(deg > 180f)) { return deg; } return deg - 360f; } } internal static class NativeCustomTypeImport { internal static bool HasNativeAnnounceList(CosmeticAsset asset) { if (!BridgeIds.IsBridgeAsset(asset)) { List customTypeList = asset.customTypeList; if (customTypeList != null) { return customTypeList.Count > 0; } return false; } return false; } internal static void MergeIntoPending(CosmeticAsset asset, HashSet pending) { //IL_000a: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (BridgeIds.IsBridgeAsset(asset)) { return; } HashSet hashSet = new HashSet(CosmeticTriggerCatalog.ValidCustomTypes(asset.type)); if (hashSet.Count == 0) { return; } if (asset.customTypeList != null) { foreach (Type customType in asset.customTypeList) { if (hashSet.Contains(customType)) { pending.Add(customType); } } } GameObject val = ((PrefabRef)(object)asset.prefab)?.Prefab; if (val == null) { return; } CosmeticCustomCondition[] componentsInChildren = val.GetComponentsInChildren(true); foreach (CosmeticCustomCondition val2 in componentsInChildren) { if (val2?.types == null) { continue; } foreach (Type type in val2.types) { if (hashSet.Contains(type)) { pending.Add(type); } } } } internal static void AbsorbAndStrip(GameObject instance, CosmeticAsset asset, BridgeCustomTypesBroadcaster broadcaster) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (BridgeIds.IsBridgeAsset(asset)) { return; } HashSet hashSet = new HashSet(CosmeticTriggerCatalog.ValidCustomTypes(asset.type)); CosmeticCustomCondition[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (CosmeticCustomCondition val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } if (val.types != null) { foreach (Type type in val.types) { if (!hashSet.Contains(type) && !broadcaster.Types.Contains(type)) { broadcaster.Types.Add(type); } } } Object.Destroy((Object)(object)val); } } } internal static class NativeHideImport { internal static void MergeIntoPending(CosmeticAsset asset, CosmeticHideConfig config) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) if (BridgeIds.IsBridgeAsset(asset)) { return; } GameObject val = ((PrefabRef)(object)asset.prefab)?.Prefab; if (val == null) { return; } CosmeticHideCondition[] componentsInChildren = val.GetComponentsInChildren(true); foreach (CosmeticHideCondition val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } if (val2.cosmeticTypeList != null) { foreach (CosmeticType cosmeticType in val2.cosmeticTypeList) { CosmeticHideConfig cosmeticHideConfig = config; Add(cosmeticHideConfig.WhenTypes ?? (cosmeticHideConfig.WhenTypes = new List()), cosmeticType); } } if (val2.customList != null) { foreach (Type custom in val2.customList) { CosmeticHideConfig cosmeticHideConfig = config; Add(cosmeticHideConfig.WhenConditions ?? (cosmeticHideConfig.WhenConditions = new List()), custom); } } if (val2.playerPosesList != null) { foreach (Pose playerPoses in val2.playerPosesList) { CosmeticHideConfig cosmeticHideConfig = config; Add(cosmeticHideConfig.WhenPoses ?? (cosmeticHideConfig.WhenPoses = new List()), playerPoses); } } if (val2.cosmeticList == null) { continue; } foreach (CosmeticAsset cosmetic in val2.cosmeticList) { if ((Object)(object)cosmetic != (Object)null) { CosmeticHideConfig cosmeticHideConfig = config; Add(cosmeticHideConfig.WhenCosmetics ?? (cosmeticHideConfig.WhenCosmetics = new List()), ((Object)cosmetic).name); } } } } private static void Add(List list, T value) { if (!list.Contains(value)) { list.Add(value); } } } internal static class NativeOffsetImport { private static bool IsEditable(Offset o, out Type trigger) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected I4, but got Unknown trigger = (Type)0; if (o?.customTypes == null || o.customTypes.Count != 1) { return false; } List cosmeticTypes = o.cosmeticTypes; if (cosmeticTypes == null || cosmeticTypes.Count <= 0) { List playerPoses = o.playerPoses; if (playerPoses == null || playerPoses.Count <= 0) { List cosmetics = o.cosmetics; if (cosmetics == null || cosmetics.Count <= 0) { trigger = (Type)(int)o.customTypes[0]; return !OffsetSeedDefaults.IsFitTrigger(trigger); } } } return false; } internal static void MergeIntoPending(CosmeticAsset asset, List pending) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (BridgeIds.IsBridgeAsset(asset)) { return; } GameObject val = ((PrefabRef)(object)asset.prefab)?.Prefab; if (val == null) { return; } CosmeticOffsetCondition[] components = val.GetComponents(); foreach (CosmeticOffsetCondition val2 in components) { if (val2?.offsets == null) { continue; } foreach (Offset offset in val2.offsets) { if (!IsEditable(offset, out var trigger)) { continue; } bool flag = false; foreach (CosmeticOffsetEntry item in pending) { if (item.TriggerType == trigger) { flag = true; break; } } if (!flag) { pending.Add(new CosmeticOffsetEntry { TriggerType = trigger, PosX = offset.position.x, PosY = offset.position.y, PosZ = offset.position.z, RotX = offset.rotation.x, RotY = offset.rotation.y, RotZ = offset.rotation.z, ScaleX = offset.scale.x, ScaleY = offset.scale.y, ScaleZ = offset.scale.z, LerpSpeed = offset.lerpSpeed }); } } } } internal static void AbsorbAndStrip(GameObject instance, CosmeticOffsetCondition bridgeComp) { CosmeticOffsetCondition[] components = instance.GetComponents(); foreach (CosmeticOffsetCondition val in components) { if ((Object)(object)val == (Object)(object)bridgeComp) { continue; } if (val.offsets != null) { foreach (Offset offset in val.offsets) { if (!IsEditable(offset, out var _)) { bridgeComp.offsets.Add(CloneOffset(offset)); } } } Object.Destroy((Object)(object)val); } } private static Offset CloneOffset(Offset o) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown return new Offset { setupName = o.setupName, cosmeticTypes = ((o.cosmeticTypes != null) ? new List(o.cosmeticTypes) : new List()), customTypes = ((o.customTypes != null) ? new List(o.customTypes) : new List()), playerPoses = ((o.playerPoses != null) ? new List(o.playerPoses) : new List()), cosmetics = ((o.cosmetics != null) ? new List(o.cosmetics) : new List()), position = o.position, rotation = o.rotation, scale = o.scale, lerpSpeed = o.lerpSpeed }; } } [HarmonyPatch(typeof(PlayerDeathHead), "Trigger")] internal static class PlayerDeathHeadTriggerPatch { [HarmonyPostfix] private static void Postfix(PlayerDeathHead __instance) { try { BridgeDeathHeadGameplayMount.GetOrAdd(__instance).Remount(); } catch { } } } [HarmonyPatch(typeof(PlayerDeathHead), "Reset")] internal static class PlayerDeathHeadResetPatch { [HarmonyPostfix] private static void Postfix(PlayerDeathHead __instance) { try { ((Component)__instance).GetComponent()?.ClearMounts(); } catch { } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupCosmeticsLogic")] internal static class SetupCosmeticsLogicDeathHeadPatch { [HarmonyPriority(0)] [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { try { PlayerDeathHead deathHead = __instance.deathHead; if (!((Object)(object)deathHead == (Object)null) && deathHead.triggered) { BridgeDeathHeadGameplayMount.GetOrAdd(deathHead).Remount(); MoreHeadCosmeticMountPatch.InvokeSetupColorsLogic(__instance); } } catch { } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsLogic")] internal static class SetupColorsLogicDeathHeadColorPatch { [HarmonyPriority(0)] [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { try { PlayerDeathHead deathHead = __instance.deathHead; if (!((Object)(object)deathHead == (Object)null) && deathHead.triggered) { ((Component)deathHead).GetComponent()?.RecolorMountedBridge(); } } catch { } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsAllLogic")] internal static class SetupColorsAllLogicDeathHeadColorPatch { [HarmonyPriority(0)] [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { try { PlayerDeathHead deathHead = __instance.deathHead; if (!((Object)(object)deathHead == (Object)null) && deathHead.triggered) { ((Component)deathHead).GetComponent()?.RecolorMountedBridge(); } } catch { } } } internal static class REPOLibRpcOrderPatch { private static Type? _playerCosmeticsModdedType; internal static void TryApply(Harmony harmony) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown try { _playerCosmeticsModdedType = AccessTools.TypeByName("REPOLib.Objects.PlayerCosmeticsModded"); if (_playerCosmeticsModdedType == null) { BridgeLog.Trace("REPOLibRpcOrderPatch: PlayerCosmeticsModded not found — skipped"); return; } MethodInfo methodInfo = AccessTools.Method(typeof(PlayerCosmetics), "SetupCosmetics", (Type[])null, (Type[])null); if (methodInfo == null) { BridgeLog.Trace("REPOLibRpcOrderPatch: PlayerCosmetics.SetupCosmetics not found — skipped"); return; } MethodInfo method = typeof(REPOLibRpcOrderPatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method) { priority = 600 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); BridgeLog.Trace("REPOLibRpcOrderPatch: modded-before-vanilla RPC fix applied"); } catch (Exception ex) { BridgeLog.Trace("REPOLibRpcOrderPatch: skipped — " + ex.Message); } } private static void Prefix(PlayerCosmetics __instance, bool _synced, List? _cosmetics) { if (!_synced || !SemiFunc.IsMultiplayer()) { return; } PhotonView component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsMine || _playerCosmeticsModdedType == null) { return; } CustomizerSync.BroadcastAll(); Component component2 = ((Component)__instance).GetComponent(_playerCosmeticsModdedType); MonoBehaviourPun val = (MonoBehaviourPun)(object)((component2 is MonoBehaviourPun) ? component2 : null); if ((Object)(object)val == (Object)null) { return; } PhotonView photonView = val.photonView; if ((Object)(object)photonView == (Object)null) { return; } MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } IEnumerable enumerable = _cosmetics ?? instance.cosmeticEquipped; StringBuilder stringBuilder = new StringBuilder(); bool flag = true; foreach (int item in enumerable) { if (item < 0 || item >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val2 = instance.cosmeticAssets[item]; if (val2 != null && val2.assetId != null) { if (!flag) { stringBuilder.Append('\u001f'); } stringBuilder.Append(val2.assetId); flag = false; } } PhotonNetwork.RemoveBufferedRPCs(photonView.ViewID, "SetupCosmeticsModdedRPC", (int[])null); photonView.RPC("SetupCosmeticsModdedRPC", (RpcTarget)4, new object[1] { stringBuilder.ToString() }); } } internal static class SetupCosmeticsModdedRpcPatch { private static FieldInfo? _cosmeticEquippedField; internal static void TryApply(Harmony harmony) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("REPOLib.Objects.PlayerCosmeticsModded"); if (type == null) { BridgeLog.Trace("PlayerCosmeticsModded not found — multiplayer bridge sync fix skipped"); return; } MethodInfo methodInfo = AccessTools.Method(type, "SetupCosmeticsModdedRPC", (Type[])null, (Type[])null); if (!(methodInfo == null)) { _cosmeticEquippedField = AccessTools.Field(type, "cosmeticEquipped"); if (!(_cosmeticEquippedField == null)) { MethodInfo method = typeof(SetupCosmeticsModdedRpcPatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.NonPublic); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); BridgeLog.Trace("Multiplayer bridge sync fix applied"); } } } catch (Exception ex) { BceConsole.LogWarning("Could not apply multiplayer bridge sync fix: " + ex.Message); } } private static void Postfix(MonoBehaviourPun __instance) { if ((Object)(object)__instance.photonView == (Object)null || __instance.photonView.IsMine || !(_cosmeticEquippedField?.GetValue(__instance) is List)) { return; } PlayerCosmetics component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { component.SetupCosmeticsLogic(Array.Empty(), false); Player owner = __instance.photonView.Owner; int num = ((owner != null) ? owner.ActorNumber : (-1)); Dictionary dictionary = ((num > 0) ? CustomizerSync.GetRemotePlayerData(num) : null); if (dictionary != null) { MoreHeadCosmeticMountPatch.RefreshRemoteCosmetics(num); } else { component.SetupColorsLogic(component.colorsEquipped); } } } } [HarmonyPatch(typeof(MetaManager), "Load")] internal static class UnlockPatch { private static readonly bool _resetRequestedAtStartup = Plugin.ResetBridgeUnlocks.Value; private static readonly bool _resetModdedRequestedAtStartup = Plugin.ResetModdedUnlocks.Value; private static bool _resetDone; private static readonly string _moddedTrackPath = BridgePaths.Of("AutoUnlockedModded.json"); private static HashSet _autoUnlockedModded = LoadModdedTracking(); private static HashSet LoadModdedTracking() { try { if (!File.Exists(_moddedTrackPath)) { return new HashSet(); } HashSet hashSet = JsonConvert.DeserializeObject>(File.ReadAllText(_moddedTrackPath)); return hashSet ?? new HashSet(); } catch (Exception ex) { BridgeLog.Debug("AutoUnlockModded: tracking file unreadable, starting fresh — " + ex.Message); return new HashSet(); } } private static void SaveModdedTracking() { try { File.WriteAllText(_moddedTrackPath, JsonConvert.SerializeObject((object)_autoUnlockedModded, (Formatting)1)); } catch (Exception ex) { BceConsole.LogWarning("AutoUnlockModded: could not save tracking — " + ex.Message); } } [HarmonyPostfix] private static void Postfix(MetaManager __instance) { if (_resetRequestedAtStartup && !_resetDone) { TryReset(__instance); BundleLoader.OnAllBundlesLoaded += OnBundlesLoaded; return; } if (Plugin.AutoUnlockBridgeCosmetics.Value) { TryUnlock(__instance); } else { BridgeLog.Trace("AutoUnlockBridgeCosmetics=false, skipping bridge auto-unlock"); } if (Plugin.AutoUnlockBridgeCosmetics.Value || Plugin.AutoUnlockModdedCosmetics.Value || _resetModdedRequestedAtStartup) { BundleLoader.OnAllBundlesLoaded += OnBundlesLoaded; } } private static void OnBundlesLoaded() { BundleLoader.OnAllBundlesLoaded -= OnBundlesLoaded; if ((Object)(object)MetaManager.instance == (Object)null) { BceConsole.LogWarning("MetaManager.instance is null in deferred path — skipping"); return; } if (_resetRequestedAtStartup && !_resetDone) { TryReset(MetaManager.instance); if (!_resetDone) { return; } } if (Plugin.AutoUnlockBridgeCosmetics.Value) { TryUnlock(MetaManager.instance); } if (_resetModdedRequestedAtStartup) { TryResetModded(MetaManager.instance); Plugin.ResetModdedUnlocks.Value = false; Plugin instance = Plugin.Instance; if (instance != null) { ((BaseUnityPlugin)instance).Config.Save(); } } else if (Plugin.AutoUnlockModdedCosmetics.Value) { TryUnlockModded(MetaManager.instance); } } private static void TryUnlock(MetaManager instance) { Dictionary dictionary = BuildAssetIdIndex(instance); int num = 0; foreach (string registeredAssetId in HhhCosmeticLoader.RegisteredAssetIds) { if (dictionary.TryGetValue(registeredAssetId, out var value) && !instance.cosmeticUnlocks.Contains(value)) { instance.cosmeticUnlocks.Add(value); num++; } } if (num > 0) { BceConsole.LogInfo($"Auto-unlocked {num} bridge cosmetic(s) (AutoUnlockBridgeCosmetics=true)", ConsoleColor.Magenta); } } internal static void RunAutoUnlockNow() { MetaManager instance = MetaManager.instance; if (!((Object)(object)instance == (Object)null)) { TryUnlock(instance); } } internal static void RunResetNow() { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } HashSet hashSet = new HashSet(HhhCosmeticLoader.RegisteredAssetIds); if (hashSet.Count == 0) { Plugin.ResetBridgeUnlocks.Value = false; Plugin instance2 = Plugin.Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Config.Save(); } return; } Dictionary dictionary = BuildAssetIdIndex(instance); HashSet hashSet2 = new HashSet(); foreach (string item in hashSet) { if (dictionary.TryGetValue(item, out var value)) { hashSet2.Add(value); } } bool flag = instance.cosmeticEquipped.Exists(hashSet2.Contains); int num = instance.cosmeticUnlocks.RemoveAll(hashSet2.Contains); int num2 = instance.cosmeticEquipped.RemoveAll(hashSet2.Contains); int num3 = instance.cosmeticHistory.RemoveAll(hashSet2.Contains); instance.Save(); Plugin.ResetBridgeUnlocks.Value = false; Plugin instance3 = Plugin.Instance; if (instance3 != null) { ((BaseUnityPlugin)instance3).Config.Save(); } if (Plugin.AutoUnlockBridgeCosmetics.Value) { TryUnlock(instance); } if (flag) { RuntimeConfigApplier.ReinstantiateAllLocalCosmetics(); } BceConsole.LogInfo($"ResetBridgeUnlocks (ingame): cleared {num} unlock(s), " + $"{num2} equipped, {num3} history. Flag reset to false", ConsoleColor.Magenta); } private static void TryUnlockModded(MetaManager instance) { Dictionary dictionary = BuildAssetIdIndex(instance); int num = 0; foreach (CosmeticAsset cosmeticAsset in instance.cosmeticAssets) { if (!((Object)(object)cosmeticAsset == (Object)null) && BridgeIds.IsModdedCosmetic(cosmeticAsset) && dictionary.TryGetValue(cosmeticAsset.assetId, out var value) && !instance.cosmeticUnlocks.Contains(value)) { instance.cosmeticUnlocks.Add(value); _autoUnlockedModded.Add(cosmeticAsset.assetId); num++; } } if (num > 0) { SaveModdedTracking(); instance.Save(); BceConsole.LogInfo($"Auto-unlocked {num} modded cosmetic(s) (AutoUnlockModdedCosmetics=true)", ConsoleColor.Magenta); } } private static void TryResetModded(MetaManager instance) { if (_autoUnlockedModded.Count == 0) { BridgeLog.Trace("ResetModdedUnlocks: no tracked unlocks to remove"); return; } List assetIds = new List(_autoUnlockedModded); Dictionary dictionary = BuildAssetIdIndex(instance); HashSet hashSet = new HashSet(); foreach (string item in _autoUnlockedModded) { if (dictionary.TryGetValue(item, out var value)) { hashSet.Add(value); } } bool flag = instance.cosmeticEquipped.Exists(hashSet.Contains); int num = instance.cosmeticUnlocks.RemoveAll(hashSet.Contains); int num2 = instance.cosmeticEquipped.RemoveAll(hashSet.Contains); int num3 = instance.cosmeticHistory.RemoveAll(hashSet.Contains); int num4 = PurgeFromRepoLibMissing(assetIds); _autoUnlockedModded.Clear(); SaveModdedTracking(); instance.Save(); if (flag) { RuntimeConfigApplier.ReinstantiateAllLocalCosmetics(); } BceConsole.LogInfo($"ResetModdedUnlocks: removed {num} unlock(s), " + $"{num2} equipped, {num3} history, {num4} uninstalled-mod " + "entr(ies). Tracking cleared.", ConsoleColor.Magenta); } private static int PurgeFromRepoLibMissing(ICollection assetIds) { if (assetIds.Count == 0) { return 0; } int num = 0; try { Type type = AccessTools.TypeByName("REPOLib.Patches.MetaManagerPatch"); if (type == null) { return 0; } HashSet idSet = new HashSet(assetIds, StringComparer.Ordinal); string[] array = new string[2] { "missingCosmeticUnlocks", "missingCosmeticHistory" }; foreach (string text in array) { if (AccessTools.Field(type, text)?.GetValue(null) is List list) { num += list.RemoveAll((string id) => idSet.Contains(id)); } } } catch (Exception ex) { BceConsole.LogWarning("ResetModded: could not prune REPOLib missing list — " + ex.Message); } return num; } internal static void RunAutoUnlockModdedNow() { MetaManager instance = MetaManager.instance; if (!((Object)(object)instance == (Object)null)) { TryUnlockModded(instance); } } internal static void RunResetModdedNow() { MetaManager instance = MetaManager.instance; if (!((Object)(object)instance == (Object)null)) { TryResetModded(instance); Plugin.ResetModdedUnlocks.Value = false; Plugin instance2 = Plugin.Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Config.Save(); } } } private static Dictionary BuildAssetIdIndex(MetaManager instance) { Dictionary dictionary = new Dictionary(instance.cosmeticAssets.Count, StringComparer.Ordinal); for (int i = 0; i < instance.cosmeticAssets.Count; i++) { string text = instance.cosmeticAssets[i]?.assetId; if (text != null) { dictionary[text] = i; } } return dictionary; } private static void TryReset(MetaManager instance) { HashSet hashSet = new HashSet(HhhCosmeticLoader.RegisteredAssetIds); if (hashSet.Count == 0) { return; } Dictionary dictionary = BuildAssetIdIndex(instance); HashSet hashSet2 = new HashSet(); foreach (string item in hashSet) { if (dictionary.TryGetValue(item, out var value)) { hashSet2.Add(value); } } if (hashSet2.Count == 0) { BridgeLog.Trace("ResetBridgeUnlocks: no bridge cosmetics in cosmeticAssets yet, deferring"); return; } int num = instance.cosmeticUnlocks.RemoveAll(hashSet2.Contains); int num2 = instance.cosmeticEquipped.RemoveAll(hashSet2.Contains); int num3 = instance.cosmeticHistory.RemoveAll(hashSet2.Contains); instance.Save(); Plugin.ResetBridgeUnlocks.Value = false; Plugin instance2 = Plugin.Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Config.Save(); } _resetDone = true; BceConsole.LogInfo($"ResetBridgeUnlocks: cleared {num} unlock(s), " + $"{num2} equipped, {num3} history entry. Flag reset to false", ConsoleColor.Magenta); } } internal sealed class ArrowButtonProxy : MonoBehaviour { internal BridgeSlotSelectorRow? row; internal bool right; internal RectTransform? labelRT; internal float baseY; private MenuButton? _btn; private bool _wasClicked; private void Awake() { _btn = ((Component)this).GetComponent(); } private void Update() { if (!((Object)(object)_btn != (Object)null) || !_btn.clicked) { _wasClicked = false; } else if (!_wasClicked) { _wasClicked = true; MenuManager instance = MenuManager.instance; if (instance != null) { instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); } row?.OnArrowClicked(right); } } private void LateUpdate() { HoverAdjust(); } private void HoverAdjust() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_btn == (Object)null) && !((Object)(object)labelRT == (Object)null)) { Vector2 anchoredPosition = labelRT.anchoredPosition; float num = (_btn.hovering ? 1f : baseY); if (!Mathf.Approximately(anchoredPosition.y, num)) { labelRT.anchoredPosition = new Vector2(anchoredPosition.x, num); } } } } internal sealed class BridgeAnimateButton : MonoBehaviour { internal static BridgeAnimateButton? Active; internal CosmeticAsset? cosmeticAsset; internal RectTransform? labelRT; internal MenuPageColor? menuPageColor; internal Color selectedColor = Color.white; internal bool initiallySelected; private MenuButton? _btn; private bool _wasClicked; private void Awake() { _btn = ((Component)this).GetComponent(); } private void OnEnable() { if ((Object)(object)Active == (Object)null) { Active = this; } } private void OnDestroy() { if ((Object)(object)Active == (Object)(object)this) { Active = null; } } private IEnumerator Start() { if (!initiallySelected) { yield break; } yield return (object)new WaitForSeconds(0.1f); MenuPage page = ((Component)this).GetComponentInParent(); if ((Object)(object)page != (Object)null) { while ((int)page.currentPageState != 1) { yield return (object)new WaitForSeconds(0.1f); } } SelectRingNow(); } internal void SelectRingNow() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_006b: 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) //IL_0075: 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) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)menuPageColor?.menuColorSelected == (Object)null)) { ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); RectTransform component = ((Component)this).GetComponent(); Vector3 position = ((Transform)component).position; Rect rect = component.rect; float num = ((Rect)(ref rect)).width / 2f; rect = component.rect; Vector3 val = position + new Vector3(num, ((Rect)(ref rect)).height / 2f, 0f); menuPageColor.menuColorSelected.SetColor(selectedColor, val); } } private void Update() { if (!((Object)(object)_btn != (Object)null) || !_btn.clicked) { _wasClicked = false; } else if (!_wasClicked) { _wasClicked = true; MenuManager instance = MenuManager.instance; if (instance != null) { instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); } ColorAnimationPopup.Show(cosmeticAsset); } } private void LateUpdate() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_005f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_btn == (Object)null) && !((Object)(object)labelRT == (Object)null)) { Vector2 anchoredPosition = labelRT.anchoredPosition; float num = (_btn.hovering ? 1f : 0f); if (!Mathf.Approximately(anchoredPosition.y, num)) { labelRT.anchoredPosition = new Vector2(anchoredPosition.x, num); } } } } internal sealed class BridgeColorAnimator : MonoBehaviour { private readonly struct Binding { internal readonly BridgeTintMaterial Btm; internal readonly int LocalSlot; internal readonly ColorAnimation Spec; internal Binding(BridgeTintMaterial btm, int localSlot, ColorAnimation spec) { Btm = btm; LocalSlot = localSlot; Spec = spec; } } private const float UpdateInterval = 1f / 30f; private Binding[] _bindings = Array.Empty(); private float _accum; internal bool IsEmpty => _bindings.Length == 0; internal void Init(GameObject searchRoot, AnimSet set) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) BridgeTintMaterial[] componentsInChildren = searchRoot.GetComponentsInChildren(true); List list = new List(); BridgeTintMaterial[] array = componentsInChildren; foreach (BridgeTintMaterial bridgeTintMaterial in array) { if ((Object)(object)bridgeTintMaterial == (Object)null) { continue; } Material[]? materials = bridgeTintMaterial.materials; int num = ((materials != null) ? materials.Length : 0); for (int j = 0; j < num; j++) { ColorAnimation colorAnimation = set.ForSlot(bridgeTintMaterial.SlotIdOf(j)); if (colorAnimation != null) { list.Add(new Binding(bridgeTintMaterial, j, colorAnimation)); } } } _bindings = list.ToArray(); _accum = 1f / 30f; if (_bindings.Length == 0) { return; } double t = (SemiFunc.IsMultiplayer() ? PhotonNetwork.Time : Time.timeAsDouble); Binding[] bindings = _bindings; for (int k = 0; k < bindings.Length; k++) { Binding binding = bindings[k]; if ((Object)(object)binding.Btm != (Object)null) { binding.Btm.ApplyColorRGBToSlot(binding.LocalSlot, Evaluate(binding.Spec, t)); } } } internal void Stop() { _bindings = Array.Empty(); Object.Destroy((Object)(object)this); } private void Update() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (_bindings.Length == 0) { return; } _accum += Time.deltaTime; if (_accum < 1f / 30f) { return; } _accum = 0f; double t = (SemiFunc.IsMultiplayer() ? PhotonNetwork.Time : Time.timeAsDouble); Binding[] bindings = _bindings; for (int i = 0; i < bindings.Length; i++) { Binding binding = bindings[i]; if ((Object)(object)binding.Btm != (Object)null) { binding.Btm.ApplyColorRGBToSlot(binding.LocalSlot, Evaluate(binding.Spec, t)); } } } private static Color Evaluate(ColorAnimation spec, double t) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) if (spec.Mode == ColorAnimMode.Rainbow) { double num = ((spec.SecondsPerStep <= 0f) ? 1.0 : ((double)spec.SecondsPerStep)); double num2 = t / num; float num3 = ((spec.Dir == ColorAnimDir.PingPong) ? Mathf.PingPong((float)num2, 1f) : ((float)(num2 - Math.Floor(num2)))); return Color.HSVToRGB(Mathf.Clamp01(num3), 1f, 1f); } int num4 = spec.Palette?.Count ?? 0; switch (num4) { case 0: return Color.white; case 1: return ResolvePaletteColor(spec.Palette[0]); default: { double num5 = ((spec.SecondsPerStep <= 0f) ? 1.0 : ((double)spec.SecondsPerStep)); double num6 = t / num5; int num8; int index; float num9; if (spec.Dir == ColorAnimDir.PingPong) { float num7 = Mathf.PingPong((float)num6, (float)(num4 - 1)); num8 = Mathf.Clamp(Mathf.FloorToInt(num7), 0, num4 - 2); index = num8 + 1; num9 = num7 - (float)num8; } else { long num10 = (long)Math.Floor(num6); num8 = (int)((num10 % num4 + num4) % num4); index = (num8 + 1) % num4; num9 = (float)(num6 - Math.Floor(num6)); } return Color.Lerp(ResolvePaletteColor(spec.Palette[num8]), ResolvePaletteColor(spec.Palette[index]), num9); } } } private static Color ResolvePaletteColor(int paletteIdx) { //IL_0022: 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) List list = MetaManager.instance?.colors; if (list == null || paletteIdx < 0 || paletteIdx >= list.Count) { return Color.white; } return list[paletteIdx].color; } } internal sealed class BridgeCustomColorButton : MonoBehaviour { private const float PopFadeDuration = 0.1f; internal static BridgeCustomColorButton? Active; internal MenuPageColor? menuPageColor; internal CosmeticAsset? cosmeticAsset; internal RectTransform? labelRT; internal Color selectedColor = Color.white; internal bool initiallySelected; internal bool sectionMode; internal int sectionColorKey; internal ColorPageType sectionPageMode; private MenuButton? _menuButton; private bool _buttonClicked; private bool _flashSunk; private CanvasGroup? _canvasGroup; private float _fadeT = -1f; private void Awake() { _menuButton = ((Component)this).GetComponent(); } private void OnEnable() { if ((Object)(object)Active == (Object)null) { Active = this; } } private void OnDestroy() { if ((Object)(object)Active == (Object)(object)this) { Active = null; } } private IEnumerator Start() { if (!initiallySelected) { yield break; } yield return (object)new WaitForSeconds(0.1f); MenuPage page = ((Component)this).GetComponentInParent(); if ((Object)(object)page != (Object)null) { while ((int)page.currentPageState != 1) { yield return (object)new WaitForSeconds(0.1f); } } SelectRingNow(); } internal void SetDisplayColor(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_0031: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) selectedColor = c; if (_menuButton == null) { _menuButton = ((Component)this).GetComponent(); } if (!((Object)(object)_menuButton == (Object)null)) { _menuButton.colorNormal = c + Color.black * 0.5f; _menuButton.colorHover = c; _menuButton.colorClick = c + Color.white * 0.95f; } } internal void SelectRingNow() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_006b: 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) //IL_0075: 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) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)menuPageColor?.menuColorSelected == (Object)null)) { ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); RectTransform component = ((Component)this).GetComponent(); Vector3 position = ((Transform)component).position; Rect rect = component.rect; float num = ((Rect)(ref rect)).width / 2f; rect = component.rect; Vector3 val = position + new Vector3(num, ((Rect)(ref rect)).height / 2f, 0f); menuPageColor.menuColorSelected.SetColor(selectedColor, val); } } private void Update() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_menuButton == (Object)null) { return; } bool clicked = _menuButton.clicked; if (clicked) { if (!_flashSunk && !IsCurrentlySelected()) { _flashSunk = true; SinkBelowRing(); } } else if (_flashSunk) { _flashSunk = false; ((Component)this).transform.SetAsLastSibling(); BeginPopFade(); } if (_fadeT >= 0f) { _fadeT += Time.deltaTime; float num = Mathf.Clamp01(_fadeT / 0.1f); if ((Object)(object)_canvasGroup != (Object)null) { _canvasGroup.alpha = num; } if (num >= 1f) { _fadeT = -1f; } } if (!clicked) { _buttonClicked = false; _menuButton.colorClick = (IsCurrentlySelected() ? selectedColor : (selectedColor + Color.white * 0.95f)); } else if (!_buttonClicked) { _buttonClicked = true; MenuManager instance = MenuManager.instance; if (instance != null) { instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); } if (sectionMode) { CustomColorPopup.Show(null, sectionColorKey, sectionPageMode); } else { CustomColorPopup.Show(cosmeticAsset); } } } private bool IsCurrentlySelected() { if (sectionMode || (Object)(object)cosmeticAsset == (Object)null) { return false; } return PerCosmeticColors.IsSlotCustom(cosmeticAsset.assetId, PerCosmeticColors.ActiveSlot); } private void SinkBelowRing() { MenuColorSelected val = menuPageColor?.menuColorSelected; if (!((Object)(object)val == (Object)null)) { ((Component)this).transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex()); } } private void BeginPopFade() { if (_canvasGroup == null) { _canvasGroup = ((Component)this).GetComponent() ?? ((Component)this).gameObject.AddComponent(); } _canvasGroup.alpha = 0f; _fadeT = 0f; } private void LateUpdate() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_005f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_menuButton == (Object)null) && !((Object)(object)labelRT == (Object)null)) { Vector2 anchoredPosition = labelRT.anchoredPosition; float num = (_menuButton.hovering ? 1f : 0f); if (!Mathf.Approximately(anchoredPosition.y, num)) { labelRT.anchoredPosition = new Vector2(anchoredPosition.x, num); } } } } internal sealed class BridgeOriginalColorButton : MonoBehaviour { internal const float ClickWhiteAmount = 0.95f; private const float PopFadeDuration = 0.1f; internal MenuPageColor? menuPageColor; internal CosmeticAsset? cosmeticAsset; internal Color originalColor = Color.white; internal bool initiallySelected; internal bool sectionMode; internal int sectionColorKey; internal ColorPageType sectionPageMode; private MenuButton? _menuButton; private bool _buttonClicked; private bool _flashSunk; private CanvasGroup? _canvasGroup; private float _fadeT = -1f; private void Awake() { _menuButton = ((Component)this).GetComponent(); } internal void SetDisplayColor(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_0031: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) originalColor = c; if (_menuButton == null) { _menuButton = ((Component)this).GetComponent(); } if (!((Object)(object)_menuButton == (Object)null)) { _menuButton.colorNormal = c + Color.black * 0.5f; _menuButton.colorHover = c; _menuButton.colorClick = c + Color.white * 0.95f; } } private IEnumerator Start() { if (!initiallySelected) { yield break; } yield return (object)new WaitForSeconds(0.1f); MenuPage page = ((Component)this).GetComponentInParent(); if ((Object)(object)page != (Object)null) { while ((int)page.currentPageState != 1) { yield return (object)new WaitForSeconds(0.1f); } } if (!((Object)(object)menuPageColor == (Object)null)) { ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); RectTransform component = ((Component)this).GetComponent(); Vector3 position = ((Transform)component).position; Rect rect = component.rect; float num = ((Rect)(ref rect)).width / 2f; rect = component.rect; Vector3 val = position + new Vector3(num, ((Rect)(ref rect)).height / 2f, 0f); menuPageColor.menuColorSelected.SetColor(originalColor, val); } } private void Update() { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_menuButton == (Object)null) { return; } bool clicked = _menuButton.clicked; if (clicked) { if (!_flashSunk && !IsCurrentlySelected()) { _flashSunk = true; SinkBelowRing(); } } else if (_flashSunk) { _flashSunk = false; ((Component)this).transform.SetAsLastSibling(); BeginPopFade(); } if (_fadeT >= 0f) { _fadeT += Time.deltaTime; float num = Mathf.Clamp01(_fadeT / 0.1f); if ((Object)(object)_canvasGroup != (Object)null) { _canvasGroup.alpha = num; } if (num >= 1f) { _fadeT = -1f; } } if (!clicked) { _buttonClicked = false; _menuButton.colorClick = (IsCurrentlySelected() ? originalColor : (originalColor + Color.white * 0.95f)); } else { if (_buttonClicked) { return; } _buttonClicked = true; if ((Object)(object)menuPageColor == (Object)null) { return; } MenuManager.instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); Rect rect; if (sectionMode) { ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); RectTransform component = ((Component)this).GetComponent(); Vector3 position = ((Transform)component).position; rect = component.rect; float num2 = ((Rect)(ref rect)).width / 2f; rect = component.rect; Vector3 val = position + new Vector3(num2, ((Rect)(ref rect)).height / 2f, 0f); menuPageColor.menuColorSelected.SetColor(originalColor, val); ApplyOriginalToSection(); MetaManager.instance.colorsPreviewEnabled = false; MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); } else if (!((Object)(object)cosmeticAsset == (Object)null)) { ColorAnimatorRefresher.StopAnimation(cosmeticAsset.assetId, PerCosmeticColors.ActiveSlot); ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); RectTransform component2 = ((Component)this).GetComponent(); Vector3 position2 = ((Transform)component2).position; rect = component2.rect; float num3 = ((Rect)(ref rect)).width / 2f; rect = component2.rect; Vector3 val2 = position2 + new Vector3(num3, ((Rect)(ref rect)).height / 2f, 0f); menuPageColor.menuColorSelected.SetColor(originalColor, val2); int activeSlot = PerCosmeticColors.ActiveSlot; if (activeSlot >= 0) { PerCosmeticColors.SetSlotColor(cosmeticAsset.assetId, activeSlot, -1); BridgeTintHelper.ApplySlotColorToLiveInstances(cosmeticAsset, activeSlot, -1); } else { PerCosmeticColors.SetOriginalColor(cosmeticAsset.assetId); ApplyToLiveInstances(cosmeticAsset); } BridgeSlotSelectorRow.Active?.Refresh(); MetaManager.instance.colorsPreviewEnabled = false; MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); } } } private void SinkBelowRing() { MenuColorSelected val = menuPageColor?.menuColorSelected; if (!((Object)(object)val == (Object)null)) { ((Component)this).transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex()); } } private void BeginPopFade() { if (_canvasGroup == null) { _canvasGroup = ((Component)this).GetComponent() ?? ((Component)this).gameObject.AddComponent(); } _canvasGroup.alpha = 0f; _fadeT = 0f; } private bool IsCurrentlySelected() { if (sectionMode || (Object)(object)cosmeticAsset == (Object)null) { return false; } int activeSlot = PerCosmeticColors.ActiveSlot; if (PerCosmeticColors.IsSlotAnimated(cosmeticAsset.assetId, activeSlot)) { return false; } if (PerCosmeticColors.IsSlotCustom(cosmeticAsset.assetId, activeSlot)) { return false; } if (activeSlot >= 0 && PerCosmeticColors.TryGetSlotColor(cosmeticAsset.assetId, activeSlot, out var colorIndex)) { return colorIndex == -1; } if (PerCosmeticColors.TryGetColor(cosmeticAsset.assetId, out var colorIndex2)) { return colorIndex2 == -1; } return true; } private static void ApplyToLiveInstances(CosmeticAsset asset) { BridgeTintMaterial[] array = Object.FindObjectsOfType(true); foreach (BridgeTintMaterial bridgeTintMaterial in array) { if (!((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset != (Object)(object)asset) && !MiniSemibotSpawner.IsPresetMiniComponent((Component?)(object)bridgeTintMaterial)) { bridgeTintMaterial.RestoreOriginalColor(); } } } private void ApplyOriginalToSection() { //IL_013b: Unknown result type (might be due to invalid IL or missing references) MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return; } bool flag = false; bool anyOverridesChanged = false; bool flag2 = false; bool flag3 = false; foreach (int item in instance.cosmeticEquipped) { if (item < 0 || item >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = instance.cosmeticAssets[item]; if (!MatchesSectionFilter(val)) { continue; } if (BridgeTintHelper.CanBridgeCosmeticReceivePaint(val)) { PerCosmeticColors.SetNoSave(val.assetId, -1); flag |= PerCosmeticColors.RemoveSlotsNoSave(val.assetId); flag2 |= PerCosmeticColors.RemoveCustomColorNoSave(val.assetId); flag2 |= PerCosmeticColors.RemoveCustomSlotsNoSave(val.assetId); flag3 |= PerCosmeticColors.RemoveAnimationNoSave(val.assetId); flag3 |= PerCosmeticColors.RemoveSlotAnimationsNoSave(val.assetId); ApplyToLiveInstances(val); anyOverridesChanged = true; } else if (!BridgeIds.IsBridgeAsset(val)) { if (PerCosmeticColors.RemoveColorNoSave(val.assetId)) { anyOverridesChanged = true; } if (PerCosmeticColors.RemoveCustomColorNoSave(val.assetId)) { flag2 = true; } if (PerCosmeticColors.RemoveCustomSlotsNoSave(val.assetId)) { flag2 = true; } } } if (VanillaTintHelper.RemoveSectionBaseMeshCustomsNoSave(sectionColorKey, sectionPageMode)) { flag2 = true; } bool flag4 = false; if (sectionColorKey < 0) { for (int i = 0; i < instance.colorsEquipped.Length; i++) { if (TypeIndexMatchesMode(i, instance)) { int defaultTypeColor = GetDefaultTypeColor(i, instance); if (instance.colorsEquipped[i] != defaultTypeColor) { instance.colorsEquipped[i] = defaultTypeColor; flag4 = true; } PinVanillaCosmeticDefaults(i, defaultTypeColor, instance, ref anyOverridesChanged); } } } if (anyOverridesChanged) { PerCosmeticColors.Save(); } if (flag) { PerCosmeticColors.SaveSlots(); } if (flag2) { PerCosmeticColors.SaveCustom(); PerCosmeticColors.SaveCustomSlots(); } if (flag3) { PerCosmeticColors.SaveAnimations(); PerCosmeticColors.SaveSlotAnimations(); ColorAnimatorRefresher.RefreshLocal(); } if (flag4) { instance.Save(); } if (flag2) { RuntimeConfigApplier.ReapplyLocalCosmeticColors(); } } private static void PinVanillaCosmeticDefaults(int typeIdx, int typeDefaultColor, MetaManager meta, ref bool anyOverridesChanged) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 foreach (int item in meta.cosmeticEquipped) { if (item < 0 || item >= meta.cosmeticAssets.Count) { continue; } CosmeticAsset val = meta.cosmeticAssets[item]; if ((Object)(object)val == (Object)null || BridgeIds.IsBridgeAsset(val) || (int)val.type != typeIdx) { continue; } int num = 0; if ((Object)(object)val.defaultColor != (Object)null) { int num2 = meta.colors.IndexOf(val.defaultColor); if (num2 >= 0) { num = num2; } } if (num == typeDefaultColor) { if (PerCosmeticColors.HasOverride(val.assetId)) { PerCosmeticColors.RemoveColorNoSave(val.assetId); anyOverridesChanged = true; } } else { PerCosmeticColors.SetNoSave(val.assetId, num); anyOverridesChanged = true; } } } private static int GetDefaultTypeColor(int typeIdx, MetaManager meta) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 int result = 0; foreach (int item in meta.cosmeticEquipped) { if (item < 0 || item >= meta.cosmeticAssets.Count) { continue; } CosmeticAsset val = meta.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && (int)val.type == typeIdx) { if ((Object)(object)val.defaultColor != (Object)null) { int num = meta.colors.IndexOf(val.defaultColor); result = ((num >= 0) ? num : 0); } else { result = 0; } } } return result; } private bool TypeIndexMatchesMode(int typeIdx, MetaManager meta) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 if ((int)sectionPageMode == 0) { return true; } if (meta?.cosmeticTypeAssets == null || typeIdx < 0 || typeIdx >= meta.cosmeticTypeAssets.Count) { return true; } bool meshSwitch = meta.cosmeticTypeAssets[typeIdx].meshSwitch; if ((int)sectionPageMode != 1) { return meshSwitch; } return !meshSwitch; } private bool MatchesSectionFilter(CosmeticAsset asset) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return VanillaTintHelper.CosmeticMatchesSection(asset, sectionColorKey, sectionPageMode); } internal static Color FindOriginalColor(CosmeticAsset asset, PlayerCosmetics? preferredCosmetics = null) { //IL_00ee: 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_00da: Unknown result type (might be due to invalid IL or missing references) BridgeTintMaterial[] array = (((Object)(object)preferredCosmetics?.playerAvatarVisuals != (Object)null) ? ((Component)preferredCosmetics.playerAvatarVisuals).GetComponentsInChildren(true) : Object.FindObjectsOfType(true)); BridgeTintMaterial[] array2 = array; foreach (BridgeTintMaterial bridgeTintMaterial in array2) { if (!((Object)(object)bridgeTintMaterial.cosmetic?.cosmeticAsset != (Object)(object)asset)) { Color[]? originalPrimaryColors = bridgeTintMaterial.originalPrimaryColors; if (originalPrimaryColors != null && originalPrimaryColors.Length != 0) { return bridgeTintMaterial.originalPrimaryColors[0]; } } } if ((Object)(object)preferredCosmetics?.playerAvatarVisuals != (Object)null) { BridgeTintMaterial[] array3 = Object.FindObjectsOfType(true); BridgeTintMaterial[] array4 = array3; foreach (BridgeTintMaterial bridgeTintMaterial2 in array4) { if (!((Object)(object)bridgeTintMaterial2.cosmetic?.cosmeticAsset != (Object)(object)asset)) { Color[]? originalPrimaryColors2 = bridgeTintMaterial2.originalPrimaryColors; if (originalPrimaryColors2 != null && originalPrimaryColors2.Length != 0) { return bridgeTintMaterial2.originalPrimaryColors[0]; } } } } return Color.white; } internal static Color[] BuildSlotOriginalColors(CosmeticAsset asset, int slotCount) { //IL_000d: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[slotCount]; for (int i = 0; i < slotCount; i++) { array[i] = Color.white; } BridgeTintMaterial[] array2 = Object.FindObjectsOfType(true); foreach (BridgeTintMaterial bridgeTintMaterial in array2) { if ((Object)(object)bridgeTintMaterial.cosmetic?.cosmeticAsset != (Object)(object)asset) { continue; } Color[] originalPrimaryColors = bridgeTintMaterial.originalPrimaryColors; if (originalPrimaryColors == null) { continue; } for (int k = 0; k < originalPrimaryColors.Length; k++) { int num = bridgeTintMaterial.SlotIdOf(k); if (num >= 0 && num < slotCount && originalPrimaryColors[k].a > 0f) { array[num] = originalPrimaryColors[k]; } } } return array; } } internal sealed class BridgeSlotSelectorRow : MonoBehaviour { private const int MaxVisibleSlots = 7; private const float ButtonWidth = 38f; private const float ButtonGap = 0f; private const float ArrowWidth = 20f; internal const float SlotSelectorH = 30f; private const float AllLabelFontSize = 11.5f; private const float NumberLabelFontSize = 13.5f; private const float ArrowLabelFontSize = 22f; private const float GlyphYOffset = 5f; private const float NumberOutlineWidth = 0.5f; private const float AllOutlineWidth = 0.36f; private const float ArrowOutlineWidth = 0.24f; internal static BridgeSlotSelectorRow? Active; internal int slotCount; internal float containerWidth; internal CosmeticAsset? cosmeticAsset; internal GameObject? buttonTemplate; internal MenuPageColor? menuPageColor; private readonly List<(GameObject go, MenuButton? btn)> _slotButtons = new List<(GameObject, MenuButton)>(); private GameObject? _arrowLeft; private GameObject? _arrowRight; private int _scrollOffset; private Color[]? _slotOriginals; private void OnEnable() { if ((Object)(object)Active == (Object)null) { Active = this; } } private void OnDestroy() { if ((Object)(object)Active == (Object)(object)this) { Active = null; } } private void Start() { if (!((Object)(object)buttonTemplate == (Object)null)) { BuildButtons(); Refresh(); } } private void BuildButtons() { Transform transform = ((Component)this).transform; _slotButtons.Add(MakeSlotButton(transform, "ALL", -1)); for (int i = 0; i < slotCount; i++) { _slotButtons.Add(MakeSlotButton(transform, (i + 1).ToString(), i)); } _arrowLeft = MakeArrow(transform, right: false); _arrowRight = MakeArrow(transform, right: true); } private (GameObject go, MenuButton? btn) MakeSlotButton(Transform parent, string label, int slotIdx) { GameObject val = Object.Instantiate(buttonTemplate, parent); ((Object)val).name = "SlotBtn_" + label; MenuButtonColor component = val.GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; Object.Destroy((Object)(object)component); } ResetVanillaButton(val); RectTransform labelRT = AddOverlayLabel(val, label); SlotButtonProxy slotButtonProxy = val.AddComponent(); slotButtonProxy.row = this; slotButtonProxy.slotIndex = slotIdx; slotButtonProxy.labelRT = labelRT; slotButtonProxy.baseY = 0f; return (go: val, btn: val.GetComponent()); } private GameObject MakeArrow(Transform parent, bool right) { GameObject val = Object.Instantiate(buttonTemplate, parent); ((Object)val).name = (right ? "SlotArrowRight" : "SlotArrowLeft"); MenuButtonColor component = val.GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; Object.Destroy((Object)(object)component); } ResetVanillaButton(val); RectTransform labelRT = AddOverlayLabel(val, right ? ">" : "<"); ArrowButtonProxy arrowButtonProxy = val.AddComponent(); arrowButtonProxy.row = this; arrowButtonProxy.right = right; arrowButtonProxy.labelRT = labelRT; arrowButtonProxy.baseY = 0f; return val; } private static void ResetVanillaButton(GameObject go) { MenuButton component = go.GetComponent(); if ((Object)(object)component != (Object)null) { component.customColors = false; } } private static RectTransform AddOverlayLabel(GameObject go, string text) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI componentInChildren = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return go.GetComponent(); } GameObject val = new GameObject("SlotLabel"); val.transform.SetParent(go.transform, false); TextMeshProUGUI val2 = val.AddComponent(); ((TMP_Text)val2).text = text; ((TMP_Text)val2).font = ((TMP_Text)componentInChildren).font; float fontSize; switch (text) { default: fontSize = 13.5f; break; case ">": case "<": fontSize = 22f; break; case "ALL": fontSize = 11.5f; break; } ((TMP_Text)val2).fontSize = fontSize; ((TMP_Text)val2).fontStyle = (FontStyles)1; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((Graphic)val2).color = new Color(1f, 1f, 1f, 0.85f); ((Graphic)val2).raycastTarget = false; float outlineWidth; switch (text) { default: outlineWidth = 0.5f; break; case ">": case "<": outlineWidth = 0.24f; break; case "ALL": outlineWidth = 0.36f; break; } ApplyOutline(val2, componentInChildren, outlineWidth); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = Vector2.zero; component.sizeDelta = new Vector2(38f, 30f); return component; } internal static void ApplyOutline(TextMeshProUGUI target, TextMeshProUGUI templateLabel, float outlineWidth) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)((TMP_Text)templateLabel).fontSharedMaterial == (Object)null)) { Material val = Object.Instantiate(((TMP_Text)templateLabel).fontSharedMaterial); val.SetFloat("_OutlineWidth", outlineWidth); val.SetColor("_OutlineColor", Color.black); ((TMP_Text)target).fontSharedMaterial = val; MaterialDestroyer materialDestroyer = ((Component)target).gameObject.AddComponent(); materialDestroyer.material = val; } } internal void Refresh() { int activeSlot = PerCosmeticColors.ActiveSlot; bool flag = slotCount > 7; int num = Mathf.Max(0, slotCount - 7); _scrollOffset = Mathf.Clamp(_scrollOffset, 0, num); bool active = flag && _scrollOffset > 0; bool flag2 = flag && _scrollOffset < num; float x = 0f; if ((Object)(object)_arrowLeft != (Object)null) { _arrowLeft.SetActive(active); Place(_arrowLeft, ref x, 20f); } var (val, btn) = _slotButtons[0]; val.SetActive(true); Place(val, ref x, 38f); Style(btn, activeSlot == -1, GetSlotTintColor(-1)); for (int i = 0; i < slotCount; i++) { (GameObject go, MenuButton? btn) tuple2 = _slotButtons[i + 1]; GameObject item = tuple2.go; MenuButton item2 = tuple2.btn; bool flag3 = !flag || (i >= _scrollOffset && i < _scrollOffset + 7); item.SetActive(flag3); if (flag3) { Place(item, ref x, 38f); Style(item2, activeSlot == i, GetSlotTintColor(i)); } } if ((Object)(object)_arrowRight != (Object)null) { _arrowRight.SetActive(flag2); if (flag2) { Place(_arrowRight, ref x, 20f); } } } private Color? GetSlotTintColor(int slotIndex) { //IL_00ba: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_0165: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cosmeticAsset == (Object)null || MetaManager.instance?.colors == null) { return null; } string assetId = cosmeticAsset.assetId; List colors = MetaManager.instance.colors; if (slotIndex < 0) { if (PerCosmeticColors.TryGetAnimation(assetId, out ColorAnimation spec)) { return AnimRepresentative(spec); } if (PerCosmeticColors.TryGetCustomColor(assetId, out var color)) { return color; } if (PerCosmeticColors.TryGetColor(assetId, out var colorIndex) && colorIndex != -1 && colorIndex >= 0 && colorIndex < colors.Count) { return colors[colorIndex].color; } return SlotOriginalColor(0); } if (PerCosmeticColors.TryGetSlotAnimation(assetId, slotIndex, out ColorAnimation spec2)) { return AnimRepresentative(spec2); } if (PerCosmeticColors.TryGetCustomSlotColor(assetId, slotIndex, out var color2)) { return color2; } if (PerCosmeticColors.TryGetSlotColor(assetId, slotIndex, out var colorIndex2)) { if (colorIndex2 == -1) { return SlotOriginalColor(slotIndex); } if (colorIndex2 >= 0 && colorIndex2 < colors.Count) { return colors[colorIndex2].color; } } if (PerCosmeticColors.TryGetAnimation(assetId, out ColorAnimation spec3)) { return AnimRepresentative(spec3); } if (PerCosmeticColors.TryGetCustomColor(assetId, out var color3)) { return color3; } if (PerCosmeticColors.TryGetColor(assetId, out var colorIndex3) && colorIndex3 != -1 && colorIndex3 >= 0 && colorIndex3 < colors.Count) { return colors[colorIndex3].color; } return SlotOriginalColor(slotIndex); } private static Color AnimRepresentative(ColorAnimation spec) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) if (spec.Mode == ColorAnimMode.Rainbow) { return Color.HSVToRGB(0.83f, 0.85f, 1f); } List list = MetaManager.instance?.colors; List palette = spec.Palette; if (palette != null && palette.Count > 0 && list != null) { int num = spec.Palette[0]; if (num >= 0 && num < list.Count) { return list[num].color; } } return Color.white; } private Color SlotOriginalColor(int flatSlot) { //IL_002e: 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) if (_slotOriginals == null) { _slotOriginals = BridgeOriginalColorButton.BuildSlotOriginalColors(cosmeticAsset, slotCount); } if (flatSlot < 0 || flatSlot >= _slotOriginals.Length) { return Color.white; } return _slotOriginals[flatSlot]; } private static void Place(GameObject go, ref float x, float w) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent(); if ((Object)(object)component == (Object)null) { return; } component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 0f); component.anchoredPosition = new Vector2(x, 0f); component.sizeDelta = new Vector2(w, 0f); MenuButton component2 = go.GetComponent(); if ((Object)(object)component2?.buttonText != (Object)null) { RectTransform component3 = ((Component)component2.buttonText).GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(0f, 1f); component3.pivot = new Vector2(0f, 0f); component3.anchoredPosition = new Vector2(0f, 5f); component3.sizeDelta = new Vector2(w, 0f); ((TMP_Text)component2.buttonText).alignment = (TextAlignmentOptions)514; } Vector3 localPosition = ((TMP_Text)component2.buttonText).transform.localPosition; Traverse.Create((object)component2).Field("buttonTextSelectedOriginalPos").SetValue((object)localPosition); Traverse.Create((object)component2).Field("buttonTextHoverPos").SetValue((object)(localPosition + new Vector3(0f, 1f, 0f))); } x += w + 0f; } private static void Style(MenuButton? btn, bool selected, Color? tint) { //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_00dd: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)btn == (Object)null)) { if (tint.HasValue) { Color value = tint.Value; btn.colorNormal = (Color)(selected ? value : new Color(value.r * 0.5f, value.g * 0.5f, value.b * 0.5f, value.a)); btn.colorHover = (Color)(selected ? (value + Color.white * 0.15f) : new Color(value.r * 0.65f, value.g * 0.65f, value.b * 0.65f, value.a)); btn.colorClick = Color.white; } else { btn.colorNormal = (selected ? new Color(0.92f, 0.92f, 0.92f) : new Color(0.32f, 0.32f, 0.32f)); btn.colorHover = (Color)(selected ? Color.white : new Color(0.6f, 0.6f, 0.6f)); btn.colorClick = Color.white; } } } internal void OnSlotClicked(int slotIndex) { PerCosmeticColors.ActiveSlot = slotIndex; Refresh(); UpdateOriginalButtonColor(); UpdateCustomButtonColor(); UpdateColorIndicator(); } private void UpdateCustomButtonColor() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)cosmeticAsset == (Object)null) && !((Object)(object)menuPageColor?.colorButtonHolder == (Object)null)) { BridgeCustomColorButton componentInChildren = ((Component)menuPageColor.colorButtonHolder).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && PerCosmeticColors.TryGetSlotCustom(cosmeticAsset.assetId, PerCosmeticColors.ActiveSlot, out var color)) { componentInChildren.SetDisplayColor(color); } } } private void UpdateOriginalButtonColor() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)cosmeticAsset == (Object)null) && !((Object)(object)menuPageColor?.colorButtonHolder == (Object)null)) { BridgeOriginalColorButton componentInChildren = ((Component)menuPageColor.colorButtonHolder).GetComponentInChildren(true); int activeSlot = PerCosmeticColors.ActiveSlot; componentInChildren?.SetDisplayColor(SlotOriginalColor((activeSlot >= 0) ? activeSlot : 0)); } } internal void OnArrowClicked(bool right) { _scrollOffset = (right ? Mathf.Min(_scrollOffset + 1, Mathf.Max(0, slotCount - 7)) : Mathf.Max(_scrollOffset - 1, 0)); Refresh(); } private void UpdateColorIndicator() { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)menuPageColor == (Object)null || (Object)(object)cosmeticAsset == (Object)null || MetaManager.instance?.colors == null) { return; } string assetId = cosmeticAsset.assetId; int activeSlot = PerCosmeticColors.ActiveSlot; int colorIndex; if (PerCosmeticColors.IsSlotAnimated(assetId, activeSlot)) { SelectAnimateButton(); } else if (PerCosmeticColors.IsSlotCustom(assetId, activeSlot)) { SelectCustomButton(); } else if ((activeSlot < 0 || !PerCosmeticColors.TryGetSlotColor(assetId, activeSlot, out colorIndex)) ? (!PerCosmeticColors.TryGetColor(assetId, out colorIndex) || colorIndex == -1) : (colorIndex == -1)) { SelectOriginalButton(); } else { if (colorIndex < 0 || colorIndex >= MetaManager.instance.colors.Count) { return; } RectTransform colorButtonHolder = menuPageColor.colorButtonHolder; if ((Object)(object)colorButtonHolder == (Object)null) { return; } MenuButtonColor[] componentsInChildren = ((Component)colorButtonHolder).GetComponentsInChildren(false); foreach (MenuButtonColor val in componentsInChildren) { if (val.colorID == colorIndex) { RectTransform component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null)) { Color color = MetaManager.instance.colors[colorIndex].color; Vector3 position = ((Transform)component).position; Rect rect = component.rect; float num = ((Rect)(ref rect)).width / 2f; rect = component.rect; Vector3 val2 = position + new Vector3(num, ((Rect)(ref rect)).height / 2f, 0f); ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); menuPageColor.menuColorSelected.SetColor(color, val2); } break; } } } } private void SelectOriginalButton() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)menuPageColor?.colorButtonHolder == (Object)null) && !((Object)(object)menuPageColor.menuColorSelected == (Object)null)) { BridgeOriginalColorButton componentInChildren = ((Component)menuPageColor.colorButtonHolder).GetComponentInChildren(true); RectTransform val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent() : null); if (!((Object)(object)val == (Object)null)) { Vector3 position = ((Transform)val).position; Rect rect = val.rect; float num = ((Rect)(ref rect)).width / 2f; rect = val.rect; Vector3 val2 = position + new Vector3(num, ((Rect)(ref rect)).height / 2f, 0f); ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); menuPageColor.menuColorSelected.SetColor(componentInChildren.originalColor, val2); } } } private void SelectAnimateButton() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)menuPageColor?.colorButtonHolder == (Object)null || (Object)(object)menuPageColor.menuColorSelected == (Object)null) { return; } BridgeAnimateButton componentInChildren = ((Component)menuPageColor.colorButtonHolder).GetComponentInChildren(true); RectTransform val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent() : null); if (!((Object)(object)val == (Object)null)) { Color val2 = componentInChildren.selectedColor; int activeSlot = PerCosmeticColors.ActiveSlot; ColorAnimation spec2; if (activeSlot >= 0 && PerCosmeticColors.TryGetSlotAnimation(cosmeticAsset.assetId, activeSlot, out ColorAnimation spec)) { val2 = AnimRepresentative(spec); } else if (PerCosmeticColors.TryGetAnimation(cosmeticAsset.assetId, out spec2)) { val2 = AnimRepresentative(spec2); } Vector3 position = ((Transform)val).position; Rect rect = val.rect; float num = ((Rect)(ref rect)).width / 2f; rect = val.rect; Vector3 val3 = position + new Vector3(num, ((Rect)(ref rect)).height / 2f, 0f); ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); menuPageColor.menuColorSelected.SetColor(val2, val3); } } private void SelectCustomButton() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)menuPageColor?.colorButtonHolder == (Object)null) && !((Object)(object)menuPageColor.menuColorSelected == (Object)null)) { BridgeCustomColorButton componentInChildren = ((Component)menuPageColor.colorButtonHolder).GetComponentInChildren(true); RectTransform val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent() : null); if (!((Object)(object)val == (Object)null)) { Color color; Color val2 = (PerCosmeticColors.TryGetSlotCustom(cosmeticAsset.assetId, PerCosmeticColors.ActiveSlot, out color) ? color : componentInChildren.selectedColor); Vector3 position = ((Transform)val).position; Rect rect = val.rect; float num = ((Rect)(ref rect)).width / 2f; rect = val.rect; Vector3 val3 = position + new Vector3(num, ((Rect)(ref rect)).height / 2f, 0f); ((Component)menuPageColor.menuColorSelected).gameObject.SetActive(true); menuPageColor.menuColorSelected.SetColor(val2, val3); } } } } internal static class ColorAnimationPopup { private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnTopGap = 10f; private const float BtnTopPadding = 10f; private const float RowH = 30f; private const float PopupSpacing = 5f; private const float BtnAddX = -137f; private const float BtnCancelX = -137f; private const float BtnRemoveX = -40f; private const float BtnClearX = 58f; private const float BtnClearAnimX = 0f; private const float BtnSaveX = 58f; private const float PreviewX = 110f; private const float PreviewY = -20f; private const float SwatchSize = 24f; private const float SeqStartX = -118f; private const float SeqStep = 28f; private const string ModeCycle = "Cycle Smooth"; private const string ModeRainbow = "Rainbow"; private static readonly string[] ModeOptions = new string[2] { "Cycle Smooth", "Rainbow" }; private static readonly string[] DirOptions = new string[2] { "Loop", "Ping-Pong" }; internal static void Show(CosmeticAsset? asset) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowNow(asset); }); } private static void ShowNow(CosmeticAsset? asset) { //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Expected O, but got Unknown //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Expected O, but got Unknown //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Expected O, but got Unknown //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Expected O, but got Unknown //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Expected O, but got Unknown //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Expected O, but got Unknown //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Expected O, but got Unknown if ((Object)(object)asset == (Object)null) { return; } List palette = MetaManager.instance?.colors; int colorCount = palette?.Count ?? 0; if (colorCount == 0) { return; } string assetId = asset.assetId; int slot = PerCosmeticColors.ActiveSlot; ColorAnimation spec; ColorAnimation spec2; ColorAnimation colorAnimation = ((slot < 0) ? (PerCosmeticColors.TryGetAnimation(assetId, out spec) ? spec : null) : (PerCosmeticColors.TryGetSlotAnimation(assetId, slot, out spec2) ? spec2 : null)); string uiMode = ((colorAnimation != null && colorAnimation.Mode == ColorAnimMode.Rainbow) ? "Rainbow" : "Cycle Smooth"); ColorAnimDir dir = colorAnimation?.Dir ?? ColorAnimDir.Loop; float cycleSpeed = ((colorAnimation != null && colorAnimation.Mode == ColorAnimMode.CycleSmooth) ? Mathf.Max(1f, colorAnimation.SecondsPerStep) : 1f); float rainbowSpeed = ((colorAnimation != null && colorAnimation.Mode == ColorAnimMode.Rainbow) ? Mathf.Max(3f, colorAnimation.SecondsPerStep) : 3f); List sequence = ((colorAnimation != null) ? new List(colorAnimation.Palette) : new List()); int candidate = 0; string text = ((!string.IsNullOrEmpty(asset.assetName)) ? asset.assetName : ((Object)asset).name); string text2 = ((slot >= 0) ? $" (slot {slot + 1})" : ""); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Animate Color" + text2 + "\n" + text, false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup); List builderEls = new List(); List rainbowEls = new List(); RectTransform seqRow = null; Image previewImg = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Mode", "", (Action)delegate(string opt) { uiMode = opt; ApplyVisibility(); }, scrollView, ModeOptions, uiMode, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, 15f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_004a: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Direction", "", (Action)delegate(string opt) { dir = ((opt == DirOptions[1]) ? ColorAnimDir.PingPong : ColorAnimDir.Loop); }, scrollView, DirOptions, (dir == ColorAnimDir.PingPong) ? DirOptions[1] : DirOptions[0], default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; }, 0f, 0f); REPOSlider cycleSpeedSlider = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown cycleSpeedSlider = MenuAPI.CreateREPOSlider("Speed", "seconds per step", (Action)delegate(float v) { cycleSpeed = v; }, scrollView, default(Vector2), 1f, 8f, 1, cycleSpeed, "", "s", (BarBehavior)0); return (RectTransform)((Component)cycleSpeedSlider).transform; }, 0f, 0f); builderEls.Add(((Component)cycleSpeedSlider).GetComponent()); REPOSlider rainbowSpeedSlider = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown rainbowSpeedSlider = MenuAPI.CreateREPOSlider("Speed", "seconds per hue loop", (Action)delegate(float v) { rainbowSpeed = v; }, scrollView, default(Vector2), 3f, 15f, 1, rainbowSpeed, "", "s", (BarBehavior)0); return (RectTransform)((Component)rainbowSpeedSlider).transform; }, 0f, 0f); rainbowEls.Add(((Component)rainbowSpeedSlider).GetComponent()); REPOSlider colourSlider = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) //IL_006c: 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_0082: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown colourSlider = MenuAPI.CreateREPOSlider("Color", "scrub the palette", (Action)delegate(int v) { candidate = Mathf.Clamp(v - 1, 0, colorCount - 1); UpdatePreview(); }, scrollView, default(Vector2), 1, colorCount, 1, "#", "", (BarBehavior)0); previewImg = MakeSwatch((RectTransform)((Component)colourSlider).transform, new Vector2(110f, -20f), PaletteColor(candidate)); return (RectTransform)((Component)colourSlider).transform; }, 10f, 0f); builderEls.Add(((Component)colourSlider).GetComponent()); RectTransform editRow = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) editRow = new GameObject("Edit Row", new Type[1] { typeof(RectTransform) }).GetComponent(); ((Transform)editRow).SetParent(scrollView, false); editRow.sizeDelta = new Vector2(0f, 30f); MenuAPI.CreateREPOButton("Add", (Action)delegate { sequence.Add(candidate); RebuildSeq(); }, (Transform)(object)editRow, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Remove", (Action)delegate { if (sequence.Count > 0) { sequence.RemoveAt(sequence.Count - 1); RebuildSeq(); } }, (Transform)(object)editRow, new Vector2(-40f, 0f)); MenuAPI.CreateREPOButton("Clear", (Action)delegate { sequence.Clear(); RebuildSeq(); }, (Transform)(object)editRow, new Vector2(58f, 0f)); return editRow; }, 10f, 0f); builderEls.Add(((Component)editRow).GetComponent()); REPOLabel seqLabel = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown seqLabel = MenuAPI.CreateREPOLabel("Sequence:", scrollView, default(Vector2)); return (RectTransform)((Component)seqLabel).transform; }, 10f, 0f); builderEls.Add(((Component)seqLabel).GetComponent()); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) seqRow = new GameObject("Sequence Strip", new Type[1] { typeof(RectTransform) }).GetComponent(); ((Transform)seqRow).SetParent(scrollView, false); seqRow.sizeDelta = new Vector2(0f, 30f); RebuildSeq(); return seqRow; }, 0f, 0f); builderEls.Add(((Component)seqRow).GetComponent()); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0018: 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) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject("Bottom Row 1", new Type[1] { typeof(RectTransform) }).GetComponent(); ((Transform)component).SetParent(scrollView, false); component.sizeDelta = new Vector2(0f, 30f); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)component, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Save", (Action)delegate { if (uiMode == "Cycle Smooth" && sequence.Count == 0) { if (slot >= 0) { PerCosmeticColors.ClearSlotAnimationForAsset(assetId, slot); } else { PerCosmeticColors.ClearAnimationForAsset(assetId); } } else { ColorAnimation spec3 = new ColorAnimation { Mode = ((uiMode == "Rainbow") ? ColorAnimMode.Rainbow : ColorAnimMode.CycleSmooth), Dir = dir, SecondsPerStep = ((uiMode == "Rainbow") ? rainbowSpeed : cycleSpeed), Palette = new List(sequence) }; if (slot >= 0) { PerCosmeticColors.SetSlotAnimation(assetId, slot, spec3); } else { PerCosmeticColors.SetAnimation(assetId, spec3); } BridgeAnimateButton.Active?.SelectRingNow(); } RefreshAllLive(); BridgeSlotSelectorRow.Active?.Refresh(); popup.ClosePage(false); }, (Transform)(object)component, new Vector2(58f, 0f)); return component; }, 20f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0018: 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) //IL_006f: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject("Bottom Row 2", new Type[1] { typeof(RectTransform) }).GetComponent(); ((Transform)component).SetParent(scrollView, false); component.sizeDelta = new Vector2(0f, 30f); MenuAPI.CreateREPOButton("Remove anim", (Action)delegate { if (slot >= 0) { PerCosmeticColors.ClearSlotAnimationForAsset(assetId, slot); } else { PerCosmeticColors.ClearAnimationForAsset(assetId); } RefreshAllLive(); BridgeSlotSelectorRow.Active?.Refresh(); popup.ClosePage(false); }, (Transform)(object)component, new Vector2(0f, 0f)); return component; }, 10f, 0f); ApplyVisibility(); popup.scrollView.UpdateElements(); popup.OpenPage(true); ((Component)popup).gameObject.AddComponent().Block(); void ApplyVisibility() { bool flag = uiMode == "Cycle Smooth"; foreach (REPOScrollViewElement item in builderEls) { if ((Object)(object)item != (Object)null) { item.visibility = flag; } } foreach (REPOScrollViewElement item2 in rainbowEls) { if ((Object)(object)item2 != (Object)null) { item2.visibility = !flag; } } popup.scrollView.UpdateElements(); } Color PaletteColor(int idx) { //IL_001a: 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) if (palette == null || idx < 0 || idx >= palette.Count) { return Color.white; } return palette[idx].color; } void RebuildSeq() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)seqRow == (Object)null)) { for (int num = ((Transform)seqRow).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)seqRow).GetChild(num)).gameObject); } for (int i = 0; i < sequence.Count; i++) { MakeSwatch(seqRow, new Vector2(-118f + (float)i * 28f, 0f), PaletteColor(sequence[i])); } } } static void RefreshAllLive() { PlayerCosmetics[] array = Object.FindObjectsOfType(); foreach (PlayerCosmetics pc in array) { ColorAnimatorRefresher.RefreshLiveAnimators(pc); } MiniSemibotSpawner.InvalidateLocalDeathHeads(); } void UpdatePreview() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)previewImg != (Object)null) { ((Graphic)previewImg).color = PaletteColor(candidate); } } } private static Image MakeSwatch(RectTransform parent, Vector2 pos, Color color) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_004d: 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_0064: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Swatch", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component = val.GetComponent(); ((Transform)component).SetParent((Transform)(object)parent, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); component.anchorMax = val2; component.anchorMin = val2; component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(24f, 24f); component.anchoredPosition = pos; Image component2 = val.GetComponent(); ((Graphic)component2).color = color; ((Graphic)component2).raycastTarget = false; return component2; } } internal enum ColorAnimMode { CycleSmooth, Rainbow } internal enum ColorAnimDir { Loop, PingPong } internal sealed class ColorAnimation { public List Palette = new List(); public float SecondsPerStep = 1f; public ColorAnimMode Mode; public ColorAnimDir Dir; } internal readonly struct AnimSet { internal readonly ColorAnimation? Whole; internal readonly IReadOnlyDictionary? PerSlot; internal readonly HashSet? StaticSlots; internal bool Any { get { if (Whole == null) { if (PerSlot != null) { return PerSlot.Count > 0; } return false; } return true; } } internal AnimSet(ColorAnimation? whole, IReadOnlyDictionary? perSlot, HashSet? staticSlots = null) { Whole = whole; PerSlot = perSlot; StaticSlots = staticSlots; } internal ColorAnimation? ForSlot(int flatSlot) { if (PerSlot != null && PerSlot.TryGetValue(flatSlot, out ColorAnimation value)) { return value; } if (StaticSlots != null && StaticSlots.Contains(flatSlot)) { return null; } return Whole; } } internal sealed class ColorPageInputBlocker : MonoBehaviour { private readonly List _disabled = new List(); internal void Block() { MenuPageColor val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { return; } MenuButton[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (MenuButton val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && ((Behaviour)val2).enabled) { ((Behaviour)val2).enabled = false; _disabled.Add(val2); } } } private void OnDestroy() { foreach (MenuButton item in _disabled) { if ((Object)(object)item != (Object)null) { ((Behaviour)item).enabled = true; } } } } internal static class CustomColorPopup { private const int NotSection = int.MinValue; private const float PopupX = -120f; private const float TitleGap = 15f; private const float BtnTopGap = 10f; private const float PopupSpacing = 5f; private const float BtnCancelX = -137f; private const float BtnSaveX = 58f; private const float BtnRemoveX = 0f; private const float SwatchSize = 28f; private const float SwatchX = -10f; private static readonly string[] ByteOptions = BuildByteOptions(); private static string[] BuildByteOptions() { string[] array = new string[256]; for (int i = 0; i < 256; i++) { array[i] = i.ToString(); } return array; } internal static void Show(CosmeticAsset? asset) { if (!((Object)(object)asset == (Object)null)) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowImpl(asset, int.MinValue, (ColorPageType)0); }); } } internal static void Show(CosmeticAsset? asset, int sectionColorKey, ColorPageType sectionPageMode) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)asset != (Object)null) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowImpl(asset, int.MinValue, (ColorPageType)0); }); } else { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { //IL_0008: Unknown result type (might be due to invalid IL or missing references) ShowImpl(null, sectionColorKey, sectionPageMode); }); } } private static void ShowImpl(CosmeticAsset? asset, int sectionColorKey, ColorPageType sectionPageMode) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown bool isSection = (Object)(object)asset == (Object)null; string assetId = asset?.assetId ?? ""; bool slotCapable = !isSection && (BridgeIds.IsBridgeAsset(asset) || ModdedSlotLayout.Handles(asset)); int slot = (slotCapable ? PerCosmeticColors.ActiveSlot : (-1)); Color val = Color.white; if (!isSection) { Color color2; if (slot >= 0 && PerCosmeticColors.TryGetCustomSlotColor(assetId, slot, out var color)) { val = color; } else if (PerCosmeticColors.TryGetCustomColor(assetId, out color2)) { val = color2; } } int r = Mathf.Clamp(Mathf.RoundToInt(val.r * 255f), 0, 255); int g = Mathf.Clamp(Mathf.RoundToInt(val.g * 255f), 0, 255); int b = Mathf.Clamp(Mathf.RoundToInt(val.b * 255f), 0, 255); Image swatch = null; string text = (isSection ? "Section" : ((!string.IsNullOrEmpty(asset.assetName)) ? asset.assetName : ((Object)asset).name)); string text2 = ((!isSection && slot >= 0) ? $" (slot {slot + 1})" : ""); REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Custom Color" + text2 + "\n" + text, false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup); PopupUI.AddIntSlider(popup, "Red", ByteOptions, r, delegate(float v) { r = Mathf.RoundToInt(v); ApplyLive(); }, 15f); PopupUI.AddIntSlider(popup, "Green", ByteOptions, g, delegate(float v) { g = Mathf.RoundToInt(v); ApplyLive(); }); PopupUI.AddIntSlider(popup, "Blue", ByteOptions, b, delegate(float v) { b = Mathf.RoundToInt(v); ApplyLive(); }); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) GameObject val2 = new GameObject("CustomColorPreview", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(scrollView, false); Image val3 = val2.AddComponent(); ((Graphic)val3).color = Current(); swatch = val3; RectTransform val4 = (RectTransform)val2.transform; val4.sizeDelta = new Vector2(28f, 28f); val4.anchoredPosition = new Vector2(-10f, 0f); return val4; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: 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) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Cancel", (Action)delegate { popup.ClosePage(false); RuntimeConfigApplier.ReapplyLocalCosmeticColors(); }, (Transform)(object)val2, new Vector2(-137f, 0f)); MenuAPI.CreateREPOButton("Save", (Action)delegate { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (isSection) { VanillaTintHelper.SaveCustomColorToSection(sectionColorKey, sectionPageMode, Current()); } else if (slot >= 0) { PerCosmeticColors.SetCustomSlotColor(assetId, slot, Current()); RuntimeConfigApplier.ReapplyLocalCosmeticColors(); } else { PerCosmeticColors.SetCustomColor(assetId, Current()); RuntimeConfigApplier.ReapplyLocalCosmeticColors(); } BridgeCustomColorButton.Active?.SetDisplayColor(Current()); BridgeCustomColorButton.Active?.SelectRingNow(); BridgeSlotSelectorRow.Active?.Refresh(); popup.ClosePage(false); if (!isSection && SemiFunc.IsMultiplayer()) { PerCosmeticColorNetworkSync.BroadcastAll(); } }, (Transform)(object)val2, new Vector2(58f, 0f)); return val2; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val2 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Remove custom", (Action)delegate { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (isSection) { VanillaTintHelper.RemoveCustomColorFromSection(sectionColorKey, sectionPageMode); } else if (slot >= 0) { if (PerCosmeticColors.RemoveCustomSlotNoSave(assetId, slot)) { PerCosmeticColors.SaveCustomSlots(); } RuntimeConfigApplier.ReapplyLocalCosmeticColors(); } else { if (PerCosmeticColors.RemoveCustomColorNoSave(assetId)) { PerCosmeticColors.SaveCustom(); } RuntimeConfigApplier.ReapplyLocalCosmeticColors(); if (SemiFunc.IsMultiplayer()) { PerCosmeticColorNetworkSync.BroadcastAll(); } } popup.ClosePage(false); BridgeSlotSelectorRow.Active?.Refresh(); }, (Transform)(object)val2, new Vector2(0f, 0f)); return val2; }, 10f, 0f); popup.OpenPage(true); void ApplyLive() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) if ((Object)(object)swatch != (Object)null) { ((Graphic)swatch).color = Current(); } if (isSection) { VanillaTintHelper.ApplyCustomRGBToSectionLive(sectionColorKey, sectionPageMode, Current()); } else if (slotCapable) { if (slot >= 0) { BridgeTintHelper.ApplySlotRGBToLiveInstances(asset, slot, Current()); } else { BridgeTintHelper.ApplyWholeAssetRGBToLiveInstances(asset, Current()); } } else { VanillaTintHelper.ApplyCustomRGBToLiveInstances(asset, Current()); } } Color Current() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) return new Color((float)r / 255f, (float)g / 255f, (float)b / 255f); } } } internal static class CustomGrabColorCompat { private static readonly int GrabberSlot = 9; private const BindingFlags PubStatic = BindingFlags.Static | BindingFlags.Public; private const BindingFlags PubInst = BindingFlags.Instance | BindingFlags.Public; private static FieldInfo? _playerField; private static MethodInfo? _trySendAll; private static MethodInfo? _updateAllBeams; internal static void TryApply(Harmony harmony) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown if (!MiniSemibotModCompat.HasCustomGrabColor) { return; } try { Assembly assembly = FindAssembly("CustomGrabColour"); if (assembly == null) { return; } Type type = assembly.GetType("CustomGrabColour.PlayerGrabBeam.CustomGrabBeamColour"); if (type == null) { return; } _playerField = type.GetField("player", BindingFlags.Instance | BindingFlags.Public); if (!(_playerField == null)) { _trySendAll = assembly.GetType("CustomGrabColour.PlayerGrabBeam.GrabBeamUtil")?.GetMethod("TrySendBeamColourUpdateForAllBeams", BindingFlags.Static | BindingFlags.Public); _updateAllBeams = type.GetMethod("UpdateBeamColourForAllBeams", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null); MethodInfo method = type.GetMethod("GetGrabberCosmeticColour", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(Color) }, null); if (method != null) { HarmonyMethod val = new HarmonyMethod(typeof(CustomGrabColorCompat).GetMethod("GrabberColourPostfix", BindingFlags.Static | BindingFlags.NonPublic)); harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); BceConsole.LogInfo("CustomGrabColor compat: grabber colour bridge active (GetGrabberCosmeticColour).", ConsoleColor.Cyan); } MethodInfo method2 = type.GetMethod("GetAvatarColour", BindingFlags.Instance | BindingFlags.Public); if (method2 != null) { HarmonyMethod val2 = new HarmonyMethod(typeof(CustomGrabColorCompat).GetMethod("GetAvatarColourPostfix", BindingFlags.Static | BindingFlags.NonPublic)); harmony.Patch((MethodBase)method2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); BceConsole.LogInfo("CustomGrabColor compat: grabber colour bridge active (GetAvatarColour).", ConsoleColor.Cyan); } if (method == null && method2 == null) { BceConsole.LogWarning("CustomGrabColor compat: no known grabber-colour method found — version unsupported."); } } } catch (Exception ex) { BceConsole.LogWarning("CustomGrabColor compat patch failed (harmless): " + ex.Message); } } private static void GrabberColourPostfix(object __instance, ref Color __result) { TrySubstituteLocalCustom(__instance, ref __result); } private static void GetAvatarColourPostfix(object __instance, object __0, ref Color __result) { try { if (Convert.ToInt32(__0) != GrabberSlot) { return; } } catch { return; } TrySubstituteLocalCustom(__instance, ref __result); } private static void TrySubstituteLocalCustom(object beamInstance, ref Color result) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) try { if (Plugin.EnableVanillaCustomColors.Value) { object? obj = _playerField?.GetValue(beamInstance); PlayerAvatar val = (PlayerAvatar)((obj is PlayerAvatar) ? obj : null); if (val != null && val.isLocal && PerCosmeticColors.TryGetCustomColor(VanillaTintHelper.BaseMeshAssetId(GrabberSlot), out var color)) { result = new Color(color.r, color.g, color.b, result.a); } } } catch { } } internal static void RefreshLocalBeam() { try { if (_trySendAll != null && (Object)(object)PlayerAvatar.instance != (Object)null) { _trySendAll.Invoke(null, new object[1] { PlayerAvatar.instance }); } else { _updateAllBeams?.Invoke(null, null); } } catch { } } private static Assembly? FindAssembly(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (string.Equals(assembly.GetName().Name, name, StringComparison.OrdinalIgnoreCase)) { return assembly; } } return null; } } internal sealed class MaterialDestroyer : MonoBehaviour { internal Material? material; private void OnDestroy() { if ((Object)(object)material != (Object)null) { Object.Destroy((Object)(object)material); } } } [HarmonyPatch(typeof(MenuPageColor), "Update")] internal static class ColorPageDragRotatePatch { private const float DragThresholdPixels = 2f; private const float RotateDegreesPerPixel = 10f; private static bool _grabActive; private static float _grabOriginX; [HarmonyPostfix] private static void Postfix() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) CosmeticAsset pendingAsset = PerCosmeticColors.PendingAsset; if ((Object)(object)pendingAsset == (Object)null || !BridgeIds.IsBridgeAsset(pendingAsset) || (Object)(object)PlayerAvatarMenu.instance == (Object)null) { return; } if ((Object)(object)EventSystem.current != (Object)null && EventSystem.current.IsPointerOverGameObject()) { _grabActive = false; } else if (SemiFunc.InputHold((InputKey)10)) { float x = Input.mousePosition.x; if (!_grabActive) { _grabActive = true; _grabOriginX = x; } float num = x - _grabOriginX; if (Mathf.Abs(num) > 2f) { PlayerAvatarMenu.instance.Rotate(new Vector3(0f, (0f - num) * 10f, 0f)); } } else { _grabActive = false; } } } [HarmonyPatch(typeof(MenuElementCosmeticButton), "ChangeColorButton")] internal static class PerCosmeticColorButtonPatch { [HarmonyPrefix] private static void Prefix(MenuElementCosmeticButton __instance) { if (PerCosmeticColors.FeatureEnabled) { PerCosmeticColors.PendingAsset = __instance.cosmeticAsset; if ((Object)(object)__instance.cosmeticAsset != (Object)null) { PerCosmeticColors.TemporarilyShowForColorPage(__instance.cosmeticAsset); } } } [HarmonyPostfix] private static void Postfix(MenuElementCosmeticButton __instance) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (MetaManager.instance?.colorsEquipped == null) { return; } MenuPageColor val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { return; } int num = MetaManager.instance.colorsEquipped.Length; if (val.colorKey < 0 || val.colorKey >= num) { int num2 = (((Object)(object)__instance.cosmeticAsset != (Object)null) ? ((int)__instance.cosmeticAsset.type) : 0); if (num2 < 0 || num2 >= num) { num2 = 0; } val.colorKey = num2; } } } [HarmonyPatch(typeof(MenuElementCosmeticSection), "ChangeColorButton")] internal static class SectionColorButtonPatch { internal static bool PendingWorldSection; [HarmonyPrefix] private static void Prefix(MenuElementCosmeticSection __instance) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (PerCosmeticColors.FeatureEnabled) { PerCosmeticColors.PendingAsset = null; PendingWorldSection = (int)__instance.subCategory == 2147483646; } } [HarmonyPostfix] private static void Postfix() { if (!PendingWorldSection || MetaManager.instance?.colorsEquipped == null) { return; } MenuPageColor val = Object.FindObjectOfType(); if (!((Object)(object)val == (Object)null)) { int num = MetaManager.instance.colorsEquipped.Length; if (val.colorKey < 0 || val.colorKey >= num) { val.colorKey = 0; } } } } [HarmonyPatch(typeof(MenuPageCosmetics), "ChangeAllColorButton")] internal static class ChangeAllColorButtonPatch { [HarmonyPrefix] private static void Prefix() { PerCosmeticColors.PendingAsset = null; SectionColorButtonPatch.PendingWorldSection = false; } } [HarmonyPatch(typeof(MenuPageCosmetics), "ChangeBodyColorButton")] internal static class ChangeBodyColorButtonPatch { [HarmonyPrefix] private static void Prefix() { PerCosmeticColors.PendingAsset = null; SectionColorButtonPatch.PendingWorldSection = false; } } [HarmonyPatch(typeof(MenuPageCosmetics), "ChangeCosmeticsColorButton")] internal static class ChangeCosmeticsColorButtonPatch { [HarmonyPrefix] private static void Prefix() { PerCosmeticColors.PendingAsset = null; SectionColorButtonPatch.PendingWorldSection = false; } } [HarmonyPatch(typeof(MenuPageCosmetics), "Start")] internal static class CosmeticsMenuOpenGatePatch { [HarmonyPostfix] private static void Postfix() { PerCosmeticColorNetworkSync.OpenGate(); } } [HarmonyPatch(typeof(MenuPageColor), "OnDestroy")] internal static class ColorPageClosePatch { [HarmonyPrefix] private static void Prefix() { PerCosmeticColors.RestoreTypeColor(); PerCosmeticColors.ActiveSlot = -1; SectionColorButtonPatch.PendingWorldSection = false; } [HarmonyPostfix] private static void Postfix() { PerCosmeticColors.PendingAsset = null; } } [HarmonyPatch(typeof(MenuPageCosmetics), "OnDestroy")] internal static class CosmeticsMenuCloseFlushPatch { [HarmonyPostfix] private static void Postfix() { if (PerCosmeticColorNetworkSync.CloseGate() && SemiFunc.IsMultiplayer()) { BridgeNetMux.BroadcastSnapshot(); } } } [HarmonyPatch(typeof(MetaManager), "CosmeticColorSet")] internal static class CosmeticColorSetPatch { [HarmonyPostfix] private static void Postfix(int _index, int _colorID) { //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Invalid comparison between Unknown and I4 //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Invalid comparison between Unknown and I4 //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Invalid comparison between Unknown and I4 if (!PerCosmeticColors.FeatureEnabled || (Object)(object)PerCosmeticColors.PendingAsset != (Object)null) { return; } MenuPageColor val = Object.FindObjectOfType(true); if ((Object)(object)val == (Object)null) { return; } MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return; } bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; if (SectionColorButtonPatch.PendingWorldSection) { foreach (int item in instance.cosmeticEquipped) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val2 = instance.cosmeticAssets[item]; if (BridgeTintHelper.CanBridgeCosmeticReceivePaint(val2) && HhhCosmeticLoader.IsWorldAsset(val2)) { PerCosmeticColors.SetNoSave(val2.assetId, _colorID); flag2 |= PerCosmeticColors.RemoveSlotsNoSave(val2.assetId); flag3 |= PerCosmeticColors.RemoveCustomColorNoSave(val2.assetId); flag3 |= PerCosmeticColors.RemoveCustomSlotsNoSave(val2.assetId); flag4 |= PerCosmeticColors.RemoveAnimationNoSave(val2.assetId); flag4 |= PerCosmeticColors.RemoveSlotAnimationsNoSave(val2.assetId); flag = true; } } } if (flag) { PerCosmeticColors.Save(); if (flag2) { PerCosmeticColors.SaveSlots(); } if (flag3) { PerCosmeticColors.SaveCustom(); PerCosmeticColors.SaveCustomSlots(); } if (flag4) { PerCosmeticColors.SaveAnimations(); PerCosmeticColors.SaveSlotAnimations(); ColorAnimatorRefresher.RefreshLocal(); } } return; } bool flag5 = OriginalColorButtonPatch.HasEligibleBridgeForSection(val); bool flag6 = val.colorKey < 0; bool flag7 = (int)val.pageMode == 2; if (flag5) { foreach (int item2 in instance.cosmeticEquipped) { if (item2 >= 0 && item2 < instance.cosmeticAssets.Count) { CosmeticAsset val3 = instance.cosmeticAssets[item2]; if (BridgeTintHelper.CanBridgeCosmeticReceivePaint(val3) && (!HhhCosmeticLoader.IsWorldAsset(val3) || !(!flag6 || flag7)) && (int)val3.type == _index) { PerCosmeticColors.SetNoSave(val3.assetId, _colorID); flag2 |= PerCosmeticColors.RemoveSlotsNoSave(val3.assetId); flag3 |= PerCosmeticColors.RemoveCustomColorNoSave(val3.assetId); flag3 |= PerCosmeticColors.RemoveCustomSlotsNoSave(val3.assetId); flag4 |= PerCosmeticColors.RemoveAnimationNoSave(val3.assetId); flag4 |= PerCosmeticColors.RemoveSlotAnimationsNoSave(val3.assetId); flag = true; } } } } foreach (int item3 in instance.cosmeticEquipped) { if (item3 < 0 || item3 >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val4 = instance.cosmeticAssets[item3]; if (!((Object)(object)val4 == (Object)null) && !BridgeIds.IsBridgeAsset(val4) && (int)val4.type == _index) { bool flag8 = PerCosmeticColors.RemoveColorNoSave(val4.assetId); bool flag9 = PerCosmeticColors.RemoveCustomColorNoSave(val4.assetId); bool flag10 = PerCosmeticColors.RemoveCustomSlotsNoSave(val4.assetId); if (flag8 || flag9 || flag10) { flag = true; flag3 = flag3 || flag9 || flag10; } } } if (Plugin.EnableVanillaCustomColors.Value) { string assetId = VanillaTintHelper.BaseMeshAssetId(_index); if (PerCosmeticColors.RemoveCustomColorNoSave(assetId)) { flag = true; flag3 = true; } } if (flag) { PerCosmeticColors.Save(); if (flag2) { PerCosmeticColors.SaveSlots(); } if (flag3) { PerCosmeticColors.SaveCustom(); PerCosmeticColors.SaveCustomSlots(); } if (flag4) { PerCosmeticColors.SaveAnimations(); PerCosmeticColors.SaveSlotAnimations(); ColorAnimatorRefresher.RefreshLocal(); } } } [HarmonyPrefix] private static bool Prefix(int _index, int _colorID) { //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled) { return true; } if (SectionColorButtonPatch.PendingWorldSection) { return false; } if ((Object)(object)PerCosmeticColors.PendingAsset == (Object)null) { return true; } CosmeticAsset pendingAsset = PerCosmeticColors.PendingAsset; bool flag = BridgeIds.IsBridgeAsset(pendingAsset) || ModdedSlotLayout.Handles(pendingAsset); ColorAnimatorRefresher.StopAnimation(pendingAsset.assetId, PerCosmeticColors.ActiveSlot); if (PerCosmeticColors.ActiveSlot >= 0 && flag) { PerCosmeticColors.SetSlotColor(pendingAsset.assetId, PerCosmeticColors.ActiveSlot, _colorID); BridgeTintHelper.ApplySlotColorToLiveInstances(pendingAsset, PerCosmeticColors.ActiveSlot, _colorID); if (BridgeIds.IsBridgeAsset(pendingAsset) && !HhhCosmeticLoader.IsWorldAsset(pendingAsset) && (Object)(object)MetaManager.instance != (Object)null && _index >= 0 && _index < MetaManager.instance.colorsEquipped.Length) { MetaManager.instance.colorsEquipped[_index] = _colorID; } ColorAnimatorRefresher.RefreshLocal(); BridgeSlotSelectorRow.Active?.Refresh(); return false; } if (flag) { PerCosmeticColors.ClearSlotsForAsset(pendingAsset.assetId); } if (!HhhCosmeticLoader.IsWorldAsset(pendingAsset) && (Object)(object)MetaManager.instance != (Object)null && _index >= 0 && _index < MetaManager.instance.colorsEquipped.Length) { int realTypeColor = PerCosmeticColors.GetRealTypeColor(_index, MetaManager.instance.colorsEquipped); if (realTypeColor >= 0) { foreach (int item in MetaManager.instance.cosmeticEquipped) { if (item >= 0 && item < MetaManager.instance.cosmeticAssets.Count) { CosmeticAsset val = MetaManager.instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && val.type == pendingAsset.type && !(val.assetId == pendingAsset.assetId) && !BridgeIds.IsBridgeAsset(val) && !PerCosmeticColors.HasOverride(val.assetId)) { PerCosmeticColors.SetNoSave(val.assetId, realTypeColor); } } } } } PerCosmeticColors.Set(pendingAsset.assetId, _colorID); if (flag) { BridgeTintHelper.ApplyWholeAssetColorToLiveInstances(pendingAsset, _colorID); } if (!HhhCosmeticLoader.IsWorldAsset(pendingAsset) && (Object)(object)MetaManager.instance != (Object)null && _index >= 0 && _index < MetaManager.instance.colorsEquipped.Length) { MetaManager.instance.colorsEquipped[_index] = _colorID; } BridgeSlotSelectorRow.Active?.Refresh(); return false; } } [HarmonyPatch(typeof(MenuElementCosmeticSection), "UpdateColorButton")] internal static class SectionColorButtonBridgePatch { [HarmonyPostfix] private static void Postfix(MenuElementCosmeticSection __instance) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled || !__instance.colorButton.disabled) { return; } MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return; } bool flag = (int)__instance.subCategory == 2147483646; foreach (int item in instance.cosmeticEquipped) { if (item < 0 || item >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = instance.cosmeticAssets[item]; if (!BridgeTintHelper.CanBridgeCosmeticReceivePaint(val)) { continue; } bool flag2 = HhhCosmeticLoader.IsWorldAsset(val); if (flag) { if (!flag2) { continue; } } else if (flag2 || val.type != __instance.subCategory) { continue; } __instance.colorButton.disabled = false; ((Graphic)__instance.colorButtonIcon).color = Color.white; if (__instance.menuPageCosmetics.selectedSubCategory == __instance.subCategory) { __instance.menuPageCosmetics.stickyHeader.colorButton.disabled = false; ((Graphic)__instance.menuPageCosmetics.stickyHeader.colorButtonIcon).color = Color.white; } break; } } } [HarmonyPatch(typeof(MenuPlayerHead), "SetColor")] internal static class LobbyHeadCustomColorPatch { private static readonly LazyFieldRef _topRef = new LazyFieldRef("playerColorTop", "lobby-head custom colors"); private static readonly LazyFieldRef _botRef = new LazyFieldRef("playerColorBottom", "lobby-head custom colors"); internal static void RefreshAllHeads() { if (!PerCosmeticColors.FeatureEnabled) { return; } MenuPlayerHead[] array = Object.FindObjectsOfType(); foreach (MenuPlayerHead val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.playerAvatar == (Object)null) && !((Object)(object)val.playerAvatar.playerAvatarVisuals == (Object)null)) { val.SetColor(); } } } [HarmonyPostfix] private static void Postfix(MenuPlayerHead __instance) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled) { return; } PlayerCosmetics val = __instance.playerAvatar?.playerCosmetics; if ((Object)(object)val == (Object)null || !_topRef.TryResolve() || !_botRef.TryResolve()) { return; } Color color; bool flag = TryResolveHeadCustom(val, 5, out color); Color color2; bool flag2 = TryResolveHeadCustom(val, 6, out color2); if (!flag && !flag2) { return; } if (flag) { _topRef.TrySet(__instance, color); } if (flag2) { _botRef.TrySet(__instance, color2); } RawImage[] componentsInChildren = ((Component)__instance).GetComponentsInChildren(true); foreach (RawImage val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } switch (((Object)val2).name) { case "Jaw Sprite": if (flag2) { ((Graphic)val2).color = color2; } break; default: if (flag) { ((Graphic)val2).color = color; } break; case "Arena Crown": case "Steam Icon": break; } } } private static bool TryResolveHeadCustom(PlayerCosmetics pc, int typeIndex, out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Invalid comparison between Unknown and I4 color = default(Color); bool isLocal = (Object)(object)pc.photonView == (Object)null || pc.photonView.IsMine || (Object)(object)pc.playerAvatarVisuals == (Object)null || pc.playerAvatarVisuals.isMenuAvatar; PerCosmeticColorSyncComponent sync = (isLocal ? null : ((Component)pc).GetComponent()); PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals != (Object)null) { Cosmetic[] componentsInChildren = ((Component)playerAvatarVisuals).GetComponentsInChildren(true); foreach (Cosmetic val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && (int)val.type == typeIndex) { string text = val.cosmeticAsset?.assetId; if (text != null && Lookup(text, out color)) { return true; } } } } return Lookup(VanillaTintHelper.BaseMeshAssetId(typeIndex), out color); bool Lookup(string assetId, out Color c) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (isLocal) { return PerCosmeticColors.TryGetCustomColor(assetId, out c); } c = default(Color); if ((Object)(object)sync != (Object)null) { return sync.TryGetRemoteCustomColor(assetId, out c); } return false; } } } [HarmonyPatch(typeof(MenuPageColor), "Start")] internal static class OriginalColorButtonPatch { internal sealed class ButtonTooltip : MonoBehaviour { internal GameObject? tooltip; private MenuButton? _btn; private void Awake() { _btn = ((Component)this).GetComponent(); } private void LateUpdate() { if (!((Object)(object)_btn == (Object)null) && !((Object)(object)tooltip == (Object)null) && tooltip.activeSelf != _btn.hovering) { tooltip.SetActive(_btn.hovering); } } } internal sealed class OriginalLabelHoverAdjuster : MonoBehaviour { internal RectTransform? labelRT; private MenuButton? _btn; private void Awake() { _btn = ((Component)this).GetComponent(); } private void LateUpdate() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_005f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_btn == (Object)null) && !((Object)(object)labelRT == (Object)null)) { Vector2 anchoredPosition = labelRT.anchoredPosition; float num = (_btn.hovering ? 1f : 0f); if (!Mathf.Approximately(anchoredPosition.y, num)) { labelRT.anchoredPosition = new Vector2(anchoredPosition.x, num); } } } } private const string SlotSelectorName = "BridgeSlotSelector"; [HarmonyPostfix] private static void Postfix(MenuPageColor __instance) { //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_056f: Unknown result type (might be due to invalid IL or missing references) //IL_06cc: Unknown result type (might be due to invalid IL or missing references) //IL_070f: Unknown result type (might be due to invalid IL or missing references) //IL_0711: Unknown result type (might be due to invalid IL or missing references) //IL_0732: Unknown result type (might be due to invalid IL or missing references) //IL_0737: Unknown result type (might be due to invalid IL or missing references) //IL_062b: Unknown result type (might be due to invalid IL or missing references) //IL_0676: Unknown result type (might be due to invalid IL or missing references) //IL_0678: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Unknown result type (might be due to invalid IL or missing references) //IL_0585: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05d2: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_0411: Expected O, but got Unknown //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_074e: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled) { return; } CosmeticAsset pendingAsset = PerCosmeticColors.PendingAsset; MenuPage componentInParent = ((Component)__instance).GetComponentInParent(); object obj; if (componentInParent == null) { obj = null; } else { MenuPage pageUnderThisPage = componentInParent.pageUnderThisPage; obj = ((pageUnderThisPage == null) ? null : ((Component)pageUnderThisPage).GetComponent()?.menuPage?.playerAvatarMenu?.playerCosmetics); } PlayerCosmetics preferredCosmetics = (PlayerCosmetics)obj; bool flag = (Object)(object)pendingAsset != (Object)null && BridgeIds.IsBridgeAsset(pendingAsset) && pendingAsset.tintable; bool flag2 = (Object)(object)pendingAsset != (Object)null && !BridgeIds.IsBridgeAsset(pendingAsset) && ModdedSlotLayout.Handles(pendingAsset) && CountMaterialSlotsForAsset(pendingAsset, preferredCosmetics) > 1; bool flag3 = flag || flag2; bool flag4 = (Object)(object)pendingAsset != (Object)null && !BridgeIds.IsBridgeAsset(pendingAsset) && !flag2 && VanillaTintHelper.IsEligibleForCustomColor(pendingAsset); bool flag5 = flag3 || flag4; bool flag6 = !flag5 && (Object)(object)pendingAsset == (Object)null && HasEligibleBridgeForSection(__instance); bool flag7 = !flag5 && (Object)(object)pendingAsset == (Object)null && VanillaTintHelper.HasAnyTintableForSection(__instance); if (!flag5 && !flag6 && !flag7) { return; } if (flag4 && !flag3) { InjectNonBridgeCButton(__instance, pendingAsset); return; } if (!flag5 && !flag6 && flag7) { int resolvedSectionKey = (SectionColorButtonPatch.PendingWorldSection ? 2147483646 : __instance.colorKey); InjectSectionCButton(__instance, resolvedSectionKey); return; } RectTransform colorButtonHolder = __instance.colorButtonHolder; if ((Object)(object)colorButtonHolder == (Object)null || ((Transform)colorButtonHolder).childCount == 0) { return; } GameObject val = null; for (int i = 0; i < ((Transform)colorButtonHolder).childCount; i++) { Transform child = ((Transform)colorButtonHolder).GetChild(i); if (((Object)child).name != "BridgeSlotSelector") { val = ((Component)child).gameObject; break; } } if ((Object)(object)val == (Object)null) { return; } List list = new List(); for (int j = 0; j < ((Transform)colorButtonHolder).childCount; j++) { Transform child2 = ((Transform)colorButtonHolder).GetChild(j); if (!(((Object)child2).name == "BridgeSlotSelector")) { RectTransform component = ((Component)child2).GetComponent(); if ((Object)(object)component != (Object)null) { list.Add(component); } } } Rect rect = colorButtonHolder.rect; float rowW = ((Rect)(ref rect)).width; Vector2 anchoredPosition = list[0].anchoredPosition; float num = anchoredPosition.x + 38f; float num2 = anchoredPosition.y; if (num > rowW) { num = 0f; num2 -= 30f; } TextMeshProUGUI componentInChildren = val.GetComponentInChildren(true); bool flag8 = flag5 && PerCosmeticColors.HasAnimation(pendingAsset.assetId); bool flag9 = flag5 && PerCosmeticColors.HasCustomColor(pendingAsset.assetId); int sectionColorKey = (SectionColorButtonPatch.PendingWorldSection ? 2147483646 : __instance.colorKey); if (!flag2) { GameObject val2 = Object.Instantiate(val, (Transform)(object)colorButtonHolder); ((Object)val2).name = "OriginalColorButton"; MenuButtonColor component2 = val2.GetComponent(); if ((Object)(object)component2 != (Object)null) { ((Behaviour)component2).enabled = false; Object.Destroy((Object)(object)component2); } Color val3 = (flag5 ? BridgeOriginalColorButton.FindOriginalColor(pendingAsset, preferredCosmetics) : Color.white); MenuButton component3 = val2.GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.colorNormal = val3 + Color.black * 0.5f; component3.colorHover = val3; component3.colorClick = val3 + Color.white * 0.95f; } val2.GetComponent().anchoredPosition = new Vector2(num, num2); BridgeOriginalColorButton bridgeOriginalColorButton = val2.AddComponent(); bridgeOriginalColorButton.menuPageColor = __instance; bridgeOriginalColorButton.originalColor = val3; if (flag5) { bridgeOriginalColorButton.cosmeticAsset = pendingAsset; bridgeOriginalColorButton.initiallySelected = !flag8 && !flag9 && ((!PerCosmeticColors.HasOverride(pendingAsset.assetId) && !PerCosmeticColors.HasAnySlotColor(pendingAsset.assetId)) || PerCosmeticColors.IsOriginalMode(pendingAsset.assetId)); } else { bridgeOriginalColorButton.sectionMode = true; bridgeOriginalColorButton.sectionColorKey = sectionColorKey; bridgeOriginalColorButton.sectionPageMode = __instance.pageMode; bridgeOriginalColorButton.initiallySelected = false; } TextMeshProUGUI componentInChildren2 = val2.GetComponentInChildren(true); if ((Object)(object)componentInChildren2 != (Object)null) { StripShadow(componentInChildren2); } GameObject val4 = new GameObject("OriginalColorLabel"); val4.transform.SetParent(val2.transform, false); TextMeshProUGUI val5 = val4.AddComponent(); ((TMP_Text)val5).text = "M"; if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)val5).font = ((TMP_Text)componentInChildren).font; BridgeSlotSelectorRow.ApplyOutline(val5, componentInChildren, 0.5f); } ((TMP_Text)val5).fontSize = 12f; ((TMP_Text)val5).fontStyle = (FontStyles)1; ((TMP_Text)val5).alignment = (TextAlignmentOptions)514; ((Graphic)val5).color = new Color(1f, 1f, 1f, 0.35f); ((Graphic)val5).raycastTarget = false; RectTransform component4 = val4.GetComponent(); component4.anchorMin = Vector2.zero; component4.anchorMax = Vector2.one; component4.offsetMin = Vector2.zero; component4.offsetMax = Vector2.zero; OriginalLabelHoverAdjuster originalLabelHoverAdjuster = val2.AddComponent(); originalLabelHoverAdjuster.labelRT = component4; AddTooltip(val2, componentInChildren, "Original Mod color"); } float accentX = (flag2 ? (num - 38f) : num); float accentY = num2; float lowestBtnY = num2; if (flag5 && Plugin.MenuLibAvailable && CustomizerStore.GetEffectiveCustomColors(pendingAsset)) { AdvanceAccentSlot(); Color color; Color val6 = (Color)((flag9 && PerCosmeticColors.TryGetCustomColor(pendingAsset.assetId, out color)) ? color : new Color(0.85f, 0.5f, 0.95f)); (GameObject go, RectTransform labelRT) tuple = MakeAccentButton((Transform)(object)colorButtonHolder, val, componentInChildren, "C", val6, accentX, accentY, "Custom color"); GameObject item = tuple.go; RectTransform item2 = tuple.labelRT; BridgeCustomColorButton bridgeCustomColorButton = item.AddComponent(); bridgeCustomColorButton.cosmeticAsset = pendingAsset; bridgeCustomColorButton.labelRT = item2; bridgeCustomColorButton.menuPageColor = __instance; bridgeCustomColorButton.selectedColor = val6; bridgeCustomColorButton.initiallySelected = flag9; } if (flag5 && !flag2 && Plugin.MenuLibAvailable && CustomizerStore.GetEffectiveColorAnimations(pendingAsset)) { AdvanceAccentSlot(); Color val7 = default(Color); ((Color)(ref val7))..ctor(0.55f, 0.8f, 1f); (GameObject go, RectTransform labelRT) tuple2 = MakeAccentButton((Transform)(object)colorButtonHolder, val, componentInChildren, "A", val7, accentX, accentY, "Animated color"); GameObject item3 = tuple2.go; RectTransform item4 = tuple2.labelRT; BridgeAnimateButton bridgeAnimateButton = item3.AddComponent(); bridgeAnimateButton.cosmeticAsset = pendingAsset; bridgeAnimateButton.labelRT = item4; bridgeAnimateButton.menuPageColor = __instance; bridgeAnimateButton.selectedColor = val7; bridgeAnimateButton.initiallySelected = flag8 && !flag9; } if (!flag5 && Plugin.MenuLibAvailable && flag7) { AdvanceAccentSlot(); Color val8 = default(Color); ((Color)(ref val8))..ctor(0.85f, 0.5f, 0.95f); (GameObject go, RectTransform labelRT) tuple3 = MakeAccentButton((Transform)(object)colorButtonHolder, val, componentInChildren, "C", val8, accentX, accentY, "Custom color"); GameObject item5 = tuple3.go; RectTransform item6 = tuple3.labelRT; BridgeCustomColorButton bridgeCustomColorButton2 = item5.AddComponent(); bridgeCustomColorButton2.menuPageColor = __instance; bridgeCustomColorButton2.labelRT = item6; bridgeCustomColorButton2.selectedColor = val8; bridgeCustomColorButton2.initiallySelected = false; bridgeCustomColorButton2.sectionMode = true; bridgeCustomColorButton2.sectionColorKey = sectionColorKey; bridgeCustomColorButton2.sectionPageMode = __instance.pageMode; } if (flag5) { int num3 = CountMaterialSlotsForAsset(pendingAsset, preferredCosmetics); if (num3 > 1) { float num4 = Mathf.Min(anchoredPosition.y, lowestBtnY) - 30f - 30f + 26f - 16f - 2f; InjectSlotSelector(colorButtonHolder, val, pendingAsset, num3, __instance, num4); InjectSlotTitle(colorButtonHolder, num4 + 30f + 2f, 16f); ((MonoBehaviour)__instance).StartCoroutine(ShiftConfirmNextFrame(__instance, num4)); } } void AdvanceAccentSlot() { accentX += 38f; if (accentX > rowW) { accentX = 0f; accentY -= 30f; } lowestBtnY = Mathf.Min(lowestBtnY, accentY); } } private static void InjectNonBridgeCButton(MenuPageColor menuPageColor, CosmeticAsset asset) { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.MenuLibAvailable) { return; } RectTransform colorButtonHolder = menuPageColor.colorButtonHolder; if ((Object)(object)colorButtonHolder == (Object)null || ((Transform)colorButtonHolder).childCount == 0) { return; } GameObject val = null; for (int i = 0; i < ((Transform)colorButtonHolder).childCount; i++) { Transform child = ((Transform)colorButtonHolder).GetChild(i); if (((Object)child).name != "BridgeSlotSelector") { val = ((Component)child).gameObject; break; } } if ((Object)(object)val == (Object)null) { return; } List list = new List(); for (int j = 0; j < ((Transform)colorButtonHolder).childCount; j++) { Transform child2 = ((Transform)colorButtonHolder).GetChild(j); if (!(((Object)child2).name == "BridgeSlotSelector")) { RectTransform component = ((Component)child2).GetComponent(); if ((Object)(object)component != (Object)null) { list.Add(component); } } } if (list.Count != 0) { bool flag = PerCosmeticColors.HasCustomColor(asset.assetId); Color color; Color val2 = (Color)((flag && PerCosmeticColors.TryGetCustomColor(asset.assetId, out color)) ? color : new Color(0.85f, 0.5f, 0.95f)); Rect rect = colorButtonHolder.rect; float width = ((Rect)(ref rect)).width; Vector2 anchoredPosition = list[0].anchoredPosition; float num = anchoredPosition.x + 38f; float num2 = anchoredPosition.y; if (num > width) { num = 0f; num2 -= 30f; } TextMeshProUGUI componentInChildren = val.GetComponentInChildren(true); (GameObject go, RectTransform labelRT) tuple = MakeAccentButton((Transform)(object)colorButtonHolder, val, componentInChildren, "C", val2, num, num2, "Custom color"); GameObject item = tuple.go; RectTransform item2 = tuple.labelRT; BridgeCustomColorButton bridgeCustomColorButton = item.AddComponent(); bridgeCustomColorButton.cosmeticAsset = asset; bridgeCustomColorButton.labelRT = item2; bridgeCustomColorButton.menuPageColor = menuPageColor; bridgeCustomColorButton.selectedColor = val2; bridgeCustomColorButton.initiallySelected = flag; } } private static void InjectSectionCButton(MenuPageColor menuPageColor, int resolvedSectionKey) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.MenuLibAvailable) { return; } RectTransform colorButtonHolder = menuPageColor.colorButtonHolder; if ((Object)(object)colorButtonHolder == (Object)null || ((Transform)colorButtonHolder).childCount == 0) { return; } GameObject val = null; for (int i = 0; i < ((Transform)colorButtonHolder).childCount; i++) { Transform child = ((Transform)colorButtonHolder).GetChild(i); if (((Object)child).name != "BridgeSlotSelector") { val = ((Component)child).gameObject; break; } } if ((Object)(object)val == (Object)null) { return; } List list = new List(); for (int j = 0; j < ((Transform)colorButtonHolder).childCount; j++) { Transform child2 = ((Transform)colorButtonHolder).GetChild(j); if (!(((Object)child2).name == "BridgeSlotSelector")) { RectTransform component = ((Component)child2).GetComponent(); if ((Object)(object)component != (Object)null) { list.Add(component); } } } if (list.Count != 0) { Rect rect = colorButtonHolder.rect; float width = ((Rect)(ref rect)).width; Vector2 anchoredPosition = list[0].anchoredPosition; float num = anchoredPosition.x + 38f; float num2 = anchoredPosition.y; if (num > width) { num = 0f; num2 -= 30f; } TextMeshProUGUI componentInChildren = val.GetComponentInChildren(true); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.85f, 0.5f, 0.95f); (GameObject go, RectTransform labelRT) tuple = MakeAccentButton((Transform)(object)colorButtonHolder, val, componentInChildren, "C", val2, num, num2, "Custom color"); GameObject item = tuple.go; RectTransform item2 = tuple.labelRT; BridgeCustomColorButton bridgeCustomColorButton = item.AddComponent(); bridgeCustomColorButton.menuPageColor = menuPageColor; bridgeCustomColorButton.labelRT = item2; bridgeCustomColorButton.selectedColor = val2; bridgeCustomColorButton.initiallySelected = false; bridgeCustomColorButton.sectionMode = true; bridgeCustomColorButton.sectionColorKey = resolvedSectionKey; bridgeCustomColorButton.sectionPageMode = menuPageColor.pageMode; } } internal static bool HasEligibleBridgeForSection(MenuPageColor menuPageColor) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Invalid comparison between Unknown and I4 MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return false; } bool flag = menuPageColor.colorKey == 2147483646 || SectionColorButtonPatch.PendingWorldSection; foreach (int item in instance.cosmeticEquipped) { if (item < 0 || item >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = instance.cosmeticAssets[item]; if (!BridgeTintHelper.CanBridgeCosmeticReceivePaint(val)) { continue; } bool flag2 = HhhCosmeticLoader.IsWorldAsset(val); if (flag) { if (flag2) { return true; } } else if (flag2) { bool flag3 = menuPageColor.colorKey < 0; bool flag4 = (int)menuPageColor.pageMode == 2; if (flag3 && !flag4) { return true; } } else if (SectionScopeIncludes(menuPageColor, val.type)) { return true; } } return false; } internal static bool SectionScopeIncludes(MenuPageColor page, CosmeticType type) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (page.colorKey == 2147483646) { return false; } return VanillaTintHelper.SectionTypeScope(type, page.colorKey, page.pageMode); } private static IEnumerator ShiftConfirmNextFrame(MenuPageColor menuPageColor, float slotRowY) { yield return null; ShiftConfirmButton(menuPageColor, slotRowY); } private static int CountMaterialSlotsForAsset(CosmeticAsset asset, PlayerCosmetics? preferredCosmetics) { BridgeTintMaterial[] btms = (((Object)(object)preferredCosmetics?.playerAvatarVisuals != (Object)null) ? ((Component)preferredCosmetics.playerAvatarVisuals).GetComponentsInChildren(true) : Object.FindObjectsOfType(true)); int num = MaxSlotId(btms, asset) + 1; if (num > 0 || (Object)(object)preferredCosmetics?.playerAvatarVisuals == (Object)null) { return num; } return MaxSlotId(Object.FindObjectsOfType(true), asset) + 1; } private static int MaxSlotId(BridgeTintMaterial[] btms, CosmeticAsset asset) { int num = -1; foreach (BridgeTintMaterial bridgeTintMaterial in btms) { if ((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset != (Object)(object)asset) { continue; } Material[]? materials = bridgeTintMaterial.materials; int num2; if (materials == null) { Color[]? originalPrimaryColors = bridgeTintMaterial.originalPrimaryColors; num2 = ((originalPrimaryColors != null) ? originalPrimaryColors.Length : 0); } else { num2 = materials.Length; } int num3 = num2; for (int j = 0; j < num3; j++) { if (bridgeTintMaterial.SlotIdOf(j) > num) { num = bridgeTintMaterial.SlotIdOf(j); } } } return num; } private static void InjectSlotSelector(RectTransform holder, GameObject templateGO, CosmeticAsset asset, int slotCount, MenuPageColor menuPageColor, float rowY) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BridgeSlotSelector"); val.transform.SetParent((Transform)(object)holder, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0f, 0f); val2.anchorMax = new Vector2(0f, 0f); val2.pivot = new Vector2(0f, 0f); val2.anchoredPosition = new Vector2(0f, rowY); Rect rect = holder.rect; val2.sizeDelta = new Vector2(((Rect)(ref rect)).width, 30f); BridgeSlotSelectorRow bridgeSlotSelectorRow = val.AddComponent(); bridgeSlotSelectorRow.slotCount = slotCount; rect = holder.rect; bridgeSlotSelectorRow.containerWidth = ((Rect)(ref rect)).width; bridgeSlotSelectorRow.cosmeticAsset = asset; bridgeSlotSelectorRow.buttonTemplate = templateGO; bridgeSlotSelectorRow.menuPageColor = menuPageColor; } private static void InjectSlotTitle(RectTransform holder, float rowY, float height) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("SlotSelectorTitle"); val.transform.SetParent((Transform)(object)holder, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0f, 0f); val2.anchorMax = new Vector2(0f, 0f); val2.pivot = new Vector2(0f, 0f); val2.anchoredPosition = new Vector2(0f, rowY); Rect rect = holder.rect; val2.sizeDelta = new Vector2(((Rect)(ref rect)).width, height); TextMeshProUGUI componentInChildren = ((Component)holder).GetComponentInChildren(true); TextMeshProUGUI val3 = val.AddComponent(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)val3).font = ((TMP_Text)componentInChildren).font; ((TMP_Text)val3).fontSharedMaterial = ((TMP_Text)componentInChildren).fontSharedMaterial; } ((TMP_Text)val3).text = "Material slot:"; ((TMP_Text)val3).fontSize = 16f; ((Graphic)val3).color = new Color(1f, 1f, 1f, 0.5f); ((TMP_Text)val3).alignment = (TextAlignmentOptions)4097; ((Graphic)val3).raycastTarget = false; } private static void ShiftConfirmButton(MenuPageColor menuPageColor, float slotRowY) { //IL_001a: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) RectTransform colorButtonHolder = menuPageColor.colorButtonHolder; RectTransform val = FindConfirmRT(menuPageColor, colorButtonHolder); if (!((Object)(object)val == (Object)null)) { Rect rect = val.rect; float height = ((Rect)(ref rect)).height; float num = slotRowY - 12f; float num2 = val.anchoredPosition.y - num; if (num2 > 0f) { val.anchoredPosition -= new Vector2(0f, num2); } } } private static RectTransform? FindConfirmRT(MenuPageColor menuPageColor, RectTransform holder) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) Transform[] componentsInChildren = ((Component)menuPageColor).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } RectTransform component = ((Component)val).GetComponent(); if ((component == null || !((Transform)component).IsChildOf((Transform)(object)holder)) && ((Object)val).name.IndexOf("confirm", StringComparison.OrdinalIgnoreCase) >= 0) { RectTransform component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { return component2; } } } RectTransform result = null; float num = float.PositiveInfinity; MenuButton[] componentsInChildren2 = ((Component)menuPageColor).GetComponentsInChildren(true); foreach (MenuButton val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null)) { RectTransform component3 = ((Component)val2).GetComponent(); if (!((Object)(object)component3 == (Object)null) && !((Transform)component3).IsChildOf((Transform)(object)holder) && component3.anchoredPosition.y < num) { num = component3.anchoredPosition.y; result = component3; } } } return result; } private static (GameObject go, RectTransform labelRT) MakeAccentButton(Transform holder, GameObject templateGO, TextMeshProUGUI? templateTmp, string letter, Color tint, float x, float y, string tooltip) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate(templateGO, holder); ((Object)val).name = "AccentColorButton_" + letter; MenuButtonColor component = val.GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; Object.Destroy((Object)(object)component); } StripShadow(val.GetComponentInChildren(true)); MenuButton component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.colorNormal = tint + Color.black * 0.5f; component2.colorHover = tint; component2.colorClick = tint + Color.white * 0.95f; } val.GetComponent().anchoredPosition = new Vector2(x, y); GameObject val2 = new GameObject("AccentLabel"); val2.transform.SetParent(val.transform, false); TextMeshProUGUI val3 = val2.AddComponent(); ((TMP_Text)val3).text = letter; if ((Object)(object)templateTmp != (Object)null) { ((TMP_Text)val3).font = ((TMP_Text)templateTmp).font; BridgeSlotSelectorRow.ApplyOutline(val3, templateTmp, 0.5f); } ((TMP_Text)val3).fontSize = 12f; ((TMP_Text)val3).fontStyle = (FontStyles)1; ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((Graphic)val3).color = new Color(1f, 1f, 1f, 0.6f); ((Graphic)val3).raycastTarget = false; RectTransform component3 = val2.GetComponent(); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = Vector2.zero; component3.offsetMax = Vector2.zero; AddTooltip(val, templateTmp, tooltip); return (go: val, labelRT: component3); } private static void StripShadow(TextMeshProUGUI? tmp) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)tmp == (Object)null) && !((Object)(object)((TMP_Text)tmp).fontSharedMaterial == (Object)null)) { Material val = Object.Instantiate(((TMP_Text)tmp).fontSharedMaterial); val.DisableKeyword("UNDERLAY_ON"); if (val.HasProperty("_UnderlayColor")) { val.SetColor("_UnderlayColor", new Color(0f, 0f, 0f, 0f)); } ((TMP_Text)tmp).fontSharedMaterial = val; ((Component)tmp).gameObject.AddComponent().material = val; } } private static void AddTooltip(GameObject button, TextMeshProUGUI? templateTmp, string text) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014f: 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_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Tooltip"); val.transform.SetParent(button.transform, false); Image val2 = val.AddComponent(); ((Graphic)val2).color = new Color(0f, 0f, 0f, 0.72f); ((Graphic)val2).raycastTarget = false; RectTransform component = val.GetComponent(); component.sizeDelta = new Vector2(86f, 16f); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 1f); component.anchorMax = val3; component.anchorMin = val3; component.pivot = new Vector2(0.5f, 0f); component.anchoredPosition = new Vector2(0f, 6f); GameObject val4 = new GameObject("Label"); val4.transform.SetParent(val.transform, false); TextMeshProUGUI val5 = val4.AddComponent(); ((TMP_Text)val5).text = text; if ((Object)(object)templateTmp != (Object)null) { ((TMP_Text)val5).font = ((TMP_Text)templateTmp).font; BridgeSlotSelectorRow.ApplyOutline(val5, templateTmp, 0.5f); } ((TMP_Text)val5).fontSize = 14f; ((TMP_Text)val5).fontStyle = (FontStyles)1; ((TMP_Text)val5).alignment = (TextAlignmentOptions)514; ((TMP_Text)val5).enableWordWrapping = false; ((TMP_Text)val5).overflowMode = (TextOverflowModes)0; ((Graphic)val5).raycastTarget = false; ((Graphic)val5).color = Color.white; RectTransform component2 = val4.GetComponent(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = new Vector2(4f, 0f); component2.offsetMax = new Vector2(-4f, 0f); val.transform.SetAsLastSibling(); val.SetActive(false); button.AddComponent().tooltip = val; } } [HarmonyPatch(typeof(MetaManager), "CosmeticEquip")] internal static class CosmeticEquipColorPreservePatch { [HarmonyPrefix] private static void Prefix(MetaManager __instance, CosmeticAsset _cosmeticAssetNew, bool _isPreview) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled || (Object)(object)_cosmeticAssetNew == (Object)null) { return; } int num = (int)_cosmeticAssetNew.type; int[] colorsEquipped = __instance.colorsEquipped; if (num < 0 || num >= colorsEquipped.Length) { return; } int num2 = colorsEquipped[num]; if (num2 < 0) { return; } if (_isPreview) { List cosmeticEquippedPreview = __instance.cosmeticEquippedPreview; { foreach (int item in cosmeticEquippedPreview) { if (item >= 0 && item < __instance.cosmeticAssets.Count) { CosmeticAsset val = __instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && val.type == _cosmeticAssetNew.type && !BridgeIds.IsBridgeAsset(val) && !PerCosmeticColors.HasOverride(val.assetId) && !PerCosmeticColors.HasPreviewOverride(val.assetId)) { PerCosmeticColors.SetPreview(val.assetId, num2); } } } return; } } int realTypeColor = PerCosmeticColors.GetRealTypeColor(num, colorsEquipped); if (realTypeColor < 0) { return; } List cosmeticEquipped = __instance.cosmeticEquipped; bool flag = false; foreach (int item2 in cosmeticEquipped) { if (item2 >= 0 && item2 < __instance.cosmeticAssets.Count) { CosmeticAsset val2 = __instance.cosmeticAssets[item2]; if (!((Object)(object)val2 == (Object)null) && val2.type == _cosmeticAssetNew.type && !BridgeIds.IsBridgeAsset(val2) && !PerCosmeticColors.HasOverride(val2.assetId)) { PerCosmeticColors.SetNoSave(val2.assetId, realTypeColor); flag = true; } } } if (flag) { PerCosmeticColors.Save(); } } } [HarmonyPatch(typeof(MetaManager), "CosmeticPreviewSet")] internal static class CosmeticPreviewSetClearPatch { [HarmonyPrefix] private static void Prefix(bool _state) { if (PerCosmeticColors.FeatureEnabled && !_state && (Object)(object)PerCosmeticColors.PendingAsset == (Object)null) { bool presetPreviewActive = PerCosmeticColors.PresetPreviewActive; PerCosmeticColors.ClearPreviewOverrides(); PerCosmeticColors.NotifyPresetHoverStart(-1); if (presetPreviewActive && !PresetLoadColorsPatch.LoadInProgress) { ColorAnimatorRefresher.RefreshLocal(); } } } } [HarmonyPatch(typeof(MetaManager), "CosmeticUnequip")] internal static class CosmeticUnequipColorClearPatch { [HarmonyPostfix] private static void Postfix(CosmeticAsset _cosmeticAsset, bool _isPreview, bool __result) { if (PerCosmeticColors.FeatureEnabled && __result && !_isPreview && !((Object)(object)_cosmeticAsset == (Object)null)) { PerCosmeticColors.ClearForAsset(_cosmeticAsset.assetId); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "ResetAllButton")] internal static class ResetAllButtonClearPatch { [HarmonyPostfix] private static void Postfix() { if (PerCosmeticColors.FeatureEnabled) { PerCosmeticColors.ClearAll(); RuntimeConfigApplier.ReapplyLocalCosmeticColors(); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "ResetBodyButton")] internal static class ResetBodyButtonClearPatch { [HarmonyPostfix] private static void Postfix() { if (PerCosmeticColors.FeatureEnabled && PerCosmeticColors.ClearAllBaseMeshCustomColorsNoSave()) { PerCosmeticColors.SaveCustom(); RuntimeConfigApplier.ReapplyLocalCosmeticColors(); } } } [HarmonyPatch(typeof(MetaManager), "CosmeticPresetSet")] internal static class CosmeticPresetSetColorsPatch { [HarmonyPostfix] private static void Postfix(int _index, List _cosmeticEquipped) { if (PerCosmeticColors.FeatureEnabled) { if (_cosmeticEquipped.Count == 0) { PerCosmeticColors.DeletePresetColors(_index); } else { PerCosmeticColors.SavePreset(_index, _cosmeticEquipped); } } } } [HarmonyPatch(typeof(MenuElementCosmeticPreset), "IsEquipped")] internal static class PresetIsEquippedColorPatch { [HarmonyPostfix] private static void Postfix(MenuElementCosmeticPreset __instance, ref bool __result) { if (__result && PerCosmeticColors.FeatureEnabled && !PerCosmeticColors.PresetMatchesCurrent(__instance.presetIndex)) { __result = false; } } } [HarmonyPatch(typeof(MenuElementCosmeticPreset), "Update")] internal static class PresetHoverIndexTrackPatch { [HarmonyPrefix] private static void Prefix(MenuElementCosmeticPreset __instance) { if (PerCosmeticColors.FeatureEnabled && (Object)(object)__instance.menuButton != (Object)null && __instance.menuButton.hovering) { PerCosmeticColors.NotifyPresetHoverStart(__instance.presetIndex); } } } [HarmonyPatch(typeof(MetaManager), "CosmeticPreviewSet")] internal static class PresetPreviewColorsPatch { [HarmonyPostfix] private static void Postfix(MetaManager __instance, bool _state) { if (!PerCosmeticColors.FeatureEnabled || !_state) { return; } int num = FindMatchingPreset(__instance); if (num < 0) { if (PerCosmeticColors.PresetPreviewActive) { PerCosmeticColors.ClearPresetPreviewOnly(); ColorAnimatorRefresher.RefreshLocal(); } return; } PerCosmeticColors.ClearPreviewOverrides(); PerCosmeticColors.SetPresetPreviewActive(value: true); IReadOnlyDictionary presetColors = PerCosmeticColors.GetPresetColors(num); if (presetColors == null) { return; } foreach (KeyValuePair item in presetColors) { PerCosmeticColors.SetPreviewFromEntry(item.Key, item.Value); } } private static int FindMatchingPreset(MetaManager meta) { List cosmeticEquippedPreview = meta.cosmeticEquippedPreview; if (cosmeticEquippedPreview.Count == 0) { return -1; } int pendingHoverPresetIndex = PerCosmeticColors.GetPendingHoverPresetIndex(); if (pendingHoverPresetIndex < 0 || pendingHoverPresetIndex >= meta.cosmeticPresets.Count) { return -1; } HashSet hashSet = new HashSet(cosmeticEquippedPreview); List list = meta.cosmeticPresets[pendingHoverPresetIndex]; if (list.Count != hashSet.Count) { return -1; } foreach (int item in list) { if (!hashSet.Contains(item)) { return -1; } } return pendingHoverPresetIndex; } } [HarmonyPatch(typeof(MenuElementCosmeticPreset), "TogglePreset")] internal static class PresetLoadColorsPatch { private static bool _wasLoad; internal static bool LoadInProgress { get; private set; } [HarmonyPrefix] private static void Prefix(MenuElementCosmeticPreset __instance) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { _wasLoad = false; return; } _wasLoad = instance.cosmeticPresets[__instance.presetIndex].Count > 0 || instance.colorPresets[__instance.presetIndex].Count > 0; LoadInProgress = _wasLoad && PerCosmeticColors.FeatureEnabled; } [HarmonyPostfix] private static void Postfix(MenuElementCosmeticPreset __instance) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled || !_wasLoad) { LoadInProgress = false; return; } MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { LoadInProgress = false; return; } IReadOnlyDictionary presetColors = PerCosmeticColors.GetPresetColors(__instance.presetIndex); HashSet hashSet = new HashSet(); foreach (int item in instance.cosmeticPresets[__instance.presetIndex]) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[item]; if ((Object)(object)val != (Object)null) { hashSet.Add(val.type); } } } foreach (CosmeticType item2 in hashSet) { PerCosmeticColors.ClearAllForType(item2, instance); } if (PerCosmeticColors.ClearAllBaseMeshCustomColorsNoSave()) { PerCosmeticColors.SaveCustom(); } if (presetColors != null && presetColors.Count > 0) { PerCosmeticColors.RestorePreset(__instance.presetIndex); } LoadInProgress = false; instance.CosmeticPlayerUpdateLocal(false, false); } } [HarmonyPatch(typeof(PlayerCosmetics), "Awake")] internal static class PerCosmeticColorSyncAwakePatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { PerCosmeticColorSyncComponent sync = ((Component)__instance).gameObject.AddComponent(); PerCosmeticColorNetworkSync.ApplyCachedTo(__instance, sync); } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupCosmetics")] internal static class SendPerCosmeticColorsSyncPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance, bool _synced) { if (_synced && SemiFunc.IsMultiplayer() && !((Object)(object)__instance.photonView == (Object)null) && __instance.photonView.IsMine) { bool flag = PerCosmeticColorNetworkSync.CloseGate(); if (PerCosmeticColors.FeatureEnabled) { PerCosmeticColorNetworkSync.BroadcastAll(); } else if (flag) { BridgeNetMux.BroadcastSnapshot(); } } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColors")] internal static class AlignTypeColorsForSyncPatch { [HarmonyPrefix] private static void Prefix(PlayerCosmetics __instance, bool _synced, ref int[] _colors) { if (!PerCosmeticColors.FeatureEnabled || !_synced || _colors != null) { return; } PlayerAvatarVisuals playerAvatarVisuals = __instance.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null || playerAvatarVisuals.isMenuAvatar) { return; } if (SemiFunc.IsMultiplayer()) { PlayerAvatar playerAvatar = playerAvatarVisuals.playerAvatar; if (playerAvatar == null || !playerAvatar.isLocal) { return; } } int[] array = PerCosmeticColors.BuildCompatibilitySyncColors(MetaManager.instance); if (array != null) { _colors = array; } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsLogic")] internal static class ApplyRemoteColorsAfterSetupLogicPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { RemoteColorSync.Apply(__instance); } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsAllLogic")] internal static class ApplyRemoteColorsAfterSetupAllLogicPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { RemoteColorSync.Apply(__instance); } } internal static class RemoteColorSync { internal static void Apply(PlayerCosmetics pc) { PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null) { return; } if (playerAvatarVisuals.isMenuAvatar) { if (AvatarIdentity.IsRemoteMini(pc)) { PerCosmeticColorSyncComponent component = ((Component)pc).GetComponent(); if ((Object)(object)component != (Object)null) { component.ApplyToCosmetics(pc); component.RefreshAnimators(pc); } } return; } PlayerAvatar playerAvatar = playerAvatarVisuals.playerAvatar; if (playerAvatar == null || !playerAvatar.isLocal) { PerCosmeticColorSyncComponent component2 = ((Component)pc).GetComponent(); if (!((Object)(object)component2 == (Object)null)) { component2.ApplyToCosmetics(pc); component2.RefreshAnimators(pc); } } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsLogic")] internal static class SetupColorsLogicOverridePatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { BridgeTintHelper.ApplyTypeColors(__instance); PerCosmeticColors.ApplyOverrides(__instance); ColorAnimatorRefresher.RefreshLiveAnimators(__instance); } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColors")] internal static class SetupColorsBaseMeshPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { VanillaTintHelper.ReapplyBaseMeshColors(__instance); } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsAllLogic")] internal static class SetupColorsAllLogicOverridePatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { BridgeTintHelper.ApplyTypeColors(__instance); PerCosmeticColors.ApplyOverrides(__instance); ColorAnimatorRefresher.RefreshLiveAnimators(__instance); } } internal static class ColorAnimatorRefresher { internal static void RefreshLiveAnimators(PlayerCosmetics pc) { PlayerAvatarVisuals val = pc?.playerAvatarVisuals; if ((Object)(object)val == (Object)null) { return; } if (!val.isMenuAvatar) { PlayerAvatar playerAvatar = val.playerAvatar; if (playerAvatar == null || !playerAvatar.isLocal) { return; } } if (AvatarIdentity.IsRemoteMini(pc)) { return; } if (!PerCosmeticColors.MiniPresetContextActive) { int num = MiniSemibotSpawner.PresetSlotOf(pc); if (num >= 0) { PerCosmeticColors.RunWithPresetContext(num, delegate { RefreshLiveAnimators(pc); }); return; } } if (!PerCosmeticColors.FeatureEnabled) { Apply(pc, (string _) => default(AnimSet)); return; } Func baseLookup = (PerCosmeticColors.PresetPreviewActive ? new Func(PerCosmeticColors.GetPreviewAnimSet) : new Func(PerCosmeticColors.GetAnimSet)); Apply(pc, (string id) => (!CustomizerStore.GetEffectiveColorAnimations(id)) ? default(AnimSet) : baseLookup(id)); } internal static void StopAnimation(string? assetId, int slot = -1) { if (assetId == null) { return; } if (slot >= 0) { if (PerCosmeticColors.RemoveSlotAnimationNoSave(assetId, slot)) { PerCosmeticColors.SaveSlotAnimations(); } } else { bool flag = PerCosmeticColors.HasAnimation(assetId) || PerCosmeticColors.HasAnySlotAnimation(assetId); PerCosmeticColors.RemoveAnimationNoSave(assetId); PerCosmeticColors.RemoveSlotAnimationsNoSave(assetId); if (flag) { PerCosmeticColors.SaveAnimations(); PerCosmeticColors.SaveSlotAnimations(); } } PlayerCosmetics[] array = Object.FindObjectsOfType(); foreach (PlayerCosmetics pc in array) { RefreshLiveAnimators(pc); } } internal static void RefreshLocal() { PlayerCosmetics[] array = Object.FindObjectsOfType(); foreach (PlayerCosmetics pc in array) { RefreshLiveAnimators(pc); } } internal static void Apply(PlayerCosmetics pc, Func lookup) { PlayerAvatarVisuals val = pc?.playerAvatarVisuals; if ((Object)(object)val == (Object)null) { return; } HashSet hashSet = new HashSet(); BridgeTintMaterial[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Cosmetic val2 = componentsInChildren[i]?.cosmetic; string text = val2?.cosmeticAsset?.assetId; if ((Object)(object)val2 == (Object)null || text == null || !hashSet.Add(val2)) { continue; } AnimSet set = lookup(text); if (set.Any) { BridgeColorAnimator bridgeColorAnimator = ((Component)val2).GetComponent() ?? ((Component)val2).gameObject.AddComponent(); bridgeColorAnimator.Init(((Component)val2).gameObject, set); if (bridgeColorAnimator.IsEmpty) { bridgeColorAnimator.Stop(); } } } BridgeColorAnimator[] componentsInChildren2 = ((Component)val).GetComponentsInChildren(true); foreach (BridgeColorAnimator bridgeColorAnimator2 in componentsInChildren2) { string text2 = ((Component)bridgeColorAnimator2).GetComponent()?.cosmeticAsset?.assetId; if (text2 == null || !lookup(text2).Any) { bridgeColorAnimator2.Stop(); } } } } [HarmonyPatch(typeof(SpectateHeadUI), "Update")] internal static class SpectateHeadCustomColorPatch { private static readonly int[] ImageTypes = new int[6] { 5, 14, 14, 15, 15, 5 }; private static readonly int[] DarkTypes = new int[2] { 11, 12 }; private const float DarkBlend = 0.5f; private const float ResolveInterval = 0.5f; private static float _nextResolve; private static readonly Color?[] _custom = new Color?[ImageTypes.Length]; private static readonly Color?[] _customDark = new Color?[DarkTypes.Length]; [HarmonyPostfix] private static void Postfix(SpectateHeadUI __instance) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled) { return; } PlayerCosmetics val = SemiFunc.PlayerGetLocal()?.playerCosmetics; if ((Object)(object)val == (Object)null) { return; } if (Time.time >= _nextResolve) { _nextResolve = Time.time + 0.5f; for (int i = 0; i < ImageTypes.Length; i++) { _custom[i] = Resolve(val, ImageTypes[i]); } for (int j = 0; j < DarkTypes.Length; j++) { Color? val2 = Resolve(val, DarkTypes[j]); _customDark[j] = (val2.HasValue ? new Color?(Color.Lerp(val2.Value, Color.black, 0.5f)) : ((Color?)null)); } } Apply(__instance.colorImages, _custom); Apply(__instance.colorImagesDark, _customDark); } private static void Apply(RawImage[]? images, Color?[] customs) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0050: Unknown result type (might be due to invalid IL or missing references) if (images == null) { return; } for (int i = 0; i < images.Length && i < customs.Length; i++) { if (customs[i].HasValue && !((Object)(object)images[i] == (Object)null)) { Color value = customs[i].Value; ((Graphic)images[i]).color = new Color(value.r, value.g, value.b, ((Graphic)images[i]).color.a); } } } private static Color? Resolve(PlayerCosmetics pc, int typeIndex) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_0059: Unknown result type (might be due to invalid IL or missing references) PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals != (Object)null) { Cosmetic[] componentsInChildren = ((Component)playerAvatarVisuals).GetComponentsInChildren(true); foreach (Cosmetic val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && (int)val.type == typeIndex) { string text = val.cosmeticAsset?.assetId; if (text != null && PerCosmeticColors.TryGetCustomColor(text, out var color)) { return color; } } } } if (!PerCosmeticColors.TryGetCustomColor(VanillaTintHelper.BaseMeshAssetId(typeIndex), out var color2)) { return null; } return color2; } } internal static class PerCosmeticColorNetworkSync { private sealed class RemoteColorCache { internal Dictionary Colors = new Dictionary(); internal Dictionary> SlotColors = new Dictionary>(); internal Dictionary Animations = new Dictionary(); internal Dictionary CustomColors = new Dictionary(); internal Dictionary> CustomSlotColors = new Dictionary>(); internal Dictionary> SlotAnimations = new Dictionary>(); } private static readonly Dictionary _remote = new Dictionary(); private const int MaxPayloadChars = 16384; internal static bool BrowseGateOpen { get; private set; } internal static void OpenGate() { BrowseGateOpen = true; } internal static bool CloseGate() { if (!BrowseGateOpen) { return false; } BrowseGateOpen = false; MiniSemibotSpawner.CommitPendingBroadcast(); return true; } internal static void PurgeActor(int actorNumber) { _remote.Remove(actorNumber); } internal static void PurgeAll() { _remote.Clear(); BrowseGateOpen = false; } internal static void BroadcastAll() { if (PerCosmeticColors.FeatureEnabled && SemiFunc.IsMultiplayer()) { BridgeNetMux.BroadcastSnapshot(); } } private static bool TryGate(out string? gated) { if (!PerCosmeticColors.FeatureEnabled) { gated = ""; return true; } if (BrowseGateOpen) { gated = null; return true; } gated = null; return false; } internal static string? BuildColorsSection() { if (TryGate(out string gated)) { return gated; } return PerCosmeticColorSerializer.SerializeWithSlots(PerCosmeticColors.GetAll(), PerCosmeticColors.GetAllSlots()); } internal static string? BuildAnimationsSection() { if (TryGate(out string gated)) { return gated; } if (!Plugin.EnableBridgeColorAnimations.Value) { return ""; } return PerCosmeticColorSerializer.SerializeAnimations(PerCosmeticColors.GetAllAnimations()); } internal static string? BuildCustomColorsSection() { if (TryGate(out string gated)) { return gated; } BuildSyncableCustom(out Dictionary whole, out Dictionary> slots); return PerCosmeticColorSerializer.SerializeCustomColors(whole, slots); } internal static string? BuildSlotAnimationsSection() { if (TryGate(out string gated)) { return gated; } if (!Plugin.EnableBridgeColorAnimations.Value) { return ""; } return PerCosmeticColorSerializer.SerializeSlotAnimations(PerCosmeticColors.GetAllSlotAnimations()); } private static void BuildSyncableCustom(out Dictionary whole, out Dictionary> slots) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) whole = new Dictionary(); slots = new Dictionary>(); MetaManager meta = MetaManager.instance; Dictionary lookup = null; foreach (KeyValuePair item in PerCosmeticColors.GetAllCustom()) { if (Allowed(item.Key)) { whole[item.Key] = item.Value; } } foreach (KeyValuePair> allCustomSlot in PerCosmeticColors.GetAllCustomSlots()) { if (Allowed(allCustomSlot.Key)) { slots[allCustomSlot.Key] = allCustomSlot.Value; } } bool Allowed(string key) { if (VanillaTintHelper.IsBaseMeshId(key)) { return Plugin.EnableVanillaCustomColors.Value; } if (meta?.cosmeticAssets == null) { return Plugin.EnableBridgeCustomColors.Value; } if (lookup == null) { lookup = new Dictionary(meta.cosmeticAssets.Count); foreach (CosmeticAsset cosmeticAsset in meta.cosmeticAssets) { if ((Object)(object)cosmeticAsset != (Object)null && !string.IsNullOrEmpty(cosmeticAsset.assetId)) { lookup[cosmeticAsset.assetId] = cosmeticAsset; } } } if (!lookup.TryGetValue(key, out CosmeticAsset value)) { return Plugin.EnableBridgeCustomColors.Value; } return CustomizerStore.GetEffectiveCustomColors(value); } } private static bool IsSyncReceiveTarget(PlayerCosmetics? pc) { if ((Object)(object)pc != (Object)null) { if (AvatarIdentity.IsLocalOrMenu(pc)) { return AvatarIdentity.IsRemoteMini(pc); } return true; } return false; } internal static void ApplyCachedTo(PlayerCosmetics pc, PerCosmeticColorSyncComponent sync) { if (IsSyncReceiveTarget(pc)) { int ownerActor = GetOwnerActor(pc); if (ownerActor > 0 && (!AvatarIdentity.IsRemoteMini(pc) || !MiniSemibotSync.RemoteMiniHasOwnColors(ownerActor)) && _remote.TryGetValue(ownerActor, out RemoteColorCache value)) { sync.SetRemoteColors(value.Colors, value.SlotColors); sync.SetRemoteAnimations(value.Animations); sync.SetRemoteCustomColors(value.CustomColors, value.CustomSlotColors); sync.SetRemoteSlotAnimations(value.SlotAnimations); sync.ApplyToCosmetics(pc); sync.RefreshAnimators(pc); } } } internal static bool PopulateFromCachedActor(int actor, PerCosmeticColorSyncComponent sync) { if (actor <= 0 || !_remote.TryGetValue(actor, out RemoteColorCache value)) { return false; } sync.SetRemoteColors(value.Colors, value.SlotColors); sync.SetRemoteAnimations(value.Animations); sync.SetRemoteCustomColors(value.CustomColors, value.CustomSlotColors); sync.SetRemoteSlotAnimations(value.SlotAnimations); return true; } internal static void OnColorSection(int actor, string colorData) { if (TryBeginReceive(actor, colorData, out RemoteColorCache cache)) { PerCosmeticColorSerializer.DeserializeWithSlots(colorData, out cache.Colors, out cache.SlotColors); ApplyCacheToActor(actor, cache); } } internal static void OnAnimationSection(int actor, string animData) { if (TryBeginReceive(actor, animData, out RemoteColorCache cache)) { cache.Animations = PerCosmeticColorSerializer.DeserializeAnimations(animData); ApplyCacheToActor(actor, cache); } } internal static void OnCustomColorSection(int actor, string customData) { if (TryBeginReceive(actor, customData, out RemoteColorCache cache)) { PerCosmeticColorSerializer.DeserializeCustomColors(customData, out cache.CustomColors, out cache.CustomSlotColors); ApplyCacheToActor(actor, cache); LobbyHeadCustomColorPatch.RefreshAllHeads(); } } internal static void OnSlotAnimSection(int actor, string slotAnimData) { if (TryBeginReceive(actor, slotAnimData, out RemoteColorCache cache)) { cache.SlotAnimations = PerCosmeticColorSerializer.DeserializeSlotAnimations(slotAnimData); ApplyCacheToActor(actor, cache); } } private static void ApplyCacheToActor(int actor, RemoteColorCache cache) { PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { if ((Object)(object)val == (Object)null || GetOwnerActor(val) != actor || !IsSyncReceiveTarget(val) || (AvatarIdentity.IsRemoteMini(val) && MiniSemibotSync.RemoteMiniHasOwnColors(actor))) { continue; } PerCosmeticColorSyncComponent component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null)) { component.SetRemoteColors(cache.Colors, cache.SlotColors); component.SetRemoteAnimations(cache.Animations); component.SetRemoteCustomColors(cache.CustomColors, cache.CustomSlotColors); component.SetRemoteSlotAnimations(cache.SlotAnimations); if (val.colorsEquipped != null) { val.SetupColors(false, val.colorsEquipped); continue; } component.ApplyToCosmetics(val); component.RefreshAnimators(val); } } MiniSemibotSpawner.RefreshRemoteMiniColors(actor); } private static bool TryBeginReceive(int actor, string data, out RemoteColorCache cache) { cache = null; if (data == null || data.Length > 16384 || actor <= 0) { return false; } cache = GetOrCreate(actor); return true; } private static RemoteColorCache GetOrCreate(int actor) { if (!_remote.TryGetValue(actor, out RemoteColorCache value)) { value = (_remote[actor] = new RemoteColorCache()); } return value; } private static int GetOwnerActor(PlayerCosmetics pc) { PhotonView component = ((Component)pc).GetComponent(); if (((component != null) ? component.Owner : null) != null) { return component.Owner.ActorNumber; } PhotonView val = pc.playerAvatarVisuals?.playerAvatar?.photonView; if (((val != null) ? val.Owner : null) != null) { return val.Owner.ActorNumber; } return 0; } } internal static class PerCosmeticColors { private sealed class ColorStoreData { public int Version { get; set; } = 2; public Dictionary? Colors { get; set; } public Dictionary>? Slots { get; set; } public Dictionary? Animations { get; set; } public Dictionary>? SlotAnimations { get; set; } public Dictionary? Custom { get; set; } public Dictionary>? CustomSlots { get; set; } } private static readonly string AnimSavePath = BridgePaths.Of("ColorAnimations.json"); private static readonly string SlotAnimSavePath = BridgePaths.Of("SlotColorAnimations.json"); private static Dictionary _animations = new Dictionary(); private static Dictionary> _slotAnimations = new Dictionary>(); private static readonly string SavePath = BridgePaths.Of("PerCosmeticColors.json"); private static readonly string LegacyPath = Path.Combine(Application.persistentDataPath, "MoreHeadBridge_PerCosmeticColors.json"); internal static readonly int PropAlbedo = Shader.PropertyToID("_AlbedoColor"); internal static readonly int PropEmission = Shader.PropertyToID("_EmissionColor"); internal static readonly int PropFresnel = Shader.PropertyToID("_FresnelColor"); internal const int OriginalColorSentinel = -1; private static Dictionary _colors = new Dictionary(); private static Task _lastWrite = Task.CompletedTask; internal static int StoreVersion; private static readonly string CustomSavePath = BridgePaths.Of("PerCosmeticCustomColors.json"); private static Dictionary _customColors = new Dictionary(); private static readonly string CustomSlotSavePath = BridgePaths.Of("PerCosmeticCustomSlotColors.json"); private static Dictionary> _customSlotColors = new Dictionary>(); private static readonly string PresetSavePath = BridgePaths.Of("PresetColors.json"); private static Dictionary> _presetColors = new Dictionary>(); private static bool _presetPreviewActive; private static int _pendingHoverPresetIndex = -1; private static Task _lastPresetWrite = Task.CompletedTask; private static Dictionary _previewOverrides = new Dictionary(); private static Dictionary _previewCustom = new Dictionary(); private static Dictionary> _previewSlotOverrides = new Dictionary>(); private static Dictionary> _previewSlotCustom = new Dictionary>(); private static Dictionary _previewAnimations = new Dictionary(); private static Dictionary> _previewSlotAnimations = new Dictionary>(); private static readonly HashSet _previewEntryExists = new HashSet(); private static int _savedTypeColor = -1; private static int _savedTypeIndex = -1; private static readonly string SlotSavePath = BridgePaths.Of("PerCosmeticSlotColors.json"); private static Dictionary> _slotColors = new Dictionary>(); internal static bool FeatureEnabled => Plugin.EnablePerCosmeticColors.Value; internal static CosmeticAsset? PendingAsset { get; set; } internal static bool PresetPreviewActive => _presetPreviewActive; internal static bool MiniPresetContextActive { get; private set; } internal static int ActiveSlot { get; set; } = -1; internal static void SetAnimation(string assetId, ColorAnimation spec) { _animations[assetId] = spec; SaveAnimations(); if (RemoveColorNoSave(assetId)) { Save(); } if (RemoveSlotsNoSave(assetId)) { SaveSlots(); } if (RemoveCustomColorNoSave(assetId)) { SaveCustom(); } if (RemoveCustomSlotsNoSave(assetId)) { SaveCustomSlots(); } if (RemoveSlotAnimationsNoSave(assetId)) { SaveSlotAnimations(); } } internal static bool TryGetAnimation(string assetId, out ColorAnimation spec) { if (assetId != null && _animations.TryGetValue(assetId, out spec)) { return true; } spec = null; return false; } internal static bool HasAnimation(string? assetId) { if (assetId != null) { return _animations.ContainsKey(assetId); } return false; } internal static IReadOnlyDictionary GetAllAnimations() { return _animations; } internal static IReadOnlyDictionary> GetAllSlotAnimations() { return _slotAnimations; } internal static bool RemoveAnimationNoSave(string assetId) { return _animations.Remove(assetId); } internal static void ClearAnimationForAsset(string assetId) { if (_animations.Remove(assetId)) { SaveAnimations(); } } internal static bool ClearAllAnimationForAsset(string assetId) { bool flag = RemoveAnimationNoSave(assetId); bool flag2 = RemoveSlotAnimationsNoSave(assetId); if (flag) { SaveAnimations(); } if (flag2) { SaveSlotAnimations(); } return flag || flag2; } internal static void ClearAllAnimationsNoSave() { _animations.Clear(); _slotAnimations.Clear(); } internal static void SetSlotAnimation(string assetId, int slot, ColorAnimation spec) { if (!_slotAnimations.TryGetValue(assetId, out Dictionary value)) { value = (_slotAnimations[assetId] = new Dictionary()); } value[slot] = spec; SaveSlotAnimations(); if (RemoveSlotColorNoSave(assetId, slot)) { SaveSlots(); } if (RemoveCustomSlotNoSave(assetId, slot)) { SaveCustomSlots(); } } internal static bool TryGetSlotAnimation(string assetId, int slot, out ColorAnimation spec) { spec = null; if (_slotAnimations.TryGetValue(assetId, out Dictionary value)) { return value.TryGetValue(slot, out spec); } return false; } internal static bool HasAnySlotAnimation(string? assetId) { if (assetId != null && _slotAnimations.TryGetValue(assetId, out Dictionary value)) { return value.Count > 0; } return false; } internal static IReadOnlyDictionary? GetSlotAnimations(string assetId) { if (!_slotAnimations.TryGetValue(assetId, out Dictionary value)) { return null; } return value; } internal static bool RemoveSlotAnimationsNoSave(string assetId) { return _slotAnimations.Remove(assetId); } internal static bool RemoveSlotAnimationNoSave(string assetId, int slot) { if (_slotAnimations.TryGetValue(assetId, out Dictionary value)) { return value.Remove(slot); } return false; } internal static void ClearSlotAnimationForAsset(string assetId, int slot) { if (RemoveSlotAnimationNoSave(assetId, slot)) { SaveSlotAnimations(); } } internal static bool IsSlotAnimated(string? assetId, int slot) { if (assetId == null) { return false; } if (slot >= 0 && TryGetSlotAnimation(assetId, slot, out ColorAnimation _)) { return true; } if (slot < 0) { return HasAnimation(assetId); } return false; } internal static AnimSet GetAnimSet(string assetId) { _animations.TryGetValue(assetId, out ColorAnimation value); Dictionary value2; Dictionary perSlot = ((_slotAnimations.TryGetValue(assetId, out value2) && value2.Count > 0) ? value2 : null); HashSet into = null; if (value != null) { CollectKeys(ref into, _slotColors, assetId); CollectKeys(ref into, _customSlotColors, assetId); } return new AnimSet(value, perSlot, into); } private static void CollectKeys(ref HashSet? into, Dictionary> store, string assetId) { if (!store.TryGetValue(assetId, out Dictionary value) || value.Count == 0) { return; } if (into == null) { into = new HashSet(); } foreach (int key in value.Keys) { into.Add(key); } } internal static void LoadAnimations() { try { if (File.Exists(AnimSavePath)) { Dictionary dictionary = JsonConvert.DeserializeObject>(File.ReadAllText(AnimSavePath)); if (dictionary != null) { _animations = dictionary; } } } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: animations load failed: " + ex.Message); } try { if (File.Exists(SlotAnimSavePath)) { Dictionary> dictionary2 = JsonConvert.DeserializeObject>>(File.ReadAllText(SlotAnimSavePath)); if (dictionary2 != null) { _slotAnimations = dictionary2; } } } catch (Exception ex2) { BceConsole.LogWarning("PerCosmeticColors: slot animations load failed: " + ex2.Message); } } internal static void SaveAnimations() { Save(); } internal static void SaveSlotAnimations() { Save(); } internal static void Set(string assetId, int colorIndex) { _colors[assetId] = colorIndex; Save(); if (RemoveCustomColorNoSave(assetId)) { SaveCustom(); } } internal static void SetNoSave(string assetId, int colorIndex) { _colors[assetId] = colorIndex; } internal static bool HasOverride(string assetId) { return _colors.ContainsKey(assetId); } internal static bool RemoveColorNoSave(string assetId) { return _colors.Remove(assetId); } internal static void ClearForAsset(string assetId) { bool flag = _colors.Remove(assetId); bool flag2 = RemoveSlotsNoSave(assetId); bool flag3 = RemoveAnimationNoSave(assetId); bool flag4 = RemoveCustomColorNoSave(assetId); bool flag5 = RemoveCustomSlotsNoSave(assetId); bool flag6 = RemoveSlotAnimationsNoSave(assetId); if (flag) { Save(); } if (flag2) { SaveSlots(); } if (flag3) { SaveAnimations(); } if (flag4) { SaveCustom(); } if (flag5) { SaveCustomSlots(); } if (flag6) { SaveSlotAnimations(); } } internal static void ClearAll() { bool flag = _colors.Count > 0 || _slotColors.Count > 0 || _animations.Count > 0 || _customColors.Count > 0 || _customSlotColors.Count > 0 || _slotAnimations.Count > 0; _colors.Clear(); ClearAllSlotsNoSave(); ClearAllAnimationsNoSave(); _customColors.Clear(); _customSlotColors.Clear(); if (flag) { Save(); SaveSlots(); SaveAnimations(); SaveSlotAnimations(); SaveCustom(); SaveCustomSlots(); } } internal static IReadOnlyDictionary GetAll() { return _colors; } internal static void SetOriginalColor(string assetId) { _colors[assetId] = -1; bool flag = RemoveSlotsNoSave(assetId); Save(); if (flag) { SaveSlots(); } if (RemoveCustomColorNoSave(assetId)) { SaveCustom(); } if (RemoveCustomSlotsNoSave(assetId)) { SaveCustomSlots(); } if (RemoveAnimationNoSave(assetId)) { SaveAnimations(); } if (RemoveSlotAnimationsNoSave(assetId)) { SaveSlotAnimations(); } } internal static bool IsOriginalMode(string? assetId) { if (assetId != null && _colors.TryGetValue(assetId, out var value)) { return value == -1; } return false; } internal static bool TryGetColor(string assetId, out int colorIndex) { return _colors.TryGetValue(assetId, out colorIndex); } internal static int GetRealTypeColor(int typeIdx, int[] colorsEquipped) { if (_savedTypeIndex != typeIdx) { return colorsEquipped[typeIdx]; } return _savedTypeColor; } internal static int GetEffectiveColorIndex(string assetId, int fallbackTypeColor) { if (FeatureEnabled && _colors.TryGetValue(assetId, out var value) && value != -1) { return value; } return fallbackTypeColor; } internal static void ApplyVanillaOverridesTo(IEnumerable playerMaterials) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected I4, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) if (!FeatureEnabled || playerMaterials == null || (_colors.Count <= 0 && _customColors.Count <= 0 && (!_presetPreviewActive || (_previewOverrides.Count <= 0 && _previewCustom.Count <= 0)))) { return; } foreach (PlayerMaterial playerMaterial in playerMaterials) { if ((Object)(object)playerMaterial == (Object)null) { continue; } if ((Object)(object)playerMaterial.cosmetic == (Object)null) { if (!Plugin.EnableVanillaCustomColors.Value) { continue; } string key = VanillaTintHelper.BaseMeshAssetId((int)playerMaterial.cosmeticType); Color value2; if (_presetPreviewActive) { if (_previewCustom.TryGetValue(key, out var value)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value); } } else if (_customColors.TryGetValue(key, out value2)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value2); } continue; } CosmeticAsset cosmeticAsset = playerMaterial.cosmetic.cosmeticAsset; if (cosmeticAsset == null || BridgeIds.IsBridgeAsset(cosmeticAsset)) { continue; } string assetId = cosmeticAsset.assetId; Color value5; int value6; if (_presetPreviewActive) { int value4; if (_previewCustom.TryGetValue(assetId, out var value3)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value3); } else if (_previewOverrides.TryGetValue(assetId, out value4) && value4 != -1) { playerMaterial.ColorSet(PropAlbedo, PropEmission, PropFresnel, value4); } } else if (_customColors.TryGetValue(assetId, out value5)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value5); } else if (_colors.TryGetValue(assetId, out value6) && value6 != -1) { playerMaterial.ColorSet(PropAlbedo, PropEmission, PropFresnel, value6); } } } internal static bool ApplyLocalToBridgeTint(BridgeTintMaterial btm, string assetId) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (!FeatureEnabled) { return false; } Material[]? materials = btm.materials; int num = ((materials != null) ? materials.Length : 0); bool result = false; for (int i = 0; i < num; i++) { int slot = btm.SlotIdOf(i); Color color; Color? slotCustom = (TryGetCustomSlotColor(assetId, slot, out color) ? new Color?(color) : ((Color?)null)); int colorIndex; int? slotIndex = (TryGetSlotColor(assetId, slot, out colorIndex) ? new int?(colorIndex) : ((int?)null)); Color value; Color? wholeCustom = (_customColors.TryGetValue(assetId, out value) ? new Color?(value) : ((Color?)null)); int value2; int? wholeIndex = (_colors.TryGetValue(assetId, out value2) ? new int?(value2) : ((int?)null)); if (ApplySlotPrecedence(btm, i, slotCustom, slotIndex, wholeCustom, wholeIndex)) { result = true; } } return result; } internal static int[]? BuildCompatibilitySyncColors(MetaManager? meta) { //IL_00e1: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected I4, but got Unknown if (!FeatureEnabled) { return null; } if (meta?.cosmeticEquipped == null || meta.colorsEquipped == null) { return null; } Dictionary dictionary = new Dictionary(); Dictionary dictionary2 = new Dictionary(); foreach (int item in meta.cosmeticEquipped) { if (item < 0 || item >= meta.cosmeticAssets.Count) { continue; } CosmeticAsset val = meta.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && !BridgeIds.IsBridgeAsset(val)) { if (BridgeIds.IsModdedCosmetic(val)) { dictionary2.TryAdd(val.type, val); } else { dictionary.TryAdd(val.type, val); } } } int[] array = null; bool flag = false; HashSet hashSet = new HashSet(dictionary.Keys); foreach (CosmeticType key in dictionary2.Keys) { hashSet.Add(key); } foreach (CosmeticType item2 in hashSet) { CosmeticAsset value; CosmeticAsset val2 = (dictionary.TryGetValue(item2, out value) ? value : dictionary2[item2]); int num = (int)val2.type; if (num >= 0 && num < meta.colorsEquipped.Length && _colors.TryGetValue(val2.assetId, out var value2) && value2 != -1 && meta.colorsEquipped[num] != value2) { if (array == null) { array = (int[])meta.colorsEquipped.Clone(); } array[num] = value2; flag = true; } } if (!flag) { return null; } return array; } internal static void ApplyOverrides(PlayerCosmetics pc) { //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_05b2: Unknown result type (might be due to invalid IL or missing references) //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) if (!FeatureEnabled) { return; } bool flag = _colors.Count > 0; bool flag2 = _slotColors.Count > 0; bool flag3 = _customColors.Count > 0 || _customSlotColors.Count > 0; bool flag4 = _presetPreviewActive || _previewOverrides.Count > 0 || _previewCustom.Count > 0 || _previewSlotOverrides.Count > 0 || _previewSlotCustom.Count > 0; if ((!flag && !flag2 && !flag4 && !flag3) || pc?.playerMaterials == null) { return; } PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null) { return; } if (!playerAvatarVisuals.isMenuAvatar) { PlayerAvatar playerAvatar = playerAvatarVisuals.playerAvatar; if (playerAvatar == null || !playerAvatar.isLocal) { return; } } if (AvatarIdentity.IsRemoteMini(pc)) { return; } if (!MiniPresetContextActive) { int num = MiniSemibotSpawner.PresetSlotOf(pc); if (num >= 0) { RunWithPresetContext(num, delegate { ApplyOverrides(pc); }); return; } } foreach (PlayerMaterial playerMaterial in pc.playerMaterials) { if ((Object)(object)playerMaterial == (Object)null) { continue; } if ((Object)(object)playerMaterial.cosmetic == (Object)null) { ApplyBaseMeshColor(playerMaterial, pc.colorsEquipped); } else { if ((Object)(object)playerMaterial.cosmetic.cosmeticAsset == (Object)null) { continue; } string assetId = playerMaterial.cosmetic.cosmeticAsset.assetId; bool effectiveCustomColors = CustomizerStore.GetEffectiveCustomColors(playerMaterial.cosmetic.cosmeticAsset); Color value3; int value4; if (_presetPreviewActive) { int value2; if (_previewCustom.TryGetValue(assetId, out var value)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value); } else if (_previewOverrides.TryGetValue(assetId, out value2) && value2 != -1) { playerMaterial.ColorSet(PropAlbedo, PropEmission, PropFresnel, value2); } } else if (effectiveCustomColors && _customColors.TryGetValue(assetId, out value3)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value3); } else if (_colors.TryGetValue(assetId, out value4)) { if (value4 != -1) { playerMaterial.ColorSet(PropAlbedo, PropEmission, PropFresnel, value4); } } else if (_previewOverrides.TryGetValue(assetId, out value4)) { if (value4 != -1) { playerMaterial.ColorSet(PropAlbedo, PropEmission, PropFresnel, value4); } } else if (!BridgeIds.IsBridgeAsset(playerMaterial.cosmetic.cosmeticAsset)) { VanillaTintHelper.RepaintPalette(playerMaterial, pc); } } } BridgeTintMaterial[] componentsInChildren = ((Component)playerAvatarVisuals).GetComponentsInChildren(true); BridgeTintMaterial[] array = componentsInChildren; foreach (BridgeTintMaterial bridgeTintMaterial in array) { if ((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset == (Object)null) { continue; } string assetId2 = bridgeTintMaterial.cosmetic.cosmeticAsset.assetId; bridgeTintMaterial.EnsureSetup(); if (_presetPreviewActive) { if (!HasPreviewEntry(assetId2)) { if (HasAnimation(assetId2) || HasAnySlotAnimation(assetId2)) { Material[]? materials = bridgeTintMaterial.materials; int num3 = ((materials != null) ? materials.Length : 0); for (int num4 = 0; num4 < num3; num4++) { int slot = bridgeTintMaterial.SlotIdOf(num4); Color color; Color? slotCustom = (TryGetCustomSlotColor(assetId2, slot, out color) ? new Color?(color) : ((Color?)null)); int colorIndex; int? slotIndex = (TryGetSlotColor(assetId2, slot, out colorIndex) ? new int?(colorIndex) : ((int?)null)); Color value5; Color? wholeCustom = (_customColors.TryGetValue(assetId2, out value5) ? new Color?(value5) : ((Color?)null)); int value6; int? wholeIndex = (_colors.TryGetValue(assetId2, out value6) ? new int?(value6) : ((int?)null)); ApplySlotPrecedence(bridgeTintMaterial, num4, slotCustom, slotIndex, wholeCustom, wholeIndex); } } else { bridgeTintMaterial.RestoreOriginalColor(); } } else { Material[]? materials2 = bridgeTintMaterial.materials; int num5 = ((materials2 != null) ? materials2.Length : 0); for (int num6 = 0; num6 < num5; num6++) { int slot2 = bridgeTintMaterial.SlotIdOf(num6); Color color2; Color? slotCustom2 = (TryGetPreviewSlotCustom(assetId2, slot2, out color2) ? new Color?(color2) : ((Color?)null)); int colorIndex2; int? slotIndex2 = (TryGetPreviewSlotOverride(assetId2, slot2, out colorIndex2) ? new int?(colorIndex2) : ((int?)null)); Color value7; Color? wholeCustom2 = (_previewCustom.TryGetValue(assetId2, out value7) ? new Color?(value7) : ((Color?)null)); int value8; int? wholeIndex2 = (_previewOverrides.TryGetValue(assetId2, out value8) ? new int?(value8) : ((int?)null)); ApplySlotPrecedence(bridgeTintMaterial, num6, slotCustom2, slotIndex2, wholeCustom2, wholeIndex2); } } } else { bool effectiveCustomColors2 = CustomizerStore.GetEffectiveCustomColors(bridgeTintMaterial.cosmetic.cosmeticAsset); Material[]? materials3 = bridgeTintMaterial.materials; int num7 = ((materials3 != null) ? materials3.Length : 0); for (int num8 = 0; num8 < num7; num8++) { int slot3 = bridgeTintMaterial.SlotIdOf(num8); Color color3; Color? slotCustom3 = ((effectiveCustomColors2 && TryGetCustomSlotColor(assetId2, slot3, out color3)) ? new Color?(color3) : ((Color?)null)); int colorIndex3; int? slotIndex3 = (TryGetSlotColor(assetId2, slot3, out colorIndex3) ? new int?(colorIndex3) : ((int?)null)); Color value9; Color? wholeCustom3 = ((effectiveCustomColors2 && _customColors.TryGetValue(assetId2, out value9)) ? new Color?(value9) : ((Color?)null)); int value10; int value11; int? wholeIndex3 = (_colors.TryGetValue(assetId2, out value10) ? new int?(value10) : (_previewOverrides.TryGetValue(assetId2, out value11) ? new int?(value11) : ((int?)null))); ApplySlotPrecedence(bridgeTintMaterial, num8, slotCustom3, slotIndex3, wholeCustom3, wholeIndex3); } } } } private static void ApplySlotIndex(BridgeTintMaterial btm, int localSlot, int colorIndex) { if (colorIndex == -1) { btm.RestoreOriginalColorInSlot(localSlot); } else { btm.ApplyColorToSlot(localSlot, colorIndex); } } internal static bool ApplySlotPrecedence(BridgeTintMaterial btm, int localSlot, Color? slotCustom, int? slotIndex, Color? wholeCustom, int? wholeIndex) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (slotCustom.HasValue) { btm.ApplyColorRGBToSlot(localSlot, slotCustom.Value); return true; } if (slotIndex.HasValue) { ApplySlotIndex(btm, localSlot, slotIndex.Value); return true; } if (wholeCustom.HasValue) { btm.ApplyColorRGBToSlot(localSlot, wholeCustom.Value); return true; } if (wholeIndex.HasValue) { ApplySlotIndex(btm, localSlot, wholeIndex.Value); return true; } return false; } internal static void ApplyBaseMeshColor(PlayerMaterial pm, int[]? colorsEquipped) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected I4, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.EnableVanillaCustomColors.Value || (Object)(object)pm == (Object)null || (Object)(object)pm.cosmetic != (Object)null || !pm.tintable) { return; } int num = (int)pm.cosmeticType; string key = VanillaTintHelper.BaseMeshAssetId(num); Color value2; if (_presetPreviewActive) { if (_previewCustom.TryGetValue(key, out var value)) { VanillaTintHelper.ApplyCustomRGB(pm, value); return; } } else if (_customColors.TryGetValue(key, out value2)) { VanillaTintHelper.ApplyCustomRGB(pm, value2); return; } if (colorsEquipped != null && num >= 0 && num < colorsEquipped.Length) { int num2 = colorsEquipped[num]; if (num2 >= 0 && MetaManager.instance?.colors != null && num2 < MetaManager.instance.colors.Count) { pm.ColorSet(PropAlbedo, PropEmission, PropFresnel, num2); } } } internal static bool ClearAllBaseMeshCustomColorsNoSave() { List list = null; foreach (string key in _customColors.Keys) { if (VanillaTintHelper.IsBaseMeshId(key)) { (list ?? (list = new List())).Add(key); } } if (list == null) { return false; } foreach (string item in list) { _customColors.Remove(item); } return true; } internal static bool IsLocalDeathHeadPc(PlayerCosmetics? pc) { if ((Object)(object)pc?.deathHead != (Object)null && pc.deathHead.setup) { PlayerAvatar playerAvatar = pc.deathHead.playerAvatar; if (playerAvatar == null) { return false; } PhotonView photonView = playerAvatar.photonView; return ((photonView != null) ? new bool?(photonView.IsMine) : ((bool?)null)) == true; } return false; } internal static void Load() { bool flag = false; try { if (!File.Exists(SavePath) && File.Exists(LegacyPath)) { try { File.Move(LegacyPath, SavePath); BceConsole.LogInfo("PerCosmeticColors: migrated save file to BepInEx/config", ConsoleColor.Blue); } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: migration failed: " + ex.Message); } } if (File.Exists(SavePath)) { string text = File.ReadAllText(SavePath); if (text.Contains("\"Version\"")) { ColorStoreData colorStoreData = JsonConvert.DeserializeObject(text); if (colorStoreData != null) { _colors = colorStoreData.Colors ?? new Dictionary(); _slotColors = colorStoreData.Slots ?? new Dictionary>(); _animations = colorStoreData.Animations ?? new Dictionary(); _slotAnimations = colorStoreData.SlotAnimations ?? new Dictionary>(); SetCustomFromDto(colorStoreData.Custom); SetCustomSlotsFromDto(colorStoreData.CustomSlots); } } else { _colors = JsonConvert.DeserializeObject>(text) ?? new Dictionary(); flag = true; } } else { flag = true; } } catch (Exception ex2) { BceConsole.LogWarning("PerCosmeticColors: load failed: " + ex2.Message); _colors = new Dictionary(); } if (flag) { LoadSlots(); LoadAnimations(); LoadCustom(); if (_colors.Count > 0 || _slotColors.Count > 0 || _animations.Count > 0 || _slotAnimations.Count > 0 || HasAnyCustomData()) { Save(); } } LoadPresets(); } internal static void Save() { StoreVersion++; ColorStoreData colorStoreData = new ColorStoreData { Colors = _colors, Slots = _slotColors, Animations = _animations, SlotAnimations = _slotAnimations, Custom = CustomToDto(), CustomSlots = CustomSlotsToDto() }; string json = JsonConvert.SerializeObject((object)colorStoreData); _lastWrite = AtomicJson.QueueWrite(_lastWrite, SavePath, json, "PerCosmeticColors: save failed"); } internal static void FlushPendingWrites() { try { Task.WaitAll(new Task[2] { _lastWrite, _lastPresetWrite }, TimeSpan.FromSeconds(2.0)); } catch { } } internal static bool HasCustomColor(string? assetId) { if (assetId != null) { return _customColors.ContainsKey(assetId); } return false; } internal static bool TryGetCustomColor(string assetId, out Color color) { return _customColors.TryGetValue(assetId, out color); } internal static void SetCustomColor(string assetId, Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _customColors[assetId] = color; bool flag = _colors.Remove(assetId); bool flag2 = RemoveSlotsNoSave(assetId); bool flag3 = RemoveAnimationNoSave(assetId); bool flag4 = RemoveSlotAnimationsNoSave(assetId); bool flag5 = RemoveCustomSlotsNoSave(assetId); SaveCustom(); if (flag) { Save(); } if (flag2) { SaveSlots(); } if (flag3) { SaveAnimations(); } if (flag4) { SaveSlotAnimations(); } if (flag5) { SaveCustomSlots(); } } internal static bool RemoveCustomColorNoSave(string assetId) { return _customColors.Remove(assetId); } internal static void SetCustomColorNoSave(string assetId, Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _customColors[assetId] = color; _colors.Remove(assetId); RemoveSlotsNoSave(assetId); RemoveAnimationNoSave(assetId); RemoveSlotAnimationsNoSave(assetId); RemoveCustomSlotsNoSave(assetId); } internal static IReadOnlyDictionary GetAllCustom() { return _customColors; } internal static IReadOnlyDictionary> GetAllCustomSlots() { return _customSlotColors; } internal static bool IsSlotCustom(string? assetId, int slot) { if (assetId == null) { return false; } if (slot >= 0) { if (TryGetCustomSlotColor(assetId, slot, out var _)) { return true; } if (TryGetSlotColor(assetId, slot, out var _)) { return false; } } return HasCustomColor(assetId); } internal static bool TryGetSlotCustom(string assetId, int slot, out Color color) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (slot >= 0 && TryGetCustomSlotColor(assetId, slot, out color)) { return true; } if (slot >= 0 && TryGetSlotColor(assetId, slot, out var _)) { color = default(Color); return false; } return TryGetCustomColor(assetId, out color); } internal static bool TryGetCustomSlotColor(string assetId, int slot, out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) color = default(Color); if (_customSlotColors.TryGetValue(assetId, out Dictionary value)) { return value.TryGetValue(slot, out color); } return false; } internal static bool HasAnyCustomSlotColor(string? assetId) { if (assetId != null && _customSlotColors.TryGetValue(assetId, out Dictionary value)) { return value.Count > 0; } return false; } internal static void SetCustomSlotColor(string assetId, int slot, Color color) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!_customSlotColors.TryGetValue(assetId, out Dictionary value)) { value = (_customSlotColors[assetId] = new Dictionary()); } value[slot] = color; SaveCustomSlots(); if (_slotColors.TryGetValue(assetId, out Dictionary value2) && value2.Remove(slot)) { SaveSlots(); } if (RemoveSlotAnimationNoSave(assetId, slot)) { SaveSlotAnimations(); } } internal static bool RemoveCustomSlotsNoSave(string assetId) { return _customSlotColors.Remove(assetId); } internal static bool RemoveCustomSlotNoSave(string assetId, int slot) { if (_customSlotColors.TryGetValue(assetId, out Dictionary value)) { return value.Remove(slot); } return false; } internal static void LoadCustom() { LoadWholeCustom(); LoadCustomSlots(); } private static void LoadCustomSlots() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) try { if (!File.Exists(CustomSlotSavePath)) { return; } Dictionary> dictionary = JsonConvert.DeserializeObject>>(File.ReadAllText(CustomSlotSavePath)); if (dictionary == null) { return; } _customSlotColors = new Dictionary>(); foreach (KeyValuePair> item in dictionary) { Dictionary dictionary2 = new Dictionary(); foreach (KeyValuePair item2 in item.Value) { float[] value = item2.Value; if (value != null && value.Length >= 3) { dictionary2[item2.Key] = new Color(item2.Value[0], item2.Value[1], item2.Value[2]); } } _customSlotColors[item.Key] = dictionary2; } } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: custom slot colours load failed: " + ex.Message); } } internal static void SaveCustomSlots() { Save(); } internal static Dictionary CustomToDto() { //IL_0037: 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_0055: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(_customColors.Count); foreach (KeyValuePair customColor in _customColors) { dictionary[customColor.Key] = new float[3] { customColor.Value.r, customColor.Value.g, customColor.Value.b }; } return dictionary; } internal static Dictionary> CustomSlotsToDto() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) Dictionary> dictionary = new Dictionary>(_customSlotColors.Count); foreach (KeyValuePair> customSlotColor in _customSlotColors) { Dictionary dictionary2 = new Dictionary(); foreach (KeyValuePair item in customSlotColor.Value) { dictionary2[item.Key] = new float[3] { item.Value.r, item.Value.g, item.Value.b }; } dictionary[customSlotColor.Key] = dictionary2; } return dictionary; } internal static void SetCustomFromDto(Dictionary? dto) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) _customColors = new Dictionary(); if (dto == null) { return; } foreach (KeyValuePair item in dto) { float[] value = item.Value; if (value != null && value.Length >= 3) { _customColors[item.Key] = new Color(item.Value[0], item.Value[1], item.Value[2]); } } } internal static void SetCustomSlotsFromDto(Dictionary>? dto) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) _customSlotColors = new Dictionary>(); if (dto == null) { return; } foreach (KeyValuePair> item in dto) { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair item2 in item.Value) { float[] value = item2.Value; if (value != null && value.Length >= 3) { dictionary[item2.Key] = new Color(item2.Value[0], item2.Value[1], item2.Value[2]); } } _customSlotColors[item.Key] = dictionary; } } internal static bool HasAnyCustomData() { if (_customColors.Count <= 0) { return _customSlotColors.Count > 0; } return true; } private static void LoadWholeCustom() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) try { if (!File.Exists(CustomSavePath)) { return; } Dictionary dictionary = JsonConvert.DeserializeObject>(File.ReadAllText(CustomSavePath)); if (dictionary == null) { return; } _customColors = new Dictionary(); foreach (KeyValuePair item in dictionary) { float[] value = item.Value; if (value != null && value.Length >= 3) { _customColors[item.Key] = new Color(item.Value[0], item.Value[1], item.Value[2]); } } } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: custom colours load failed: " + ex.Message); } } internal static void SaveCustom() { Save(); } internal static void SetPresetPreviewActive(bool value) { _presetPreviewActive = value; } internal static void NotifyPresetHoverStart(int presetIndex) { _pendingHoverPresetIndex = presetIndex; } internal static int GetPendingHoverPresetIndex() { return _pendingHoverPresetIndex; } private static float[] Rgb(Color c) { //IL_0008: 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_001a: Unknown result type (might be due to invalid IL or missing references) return new float[3] { c.r, c.g, c.b }; } private static Color FromRgb(float[] a) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) return new Color(a[0], a[1], a[2]); } internal static void SavePreset(int presetIndex, IList cosmeticIndices) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } Dictionary dictionary = new Dictionary(); foreach (int cosmeticIndex in cosmeticIndices) { if (cosmeticIndex < 0 || cosmeticIndex >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = instance.cosmeticAssets[cosmeticIndex]; if ((Object)(object)val == (Object)null) { continue; } string assetId = val.assetId; PresetColorEntry presetColorEntry = new PresetColorEntry(); bool flag = false; if (_colors.TryGetValue(assetId, out var value)) { presetColorEntry.Index = value; flag = true; } if (_customColors.TryGetValue(assetId, out var value2)) { presetColorEntry.Custom = Rgb(value2); flag = true; } if (_slotColors.TryGetValue(assetId, out Dictionary value3) && value3.Count > 0) { presetColorEntry.SlotIndex = new Dictionary(value3); flag = true; } if (_customSlotColors.TryGetValue(assetId, out Dictionary value4) && value4.Count > 0) { presetColorEntry.SlotCustom = new Dictionary(); foreach (KeyValuePair item in value4) { presetColorEntry.SlotCustom[item.Key] = Rgb(item.Value); } flag = true; } if (_animations.TryGetValue(assetId, out ColorAnimation value5)) { presetColorEntry.Anim = value5; flag = true; } IReadOnlyDictionary slotAnimations = GetSlotAnimations(assetId); if (slotAnimations != null && slotAnimations.Count > 0) { presetColorEntry.SlotAnim = new Dictionary(); foreach (KeyValuePair item2 in slotAnimations) { presetColorEntry.SlotAnim[item2.Key] = item2.Value; } flag = true; } if (flag) { dictionary[assetId] = presetColorEntry; } } if (Plugin.EnableVanillaCustomColors.Value) { foreach (KeyValuePair customColor in _customColors) { if (VanillaTintHelper.IsBaseMeshId(customColor.Key) && !dictionary.ContainsKey(customColor.Key)) { dictionary[customColor.Key] = new PresetColorEntry { Custom = Rgb(customColor.Value) }; } } } if (dictionary.Count > 0) { _presetColors[presetIndex] = dictionary; } else { _presetColors.Remove(presetIndex); } SavePresets(); } internal static IReadOnlyDictionary? GetPresetColors(int presetIndex) { if (!_presetColors.TryGetValue(presetIndex, out Dictionary value)) { return null; } return value; } internal static (string colorData, string animData, string customData, string slotAnimData) SerializePresetForBroadcast(int presetIndex) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) IReadOnlyDictionary presetColors = GetPresetColors(presetIndex); if (presetColors == null) { return (colorData: "", animData: "", customData: "", slotAnimData: ""); } Dictionary dictionary = new Dictionary(); Dictionary> dictionary2 = new Dictionary>(); Dictionary dictionary3 = new Dictionary(); Dictionary> dictionary4 = new Dictionary>(); Dictionary dictionary5 = new Dictionary(); Dictionary> dictionary6 = new Dictionary>(); foreach (KeyValuePair item5 in presetColors) { string key = item5.Key; PresetColorEntry value = item5.Value; if (value == null) { continue; } float[] custom = value.Custom; if (custom != null && custom.Length >= 3) { dictionary3[key] = new Color(value.Custom[0], value.Custom[1], value.Custom[2]); } else if (value.Index.HasValue) { dictionary[key] = value.Index.Value; } Dictionary slotIndex = value.SlotIndex; if (slotIndex != null && slotIndex.Count > 0) { dictionary2[key] = new Dictionary(value.SlotIndex); } Dictionary slotCustom = value.SlotCustom; if (slotCustom != null && slotCustom.Count > 0) { Dictionary dictionary7 = new Dictionary(); foreach (KeyValuePair item6 in value.SlotCustom) { custom = item6.Value; if (custom != null && custom.Length >= 3) { dictionary7[item6.Key] = new Color(item6.Value[0], item6.Value[1], item6.Value[2]); } } if (dictionary7.Count > 0) { dictionary4[key] = dictionary7; } } if (value.Anim != null) { dictionary5[key] = value.Anim; } Dictionary slotAnim = value.SlotAnim; if (slotAnim != null && slotAnim.Count > 0) { dictionary6[key] = new Dictionary(value.SlotAnim); } } string item = ((dictionary.Count > 0 || dictionary2.Count > 0) ? PerCosmeticColorSerializer.SerializeWithSlots(dictionary, dictionary2) : ""); string item2 = ((Plugin.EnableBridgeColorAnimations.Value && dictionary5.Count > 0) ? PerCosmeticColorSerializer.SerializeAnimations(dictionary5) : ""); string item3 = ((Plugin.EnableBridgeCustomColors.Value && (dictionary3.Count > 0 || dictionary4.Count > 0)) ? PerCosmeticColorSerializer.SerializeCustomColors(dictionary3, dictionary4) : ""); string item4 = ((Plugin.EnableBridgeColorAnimations.Value && dictionary6.Count > 0) ? PerCosmeticColorSerializer.SerializeSlotAnimations(dictionary6) : ""); return (colorData: item, animData: item2, customData: item3, slotAnimData: item4); } internal static void DeletePresetColors(int presetIndex) { if (_presetColors.Remove(presetIndex)) { SavePresets(); } } internal static void ClearAllForType(CosmeticType type, MetaManager meta) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected I4, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; bool flag6 = false; foreach (int item in meta.cosmeticEquipped) { if (item >= 0 && item < meta.cosmeticAssets.Count) { CosmeticAsset val = meta.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && val.type == type) { string assetId = val.assetId; flag |= _colors.Remove(assetId); flag2 |= RemoveSlotsNoSave(assetId); flag3 |= RemoveCustomColorNoSave(assetId); flag4 |= RemoveCustomSlotsNoSave(assetId); flag5 |= RemoveAnimationNoSave(assetId); flag6 |= RemoveSlotAnimationsNoSave(assetId); } } } string assetId2 = VanillaTintHelper.BaseMeshAssetId((int)type); flag3 |= RemoveCustomColorNoSave(assetId2); if (flag) { Save(); } if (flag2) { SaveSlots(); } if (flag3) { SaveCustom(); } if (flag4) { SaveCustomSlots(); } if (flag6) { SaveSlotAnimations(); } if (flag5) { SaveAnimations(); } } internal static void RestorePreset(int presetIndex) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (!_presetColors.TryGetValue(presetIndex, out Dictionary value)) { return; } foreach (KeyValuePair item in value) { string key = item.Key; PresetColorEntry value2 = item.Value; if (value2.Index.HasValue) { _colors[key] = value2.Index.Value; } float[] custom = value2.Custom; if (custom != null && custom.Length >= 3) { _customColors[key] = FromRgb(value2.Custom); } Dictionary slotIndex = value2.SlotIndex; if (slotIndex != null && slotIndex.Count > 0) { _slotColors[key] = new Dictionary(value2.SlotIndex); } Dictionary slotCustom = value2.SlotCustom; if (slotCustom != null && slotCustom.Count > 0) { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair item2 in value2.SlotCustom) { custom = item2.Value; if (custom != null && custom.Length >= 3) { dictionary[item2.Key] = FromRgb(item2.Value); } } _customSlotColors[key] = dictionary; } if (value2.Anim != null) { _animations[key] = value2.Anim; } Dictionary slotAnim = value2.SlotAnim; if (slotAnim == null || slotAnim.Count <= 0) { continue; } Dictionary dictionary2 = new Dictionary(); foreach (KeyValuePair item3 in value2.SlotAnim) { dictionary2[item3.Key] = item3.Value; } _slotAnimations[key] = dictionary2; } Save(); SaveSlots(); SaveCustom(); SaveCustomSlots(); SaveAnimations(); SaveSlotAnimations(); } internal static bool PresetMatchesCurrent(int presetIndex) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return true; } if (presetIndex < 0 || presetIndex >= instance.cosmeticPresets.Count) { return true; } IReadOnlyDictionary presetColors = GetPresetColors(presetIndex); foreach (int item in instance.cosmeticPresets[presetIndex]) { if (item < 0 || item >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null)) { PresetColorEntry value = null; presetColors?.TryGetValue(val.assetId, out value); if (!CurrentMatchesEntry(val.assetId, value)) { return false; } } } if (Plugin.EnableVanillaCustomColors.Value && presetColors != null) { foreach (KeyValuePair item2 in presetColors) { if (VanillaTintHelper.IsBaseMeshId(item2.Key) && !CurrentMatchesEntry(item2.Key, item2.Value)) { return false; } } foreach (KeyValuePair customColor in _customColors) { if (VanillaTintHelper.IsBaseMeshId(customColor.Key) && !presetColors.ContainsKey(customColor.Key)) { return false; } } } return true; } private static bool CurrentMatchesEntry(string id, PresetColorEntry? e) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) int value; bool flag = _colors.TryGetValue(id, out value); if (flag != e?.Index.HasValue) { return false; } if (flag && value != e.Index.Value) { return false; } Color value2; bool flag2 = _customColors.TryGetValue(id, out value2); float[] array = e?.Custom; bool flag3 = array != null && array.Length >= 3; if (flag2 != flag3) { return false; } if (flag2 && !ColorsApproxEqual(value2, FromRgb(e.Custom))) { return false; } if (SlotIndexMatches(id, e?.SlotIndex) && SlotCustomMatches(id, e?.SlotCustom) && AnimMatches(id, e?.Anim)) { return SlotAnimMatches(id, e?.SlotAnim); } return false; } private static bool SlotIndexMatches(string id, Dictionary? expected) { _slotColors.TryGetValue(id, out Dictionary value); if ((value?.Count ?? 0) != (expected?.Count ?? 0)) { return false; } if (value == null) { return true; } foreach (KeyValuePair item in value) { if (expected == null || !expected.TryGetValue(item.Key, out var value2) || value2 != item.Value) { return false; } } return true; } private static bool SlotCustomMatches(string id, Dictionary? expected) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) _customSlotColors.TryGetValue(id, out Dictionary value); if ((value?.Count ?? 0) != (expected?.Count ?? 0)) { return false; } if (value == null) { return true; } foreach (KeyValuePair item in value) { if (expected == null || !expected.TryGetValue(item.Key, out float[] value2) || value2 == null || value2.Length < 3) { return false; } if (!ColorsApproxEqual(item.Value, FromRgb(value2))) { return false; } } return true; } private static bool AnimMatches(string id, ColorAnimation? expected) { ColorAnimation value; bool flag = _animations.TryGetValue(id, out value); if (flag != (expected != null)) { return false; } if (flag) { return AnimEquals(value, expected); } return true; } private static bool SlotAnimMatches(string id, Dictionary? expected) { _slotAnimations.TryGetValue(id, out Dictionary value); if ((value?.Count ?? 0) != (expected?.Count ?? 0)) { return false; } if (value == null) { return true; } foreach (KeyValuePair item in value) { if (expected == null || !expected.TryGetValue(item.Key, out ColorAnimation value2) || !AnimEquals(item.Value, value2)) { return false; } } return true; } private static bool AnimEquals(ColorAnimation a, ColorAnimation b) { if (a.Mode != b.Mode || a.Dir != b.Dir) { return false; } if (Mathf.Abs(a.SecondsPerStep - b.SecondsPerStep) > 0.001f) { return false; } int num = a.Palette?.Count ?? 0; if (num != (b.Palette?.Count ?? 0)) { return false; } for (int i = 0; i < num; i++) { if (a.Palette[i] != b.Palette[i]) { return false; } } return true; } private static bool ColorsApproxEqual(Color a, Color b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Abs(a.r - b.r) < 0.004f && Mathf.Abs(a.g - b.g) < 0.004f) { return Mathf.Abs(a.b - b.b) < 0.004f; } return false; } internal static void LoadPresets() { try { if (!File.Exists(PresetSavePath)) { return; } string text = File.ReadAllText(PresetSavePath); try { _presetColors = JsonConvert.DeserializeObject>>(text) ?? new Dictionary>(); } catch { Dictionary> dictionary = JsonConvert.DeserializeObject>>(text); _presetColors = new Dictionary>(); if (dictionary == null) { return; } foreach (KeyValuePair> item in dictionary) { Dictionary dictionary2 = new Dictionary(); foreach (KeyValuePair item2 in item.Value) { dictionary2[item2.Key] = new PresetColorEntry { Index = item2.Value }; } _presetColors[item.Key] = dictionary2; } } } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: preset colors load failed: " + ex.Message); _presetColors = new Dictionary>(); } } private static void SavePresets() { string json = JsonConvert.SerializeObject((object)_presetColors); _lastPresetWrite = AtomicJson.QueueWrite(_lastPresetWrite, PresetSavePath, json, "PerCosmeticColors: preset colors save failed"); } internal static void TemporarilyShowForColorPage(CosmeticAsset asset) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected I4, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) _savedTypeIndex = -1; if ((Object)(object)MetaManager.instance == (Object)null) { return; } int num = (int)asset.type; if (num < 0 || num >= MetaManager.instance.colorsEquipped.Length) { return; } _savedTypeColor = MetaManager.instance.colorsEquipped[num]; _savedTypeIndex = num; if (!_colors.TryGetValue(asset.assetId, out var value)) { if (BridgeIds.IsBridgeAsset(asset)) { MetaManager.instance.colorsEquipped[num] = -1; } return; } MetaManager.instance.colorsEquipped[num] = value; foreach (int item in MetaManager.instance.cosmeticEquipped) { if (item >= 0 && item < MetaManager.instance.cosmeticAssets.Count) { CosmeticAsset val = MetaManager.instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && val.type == asset.type && !(val.assetId == asset.assetId) && !_colors.ContainsKey(val.assetId)) { _previewOverrides[val.assetId] = (BridgeIds.IsBridgeAsset(val) ? (-1) : _savedTypeColor); } } } } internal static void RestoreTypeColor() { if (_savedTypeIndex >= 0 && !((Object)(object)MetaManager.instance == (Object)null)) { if (_savedTypeIndex < MetaManager.instance.colorsEquipped.Length) { MetaManager.instance.colorsEquipped[_savedTypeIndex] = _savedTypeColor; } _savedTypeIndex = -1; _savedTypeColor = -1; ClearPreviewOverrides(); } } internal static void SetPreview(string assetId, int colorIndex) { _previewOverrides[assetId] = colorIndex; } internal static bool HasPreviewOverride(string assetId) { return _previewOverrides.ContainsKey(assetId); } internal static void ClearPreviewOverrides() { _previewOverrides.Clear(); _previewCustom.Clear(); _previewSlotOverrides.Clear(); _previewSlotCustom.Clear(); _previewAnimations.Clear(); _previewSlotAnimations.Clear(); _previewEntryExists.Clear(); _presetPreviewActive = false; } internal static void ClearPresetPreviewOnly() { _previewCustom.Clear(); _previewSlotOverrides.Clear(); _previewSlotCustom.Clear(); _previewAnimations.Clear(); _previewSlotAnimations.Clear(); _previewEntryExists.Clear(); _presetPreviewActive = false; } internal static bool HasPreviewEntry(string assetId) { return _previewEntryExists.Contains(assetId); } internal static bool TryGetPreviewSlotCustom(string assetId, int slot, out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) color = default(Color); if (_previewSlotCustom.TryGetValue(assetId, out Dictionary value)) { return value.TryGetValue(slot, out color); } return false; } internal static bool TryGetPreviewSlotOverride(string assetId, int slot, out int colorIndex) { colorIndex = 0; if (_previewSlotOverrides.TryGetValue(assetId, out Dictionary value)) { return value.TryGetValue(slot, out colorIndex); } return false; } internal static AnimSet GetPreviewAnimSet(string assetId) { if (!_previewEntryExists.Contains(assetId)) { return GetAnimSet(assetId); } _previewAnimations.TryGetValue(assetId, out ColorAnimation value); Dictionary value2; Dictionary perSlot = ((_previewSlotAnimations.TryGetValue(assetId, out value2) && value2.Count > 0) ? value2 : null); return new AnimSet(value, perSlot); } internal static void RunWithPresetContext(int slot, Action dress) { if (dress == null) { return; } Dictionary previewOverrides = _previewOverrides; Dictionary previewCustom = _previewCustom; Dictionary> previewSlotOverrides = _previewSlotOverrides; Dictionary> previewSlotCustom = _previewSlotCustom; Dictionary previewAnimations = _previewAnimations; Dictionary> previewSlotAnimations = _previewSlotAnimations; HashSet other = new HashSet(_previewEntryExists); bool presetPreviewActive = _presetPreviewActive; bool miniPresetContextActive = MiniPresetContextActive; _previewOverrides = new Dictionary(); _previewCustom = new Dictionary(); _previewSlotOverrides = new Dictionary>(); _previewSlotCustom = new Dictionary>(); _previewAnimations = new Dictionary(); _previewSlotAnimations = new Dictionary>(); _previewEntryExists.Clear(); try { IReadOnlyDictionary presetColors = GetPresetColors(slot); if (presetColors != null) { foreach (KeyValuePair item in presetColors) { SetPreviewFromEntry(item.Key, item.Value); } } SetPresetPreviewActive(value: true); MiniPresetContextActive = true; dress(); } finally { _previewOverrides = previewOverrides; _previewCustom = previewCustom; _previewSlotOverrides = previewSlotOverrides; _previewSlotCustom = previewSlotCustom; _previewAnimations = previewAnimations; _previewSlotAnimations = previewSlotAnimations; _previewEntryExists.Clear(); _previewEntryExists.UnionWith(other); SetPresetPreviewActive(presetPreviewActive); MiniPresetContextActive = miniPresetContextActive; } } internal static void SetPreviewFromEntry(string assetId, PresetColorEntry e) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) _previewEntryExists.Add(assetId); if (e.Anim != null) { _previewAnimations[assetId] = e.Anim; } Dictionary slotAnim = e.SlotAnim; if (slotAnim != null && slotAnim.Count > 0) { _previewSlotAnimations[assetId] = new Dictionary(e.SlotAnim); } float[] custom = e.Custom; if (custom != null && custom.Length >= 3) { _previewCustom[assetId] = new Color(e.Custom[0], e.Custom[1], e.Custom[2]); } else if (e.Index.HasValue) { _previewOverrides[assetId] = e.Index.Value; } Dictionary slotIndex = e.SlotIndex; if (slotIndex != null && slotIndex.Count > 0) { _previewSlotOverrides[assetId] = new Dictionary(e.SlotIndex); } Dictionary slotCustom = e.SlotCustom; if (slotCustom == null || slotCustom.Count <= 0) { return; } Dictionary dictionary = new Dictionary(); foreach (KeyValuePair item in e.SlotCustom) { custom = item.Value; if (custom != null && custom.Length >= 3) { dictionary[item.Key] = new Color(item.Value[0], item.Value[1], item.Value[2]); } } _previewSlotCustom[assetId] = dictionary; } internal static void SetSlotColor(string assetId, int slot, int colorIndex) { if (!_slotColors.TryGetValue(assetId, out Dictionary value)) { value = (_slotColors[assetId] = new Dictionary()); } value[slot] = colorIndex; SaveSlots(); if (RemoveCustomSlotNoSave(assetId, slot)) { SaveCustomSlots(); } if (RemoveSlotAnimationNoSave(assetId, slot)) { SaveSlotAnimations(); } } internal static bool RemoveSlotColorNoSave(string assetId, int slot) { if (_slotColors.TryGetValue(assetId, out Dictionary value)) { return value.Remove(slot); } return false; } internal static bool TryGetSlotColor(string assetId, int slot, out int colorIndex) { colorIndex = 0; if (_slotColors.TryGetValue(assetId, out Dictionary value)) { return value.TryGetValue(slot, out colorIndex); } return false; } internal static bool HasAnySlotColor(string assetId) { if (_slotColors.TryGetValue(assetId, out Dictionary value)) { return value.Count > 0; } return false; } internal static IReadOnlyDictionary? GetSlots(string assetId) { if (!_slotColors.TryGetValue(assetId, out Dictionary value)) { return null; } return value; } internal static IReadOnlyDictionary> GetAllSlots() { return _slotColors; } internal static bool RemoveSlotsNoSave(string assetId) { return _slotColors.Remove(assetId); } internal static void ClearSlotsForAsset(string assetId) { if (_slotColors.Remove(assetId)) { SaveSlots(); } } internal static void ClearAllSlotsNoSave() { _slotColors.Clear(); } internal static void LoadSlots() { try { if (File.Exists(SlotSavePath)) { Dictionary> dictionary = JsonConvert.DeserializeObject>>(File.ReadAllText(SlotSavePath)); if (dictionary != null) { _slotColors = dictionary; } } } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: slot colours load failed: " + ex.Message); } } internal static void SaveSlots() { Save(); } } internal sealed class PresetColorEntry { [JsonProperty("i")] public int? Index; [JsonProperty("c")] public float[]? Custom; [JsonProperty("si")] public Dictionary? SlotIndex; [JsonProperty("sc")] public Dictionary? SlotCustom; [JsonProperty("an")] public ColorAnimation? Anim; [JsonProperty("sa")] public Dictionary? SlotAnim; } internal static class PerCosmeticColorSerializer { private sealed class CustomColorNetworkDto { [JsonProperty("w")] public Dictionary? W { get; set; } [JsonProperty("s")] public Dictionary>? S { get; set; } } private const char Sep = '\u001f'; private const char SlotKeySep = '\u001e'; internal static string Serialize(IReadOnlyDictionary colors) { if (colors.Count == 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(colors.Count * 48); foreach (KeyValuePair color in colors) { stringBuilder.Append(color.Key); stringBuilder.Append('\u001f'); stringBuilder.Append(color.Value); stringBuilder.Append('\u001f'); } return stringBuilder.ToString(); } internal static Dictionary Deserialize(string data) { Dictionary dictionary = new Dictionary(); if (string.IsNullOrEmpty(data)) { return dictionary; } string[] array = data.Split('\u001f', StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i + 1 < array.Length; i += 2) { if (array[i].IndexOf('\u001e') < 0 && int.TryParse(array[i + 1], out var result)) { dictionary[array[i]] = result; } } return dictionary; } internal static string SerializeWithSlots(IReadOnlyDictionary colors, IReadOnlyDictionary> slotColors) { if (colors.Count == 0 && slotColors.Count == 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair color in colors) { stringBuilder.Append(color.Key); stringBuilder.Append('\u001f'); stringBuilder.Append(color.Value); stringBuilder.Append('\u001f'); } foreach (KeyValuePair> slotColor in slotColors) { foreach (KeyValuePair item in slotColor.Value) { stringBuilder.Append(slotColor.Key); stringBuilder.Append('\u001e'); stringBuilder.Append(item.Key); stringBuilder.Append('\u001f'); stringBuilder.Append(item.Value); stringBuilder.Append('\u001f'); } } return stringBuilder.ToString(); } internal static void DeserializeWithSlots(string data, out Dictionary colors, out Dictionary> slotColors) { colors = new Dictionary(); slotColors = new Dictionary>(); if (string.IsNullOrEmpty(data)) { return; } string[] array = data.Split('\u001f', StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i + 1 < array.Length; i += 2) { string text = array[i]; if (!int.TryParse(array[i + 1], out var result)) { continue; } int num = text.IndexOf('\u001e'); if (num < 0) { colors[text] = result; continue; } string key = text.Substring(0, num); string s = text.Substring(num + 1); if (int.TryParse(s, out var result2)) { if (!slotColors.TryGetValue(key, out Dictionary value)) { value = (slotColors[key] = new Dictionary()); } value[result2] = result; } } } internal static string SerializeAnimations(IReadOnlyDictionary animations) { if (animations.Count != 0) { return JsonConvert.SerializeObject((object)animations); } return ""; } internal static Dictionary DeserializeAnimations(string data) { if (string.IsNullOrEmpty(data)) { return new Dictionary(); } try { return JsonConvert.DeserializeObject>(data) ?? new Dictionary(); } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: animation deserialise failed: " + ex.Message); return new Dictionary(); } } internal static string SerializeCustomColors(IReadOnlyDictionary whole, IReadOnlyDictionary> perSlot) { //IL_0044: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (whole.Count == 0 && perSlot.Count == 0) { return ""; } Dictionary dictionary = new Dictionary(whole.Count); foreach (KeyValuePair item in whole) { dictionary[item.Key] = new float[3] { item.Value.r, item.Value.g, item.Value.b }; } Dictionary> dictionary2 = new Dictionary>(perSlot.Count); foreach (KeyValuePair> item2 in perSlot) { Dictionary dictionary3 = new Dictionary(item2.Value.Count); foreach (KeyValuePair item3 in item2.Value) { dictionary3[item3.Key.ToString()] = new float[3] { item3.Value.r, item3.Value.g, item3.Value.b }; } dictionary2[item2.Key] = dictionary3; } return JsonConvert.SerializeObject((object)new CustomColorNetworkDto { W = dictionary, S = dictionary2 }); } internal static void DeserializeCustomColors(string data, out Dictionary whole, out Dictionary> perSlot) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) whole = new Dictionary(); perSlot = new Dictionary>(); if (string.IsNullOrEmpty(data)) { return; } try { CustomColorNetworkDto customColorNetworkDto = JsonConvert.DeserializeObject(data); if (customColorNetworkDto == null) { return; } if (customColorNetworkDto.W != null) { foreach (KeyValuePair item in customColorNetworkDto.W) { float[] value = item.Value; if (value != null && value.Length >= 3) { whole[item.Key] = new Color(item.Value[0], item.Value[1], item.Value[2]); } } } if (customColorNetworkDto.S == null) { return; } foreach (KeyValuePair> item2 in customColorNetworkDto.S) { if (item2.Value == null) { continue; } Dictionary dictionary = new Dictionary(); foreach (KeyValuePair item3 in item2.Value) { if (int.TryParse(item3.Key, out var result)) { float[] value = item3.Value; if (value != null && value.Length >= 3) { dictionary[result] = new Color(item3.Value[0], item3.Value[1], item3.Value[2]); } } } if (dictionary.Count > 0) { perSlot[item2.Key] = dictionary; } } } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: custom colours deserialise failed: " + ex.Message); } } internal static string SerializeSlotAnimations(IReadOnlyDictionary> slotAnims) { if (slotAnims.Count != 0) { return JsonConvert.SerializeObject((object)slotAnims); } return ""; } internal static Dictionary> DeserializeSlotAnimations(string data) { if (string.IsNullOrEmpty(data)) { return new Dictionary>(); } try { return JsonConvert.DeserializeObject>>(data) ?? new Dictionary>(); } catch (Exception ex) { BceConsole.LogWarning("PerCosmeticColors: slot animation deserialise failed: " + ex.Message); return new Dictionary>(); } } } internal sealed class PerCosmeticColorSyncComponent : MonoBehaviourPun { private Dictionary _remoteColors = new Dictionary(); private Dictionary> _remoteSlotColors = new Dictionary>(); private Dictionary _remoteAnimations = new Dictionary(); private Dictionary _remoteCustomColors = new Dictionary(); private Dictionary> _remoteCustomSlotColors = new Dictionary>(); private Dictionary> _remoteSlotAnimations = new Dictionary>(); internal void SetRemoteColors(Dictionary colors, Dictionary> slotColors) { _remoteColors = new Dictionary(colors); _remoteSlotColors = new Dictionary>(); foreach (KeyValuePair> slotColor in slotColors) { _remoteSlotColors[slotColor.Key] = new Dictionary(slotColor.Value); } } internal void SetRemoteAnimations(Dictionary animations) { _remoteAnimations = new Dictionary(animations); } internal void SetRemoteCustomColors(Dictionary whole, Dictionary> perSlot) { _remoteCustomColors = new Dictionary(whole); _remoteCustomSlotColors = new Dictionary>(); foreach (KeyValuePair> item in perSlot) { _remoteCustomSlotColors[item.Key] = new Dictionary(item.Value); } } internal void SetRemoteSlotAnimations(Dictionary> slotAnims) { _remoteSlotAnimations = new Dictionary>(); foreach (KeyValuePair> slotAnim in slotAnims) { _remoteSlotAnimations[slotAnim.Key] = new Dictionary(slotAnim.Value); } } internal bool TryGetRemoteCustomColor(string assetId, out Color color) { return _remoteCustomColors.TryGetValue(assetId, out color); } [PunRPC] internal void SyncPerCosmeticColorsRPC(string colorData) { if (colorData != null && colorData.Length <= 16384) { PerCosmeticColorSerializer.DeserializeWithSlots(colorData, out _remoteColors, out _remoteSlotColors); PlayerCosmetics component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { ApplyToCosmetics(component); } } } [PunRPC] internal void SyncColorAnimationsRPC(string animData) { if (animData != null && animData.Length <= 16384) { _remoteAnimations = PerCosmeticColorSerializer.DeserializeAnimations(animData); PlayerCosmetics component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { RefreshAnimators(component); } } } internal bool HasRemoteOverride(string assetId) { if (!_remoteColors.ContainsKey(assetId) && !_remoteAnimations.ContainsKey(assetId) && !_remoteCustomColors.ContainsKey(assetId) && !_remoteSlotAnimations.ContainsKey(assetId) && (!_remoteSlotColors.TryGetValue(assetId, out Dictionary value) || value.Count <= 0)) { if (_remoteCustomSlotColors.TryGetValue(assetId, out Dictionary value2)) { return value2.Count > 0; } return false; } return true; } internal int GetEffectiveRemoteColorIndex(string assetId, int fallbackTypeColor) { if (!_remoteColors.TryGetValue(assetId, out var value)) { return fallbackTypeColor; } return value; } internal void ApplyVanillaOverridesTo(IEnumerable playerMaterials) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected I4, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled || playerMaterials == null || (_remoteColors.Count <= 0 && _remoteCustomColors.Count <= 0)) { return; } foreach (PlayerMaterial playerMaterial in playerMaterials) { if ((Object)(object)playerMaterial == (Object)null) { continue; } if ((Object)(object)playerMaterial.cosmetic == (Object)null) { string key = VanillaTintHelper.BaseMeshAssetId((int)playerMaterial.cosmeticType); if (_remoteCustomColors.TryGetValue(key, out var value)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value); } continue; } CosmeticAsset cosmeticAsset = playerMaterial.cosmetic.cosmeticAsset; if (cosmeticAsset != null && !BridgeIds.IsBridgeAsset(cosmeticAsset)) { string assetId = cosmeticAsset.assetId; int value3; if (_remoteCustomColors.TryGetValue(assetId, out var value2)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value2); } else if (_remoteColors.TryGetValue(assetId, out value3) && value3 != -1) { playerMaterial.ColorSet(PerCosmeticColors.PropAlbedo, PerCosmeticColors.PropEmission, PerCosmeticColors.PropFresnel, value3); } } } } internal bool ApplyRemoteToBridgeTint(BridgeTintMaterial btm, string assetId) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled) { return false; } _remoteSlotColors.TryGetValue(assetId, out Dictionary value); _remoteCustomSlotColors.TryGetValue(assetId, out Dictionary value2); int value3; bool flag = _remoteColors.TryGetValue(assetId, out value3); Color value4; bool flag2 = _remoteCustomColors.TryGetValue(assetId, out value4); Material[]? materials = btm.materials; int num = ((materials != null) ? materials.Length : 0); bool result = false; for (int i = 0; i < num; i++) { int key = btm.SlotIdOf(i); Color value5; Color? slotCustom = ((value2 != null && value2.TryGetValue(key, out value5)) ? new Color?(value5) : ((Color?)null)); int value6; int? slotIndex = ((value != null && value.TryGetValue(key, out value6)) ? new int?(value6) : ((int?)null)); Color? wholeCustom = (flag2 ? new Color?(value4) : ((Color?)null)); int? wholeIndex = (flag ? new int?(value3) : ((int?)null)); if (PerCosmeticColors.ApplySlotPrecedence(btm, i, slotCustom, slotIndex, wholeCustom, wholeIndex)) { result = true; } } return result; } internal void RefreshAnimators(PlayerCosmetics pc) { if ((Object)(object)pc == (Object)null) { return; } if (!PerCosmeticColors.FeatureEnabled || !Plugin.EnableBridgeColorAnimations.Value) { ColorAnimatorRefresher.Apply(pc, (string _) => default(AnimSet)); return; } PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals != (Object)null) { if (!playerAvatarVisuals.isMenuAvatar) { PlayerAvatar playerAvatar = playerAvatarVisuals.playerAvatar; if (playerAvatar == null || !playerAvatar.isLocal) { goto IL_0082; } } if (AvatarIdentity.IsRemoteMini(pc)) { goto IL_0082; } } goto IL_00b4; IL_0082: if (!Plugin.SeeRemoteColorAnimations.Value) { ColorAnimatorRefresher.Apply(pc, (string _) => default(AnimSet)); return; } goto IL_00b4; IL_00b4: ColorAnimatorRefresher.Apply(pc, GetRemoteAnimSet); } internal AnimSet GetRemoteAnimSet(string assetId) { _remoteAnimations.TryGetValue(assetId, out ColorAnimation value); IReadOnlyDictionary readOnlyDictionary = null; if (_remoteSlotAnimations.TryGetValue(assetId, out Dictionary value2) && value2.Count > 0) { readOnlyDictionary = value2; } HashSet hashSet = null; if (value != null || readOnlyDictionary != null) { if (_remoteSlotColors.TryGetValue(assetId, out Dictionary value3) && value3.Count > 0) { if (hashSet == null) { hashSet = new HashSet(); } foreach (int key in value3.Keys) { hashSet.Add(key); } } if (_remoteCustomSlotColors.TryGetValue(assetId, out Dictionary value4) && value4.Count > 0) { if (hashSet == null) { hashSet = new HashSet(); } foreach (int key2 in value4.Keys) { hashSet.Add(key2); } } } return new AnimSet(value, readOnlyDictionary, hashSet); } internal void ApplyToCosmetics(PlayerCosmetics pc) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected I4, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) if (!PerCosmeticColors.FeatureEnabled || (Object)(object)pc == (Object)null) { return; } if (pc.playerMaterials != null) { foreach (PlayerMaterial playerMaterial in pc.playerMaterials) { if ((Object)(object)playerMaterial == (Object)null) { continue; } if ((Object)(object)playerMaterial.cosmetic == (Object)null) { string key = VanillaTintHelper.BaseMeshAssetId((int)playerMaterial.cosmeticType); if (_remoteCustomColors.TryGetValue(key, out var value)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value); } else { RepaintPalette(playerMaterial, pc); } } else if (!((Object)(object)playerMaterial.cosmetic.cosmeticAsset == (Object)null)) { string assetId = playerMaterial.cosmetic.cosmeticAsset.assetId; int value3; if (_remoteCustomColors.TryGetValue(assetId, out var value2)) { VanillaTintHelper.ApplyCustomRGB(playerMaterial, value2); } else if (_remoteColors.TryGetValue(assetId, out value3) && value3 != -1) { playerMaterial.ColorSet(PerCosmeticColors.PropAlbedo, PerCosmeticColors.PropEmission, PerCosmeticColors.PropFresnel, value3); } else if (!BridgeIds.IsBridgeAsset(playerMaterial.cosmetic.cosmeticAsset)) { RepaintPalette(playerMaterial, pc); } } } } PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null) { return; } BridgeTintMaterial[] componentsInChildren = ((Component)playerAvatarVisuals).GetComponentsInChildren(true); foreach (BridgeTintMaterial bridgeTintMaterial in componentsInChildren) { if ((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset == (Object)null) { continue; } string assetId2 = bridgeTintMaterial.cosmetic.cosmeticAsset.assetId; bool flag = BridgeIds.IsBridgeAsset(bridgeTintMaterial.cosmetic.cosmeticAsset); _remoteSlotColors.TryGetValue(assetId2, out Dictionary value4); _remoteCustomSlotColors.TryGetValue(assetId2, out Dictionary value5); int value6; bool flag2 = _remoteColors.TryGetValue(assetId2, out value6); Color value7; bool flag3 = _remoteCustomColors.TryGetValue(assetId2, out value7); if (!(flag2 || flag3) && (value4 == null || value4.Count <= 0) && (value5 == null || value5.Count <= 0)) { Dictionary value8; bool flag4 = _remoteAnimations.ContainsKey(assetId2) || (_remoteSlotAnimations.TryGetValue(assetId2, out value8) && value8.Count > 0); if (!flag4 && flag) { bridgeTintMaterial.RestoreOriginalColor(); } continue; } Material[]? materials = bridgeTintMaterial.materials; int num = ((materials != null) ? materials.Length : 0); for (int j = 0; j < num; j++) { int key2 = bridgeTintMaterial.SlotIdOf(j); Color value9; Color? slotCustom = ((value5 != null && value5.TryGetValue(key2, out value9)) ? new Color?(value9) : ((Color?)null)); int value10; int? slotIndex = ((value4 != null && value4.TryGetValue(key2, out value10)) ? new int?(value10) : ((int?)null)); Color? wholeCustom = (flag3 ? new Color?(value7) : ((Color?)null)); int? wholeIndex = (flag2 ? new int?(value6) : ((int?)null)); if (!PerCosmeticColors.ApplySlotPrecedence(bridgeTintMaterial, j, slotCustom, slotIndex, wholeCustom, wholeIndex) && flag) { bridgeTintMaterial.RestoreOriginalColorInSlot(j); } } } } private static void RepaintPalette(PlayerMaterial pm, PlayerCosmetics pc) { VanillaTintHelper.RepaintPalette(pm, pc); } } internal sealed class SlotButtonProxy : MonoBehaviour { internal BridgeSlotSelectorRow? row; internal int slotIndex; internal RectTransform? labelRT; internal float baseY; private MenuButton? _btn; private bool _wasClicked; private void Awake() { _btn = ((Component)this).GetComponent(); } private void Update() { if (!((Object)(object)_btn != (Object)null) || !_btn.clicked) { _wasClicked = false; } else if (!_wasClicked) { _wasClicked = true; MenuManager instance = MenuManager.instance; if (instance != null) { instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); } row?.OnSlotClicked(slotIndex); } } private void LateUpdate() { HoverAdjust(); } private void HoverAdjust() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) if (!((Object)(object)_btn == (Object)null) && !((Object)(object)labelRT == (Object)null)) { Vector2 anchoredPosition = labelRT.anchoredPosition; float num = (_btn.hovering ? (baseY + 1f) : baseY); if (!Mathf.Approximately(anchoredPosition.y, num)) { labelRT.anchoredPosition = new Vector2(anchoredPosition.x, num); } } } } [BepInPlugin("Xuaun.MoreHeadBridge", "MoreHead Bridge", "3.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private readonly Harmony _harmony = new Harmony("Xuaun.MoreHeadBridge"); public static ConfigEntry AutoUnlockBridgeCosmetics { get; private set; } public static ConfigEntry AllowMultipleCosmetics { get; private set; } public static ConfigEntry EnablePerCosmeticColors { get; private set; } public static ConfigEntry EnableMiniSemibot { get; private set; } public static ConfigEntry SpecificFolders { get; private set; } public static ConfigEntry EnableMenuEnhancements { get; private set; } public static ConfigEntry ShowToolsButton { get; private set; } public static ConfigEntry GroupCosmeticVariants { get; private set; } public static ConfigEntry HideMoreHeadButton { get; private set; } public static ConfigEntry HideMoreHeadDecorations { get; private set; } public static ConfigEntry ExcludeMoreHeadFromPresetIcons { get; private set; } public static ConfigEntry SearchFieldPosition { get; private set; } public static ConfigEntry BridgeBlacklistMode { get; private set; } public static ConfigEntry MirrorBlacklistToMoreHead { get; private set; } public static ConfigEntry EnableBridgeTinting { get; private set; } public static ConfigEntry EnableBridgeColorAnimations { get; private set; } public static ConfigEntry SeeRemoteColorAnimations { get; private set; } public static ConfigEntry EnableBridgeCustomColors { get; private set; } public static ConfigEntry EnableWorldFollowSpring { get; private set; } public static ConfigEntry HighlightBridgeCosmetics { get; private set; } public static ConfigEntry BridgeDefaultRarity { get; private set; } public static ConfigEntry EnableCosmeticCustomizer { get; private set; } public static ConfigEntry UseVanillaPositionFixes { get; private set; } public static ConfigEntry ImportOverrides { get; private set; } public static ConfigEntry ExportOverrides { get; private set; } public static ConfigEntry EnableVanillaCustomColors { get; private set; } public static ConfigEntry HighlightModdedCosmetics { get; private set; } public static ConfigEntry AutoUnlockModdedCosmetics { get; private set; } public static ConfigEntry AllowModdedOverrides { get; private set; } public static ConfigEntry ResetModdedUnlocks { get; private set; } public static ConfigEntry EnableModdedCustomColors { get; private set; } public static ConfigEntry FixCosmeticsMenuPerformance { get; private set; } public static ConfigEntry RemoveBridgePhysics { get; private set; } public static ConfigEntry LoopBridgeAnimation { get; private set; } public static ConfigEntry BridgeEquipAnimationMode { get; private set; } public static ConfigEntry UseIsolatedIconRender { get; private set; } public static ConfigEntry UseTextureAsPlaceholder { get; private set; } public static ConfigEntry AutoCaptureIcons { get; private set; } public static ConfigEntry GenerateAllIcons { get; private set; } public static ConfigEntry HideClothesWhileGenerating { get; private set; } public static ConfigEntry ResetBodyColorWhileGenerating { get; private set; } public static ConfigEntry HideAvatarWhileGenerating { get; private set; } public static ConfigEntry ResetBridgeUnlocks { get; private set; } public static ConfigEntry ResetCosmeticCustomizer { get; private set; } public static ConfigEntry DeleteIconCache { get; private set; } public static ConfigEntry DeleteIconsMatching { get; private set; } public static ConfigEntry ShowBridgeDebugLogs { get; private set; } public static Plugin Instance { get; private set; } public static ManualLogSource Logger { get; private set; } public static bool MenuLibAvailable { get; private set; } private void BindConfig() { AutoUnlockBridgeCosmetics = ((BaseUnityPlugin)this).Config.Bind("General", "AutoUnlockBridgeCosmetics", true, "Auto-unlock NEW bridge cosmetics on every load.\n\nWhen TRUE — every bridge cosmetic gets added to your inventory\n on game start, so you never have to grind for them.\nWhen FALSE — bridge cosmetics behave like vanilla ones:\n you have to earn them in-game.\n\nIMPORTANT: this flag only controls what happens going FORWARD.\nCosmetics unlocked while AutoUnlockBridgeCosmetics was TRUE get saved permanently to\nthe REPOLib modded save file. Flipping this to FALSE later does NOT\nremove them — REPOLib re-reads the save on every launch.\nIf you want to wipe existing unlocks, see the [Reset] section below."); AllowMultipleCosmetics = ((BaseUnityPlugin)this).Config.Bind("General", "AllowMultipleCosmetics", true, "When true, you can equip multiple cosmetics of the same type at once\n(e.g. two hats, three body pieces, several worlds).\nApplies to: Hat, HeadBottom, FaceTop, FaceBottom, Eyewear, Ears,\n BodyTop, BodyBottom, ArmRight, ArmLeft,\n LegRight, FootRight, LegLeft, FootLeft, World."); EnablePerCosmeticColors = ((BaseUnityPlugin)this).Config.Bind("General", "EnablePerCosmeticColors", true, "Master switch for the per-cosmetic color SYSTEM (all cosmetic kinds):\nper-cosmetic palette colors, custom RGB (bridge/vanilla/modded), animated\ncolors, and the color sync to other players.\nWhen FALSE: the mod leaves all cosmetic colors to the vanilla per-type\npalette — no per-cosmetic overrides are applied, sent, or received.\nApplies live. Bridge tinting specifically is controlled by EnableBridgeTinting."); EnableMiniSemibot = ((BaseUnityPlugin)this).Config.Bind("General", "EnableMiniSemibot", true, "Adds the 'Mini-Semibot' cosmetic to the WORLD tab — a small copy of your avatar,\ndressed in your current outfit, that follows you around and is visible to other\nplayers. Shift+click it in the menu to tweak how it looks and behaves.\nTakes effect immediately: OFF unequips it, ON registers/restores the cosmetic."); SpecificFolders = ((BaseUnityPlugin)this).Config.Bind("General", "SpecificFolders", "", "Comma-separated subfolder names under BepInEx/plugins to scan for .hhh files. Empty = scan all. Example: 'Some-MoreHeadPack,Another-CosmeticsPack'. Matching is case-insensitive and uses path contains."); EnableMenuEnhancements = ((BaseUnityPlugin)this).Config.Bind("CosmeticsMenu", "EnableMenuEnhancements", true, "When TRUE (default), enables the extended cosmetics menu:\n • Virtual tabs: SEARCH, SELECTED, FAV, HIDE\n • Ctrl+click to favorite, Alt+click to hide cosmetics\n • Live search bar and cosmetic name hover tooltip\nSet to FALSE if you prefer the unmodified vanilla cosmetics menu."); ShowToolsButton = ((BaseUnityPlugin)this).Config.Bind("CosmeticsMenu", "ShowToolsButton", true, "When TRUE (default), shows the Tools dropdown button in the cosmetics menu.\nThe button provides: Generate Icons, Clear All Icons, and Cosmetic Settings.\nSet to FALSE to hide it if you don't use those features."); GroupCosmeticVariants = ((BaseUnityPlugin)this).Config.Bind("CosmeticsMenu", "GroupCosmeticVariants", false, "When TRUE, collapses families of cosmetics that differ only by a variant\ninto a single menu button to de-clutter the list: pride flags of the same RepoPride\nitem, and color variants of the same MoreHead pack item (e.g. BASICS). Click the\nbutton to open a popup and pick the variant. Requires MenuLib.\nSet to FALSE to show every variant as its own button (vanilla behaviour)."); HideMoreHeadButton = ((BaseUnityPlugin)this).Config.Bind("CosmeticsMenu", "HideMoreHeadButton", false, "If true, hides the MoreHead button from all menus so you can use only the vanilla cosmetics UI.\nApplies automatically when changed — no restart required."); HideMoreHeadDecorations = ((BaseUnityPlugin)this).Config.Bind("CosmeticsMenu", "HideMoreHeadDecorations", false, "If true, hides the decorations you equipped through the MoreHead menu on\nplayer avatars. Owner-authoritative and synced: while on, YOUR MoreHead decorations\nare hidden for everyone (a temporary 'no decorations' look), and other players running\nthis mod won't render them either. Bridge and vanilla cosmetics are unaffected.\nApplies automatically when changed — no restart required."); BridgeBlacklistMode = ((BaseUnityPlugin)this).Config.Bind("Blacklist", "BlacklistMode", BlacklistLoadMode.NotLoadIngame, "What the bridge does with cosmetics on its blacklist.\nNotLoadIngame = skip them entirely (saves memory; matches MoreHead's behaviour).\nLoadOnHiddenMenu = still register them, but start them hidden in the menu (HIDE tab).\nLoad-time — changes apply on the next game launch."); MirrorBlacklistToMoreHead = ((BaseUnityPlugin)this).Config.Bind("Blacklist", "BlacklistOnMoreHead", false, "If true, the bridge also writes its blacklisted cosmetic names into MoreHead's own\nblacklist (merge-only — it never removes entries you added yourself), so MoreHead stops\nloading those decorations too. Load-time — applies on the next launch."); ExcludeMoreHeadFromPresetIcons = ((BaseUnityPlugin)this).Config.Bind("CosmeticsMenu", "ExcludeMoreHeadFromPresetIcons", false, "When TRUE, MoreHead-menu decorations are left out of the saved preset PREVIEW IMAGE,\nso a preset's thumbnail shows only the cosmetics that preset actually stores.\nLocal only — preset thumbnails are a per-machine PNG cache; nothing to sync.\nRe-save a preset (or clear its cached icon) to refresh an existing thumbnail."); SearchFieldPosition = ((BaseUnityPlugin)this).Config.Bind("CosmeticsMenu", "SearchFieldPosition", SearchBarPosition.Top, "Where the search bar appears in the cosmetics menu.\nBottom = at the bottom of the Semibot.\nTop = above the category strip (default)."); EnableBridgeTinting = ((BaseUnityPlugin)this).Config.Bind("BridgeAppearance", "EnableBridgeTinting", true, "Enables tinting for BRIDGE (.hhh) cosmetics specifically.\nWhen TRUE (default): bridge cosmetics with a supported color channel can be\ntinted via the in-game color picker (per-cosmetic and per-slot).\nWhen FALSE: bridge cosmetics keep their original author colors and ignore\nsection paints — vanilla/modded cosmetics are unaffected (see\nEnablePerCosmeticColors for the system-wide switch).\n\nPer-cosmetic Tintable overrides (Shift+click → CosmeticCustomizer) always\ntake priority over this global setting."); EnableBridgeCustomColors = ((BaseUnityPlugin)this).Config.Bind("BridgeAppearance", "EnableBridgeCustomColors", false, "When TRUE, a \"C\" button appears in the color picker for tintable bridge\ncosmetics, opening RGB sliders to paint the cosmetic any custom color\n(not limited to the game's palette). Custom colors are synced to other\nplayers. When FALSE (default), the button is hidden."); EnableBridgeColorAnimations = ((BaseUnityPlugin)this).Config.Bind("BridgeAppearance", "EnableBridgeColorAnimations", false, "When TRUE, an \"A\" button appears in the color picker for tintable bridge\ncosmetics, letting you set an animated color (Cycle / Rainbow). Animations are\nsynced to other players. When FALSE (default), the feature is fully off — no\nbutton and no animations run (including remote players')."); SeeRemoteColorAnimations = ((BaseUnityPlugin)this).Config.Bind("BridgeAppearance", "SeeRemoteColorAnimations", false, "When TRUE, you see animated colors that other players have set on their cosmetics.\nWhen FALSE (default), remote players' animated colors are hidden on your screen —\nthey still animate on their own screen and on any client that has this enabled.\nDoes not affect your own animations. Only relevant when EnableBridgeColorAnimations is TRUE."); EnableWorldFollowSpring = ((BaseUnityPlugin)this).Config.Bind("BridgeAppearance", "EnableWorldFollowSpring", false, "When TRUE, a \"Follow Smoothing\" slider appears in each WORLD cosmetic's Shift+click\npopup, letting that cosmetic trail you with a soft lag or a bouncy overshoot instead\nof being rigidly glued to you. Each world cosmetic keeps its own choice\n(Off / Soft / Bouncy). Purely a local visual feel; not synced. When FALSE (default),\nthe slider is hidden and world cosmetics stay rigidly attached."); HighlightBridgeCosmetics = ((BaseUnityPlugin)this).Config.Bind("BridgeAppearance", "HighlightBridgeCosmetics", true, "When TRUE (default), bridge cosmetics show an orange border in the cosmetics menu,\nmaking them visually distinct from vanilla cosmetics at a glance.\nThe sort position is unaffected — it is still controlled by BridgeDefaultRarity.\nWhen FALSE, bridge cosmetics use the standard rarity border color like any vanilla cosmetic.\n\nPer-cosmetic overrides set via the CosmeticCustomizer popup take priority over this setting."); BridgeDefaultRarity = ((BaseUnityPlugin)this).Config.Bind("BridgeAppearance", "BridgeDefaultRarity", (Rarity)0, "Rarity tier assigned to bridge cosmetics in the vanilla shop. Values: Common, Uncommon, Rare, UltraRare.\nControls sort position in the menu (UltraRare appears first, Common last).\nThe visual border color is controlled separately by HighlightBridgeCosmetics.\n\nPer-cosmetic rarity overrides set via the CosmeticCustomizer popup take priority over this setting."); EnableCosmeticCustomizer = ((BaseUnityPlugin)this).Config.Bind("CosmeticCustomizer", "EnableCosmeticCustomizer", false, "When TRUE, Shift+click on any bridge cosmetic in the menu opens a popup\nthat lets you override its rarity tier and category (Hat, BodyTop, World, …)\nindividually. Overrides are saved and applied on every launch.\n\nRequires MenuLib to be installed."); UseVanillaPositionFixes = ((BaseUnityPlugin)this).Config.Bind("CosmeticCustomizer", "UseVanillaPositionFixes", true, "When TRUE, bridge cosmetics get automatic vanilla-style position/scale fixes\nthat adapt them to non-default body shapes (big/tiny/huge limbs, …) — the\nautomatic counterpart of the 'Special Position Fixes' you can set per cosmetic.\nThe Missing Right Side head fix is NOT auto-applied: opt in per\ncosmetic via Special Position Fixes ('Use'). Turn OFF to keep every bridge\ncosmetic at its authored size/position regardless of body shape.\n\nPer-cosmetic 'Vanilla Position Fixes' (Customizer popup) overrides this default."); ImportOverrides = ((BaseUnityPlugin)this).Config.Bind("CosmeticCustomizer", "ImportCosmeticCustomizer", false, "ONE-SHOT trigger. When TRUE, immediately reads\n BepInEx/config/MoreHeadBridge/overrides_export.json\nand merges its contents into the local Cosmetic Customizer store.\nLocal Cosmetic Customizer settings not in the file are kept (true merge, not replace).\nAuto-flips back to FALSE after running."); ExportOverrides = ((BaseUnityPlugin)this).Config.Bind("CosmeticCustomizer", "ExportCosmeticCustomizer", false, "ONE-SHOT trigger. When TRUE, immediately exports ALL current\nCosmetic Customizer settings to:\n BepInEx/config/MoreHeadBridge/overrides_export.json\nMerges with any existing file — entries already in the file are\nupdated, others are kept as-is.\nAuto-flips back to FALSE after running."); EnableVanillaCustomColors = ((BaseUnityPlugin)this).Config.Bind("VanillaCosmetics", "EnableVanillaCustomColors", false, "When TRUE, a \"C\" button appears in the color picker for vanilla cosmetics\nthat support a custom color channel (Hurtable shader with _AlbedoColor),\nallowing you to paint them any RGB color beyond the game's palette.\nWhen FALSE (default), vanilla cosmetics can only use the standard palette."); AutoUnlockModdedCosmetics = ((BaseUnityPlugin)this).Config.Bind("OtherModdedCosmetics", "AutoUnlockModdedCosmetics", false, "When TRUE, automatically unlocks all cosmetics registered by other mods via\nREPOLib (non-bridge modded cosmetics) on every game start.\n\nCosmetics unlocked this way are tracked in a separate file so that\nResetModdedUnlocks (below) can remove exactly those without touching\ncosmetics you earned through normal gameplay."); EnableModdedCustomColors = ((BaseUnityPlugin)this).Config.Bind("OtherModdedCosmetics", "EnableModdedCustomColors", false, "When TRUE, a \"C\" button appears in the color picker for modded non-bridge\ncosmetics (registered via REPOLib by other mods) that support a custom color\nchannel, allowing custom RGB painting beyond the game's palette.\nWhen FALSE (default), modded cosmetics can only use the standard palette."); HighlightModdedCosmetics = ((BaseUnityPlugin)this).Config.Bind("OtherModdedCosmetics", "HighlightModdedCosmetics", false, "When TRUE, modded NON-bridge cosmetics (registered by other REPOLib mods)\nshow a purple border in the cosmetics menu, marking them as coming from\nanother mod. When FALSE (default), they use their normal rarity border.\n\nBridge (.hhh) cosmetics are controlled separately by HighlightBridgeCosmetics.\nPer-cosmetic overrides (Shift+click) take priority over this setting."); AllowModdedOverrides = ((BaseUnityPlugin)this).Config.Bind("OtherModdedCosmetics", "AllowModdedCosmeticCustomizer", false, "ADVANCED / opt-in. When TRUE, the Cosmetic Customizer popup\n(Shift+click) also opens for MODDED non-bridge cosmetics registered via\nREPOLib — letting you remap their category, add offset/hide conditions, etc.\nModded cosmetics are authored against the vanilla anchors, so type remaps\nre-parent them onto those anchors. Leave OFF unless you know what you're doing.\n\nRequires EnableCosmeticCustomizer (and MenuLib) to be enabled."); ResetModdedUnlocks = ((BaseUnityPlugin)this).Config.Bind("OtherModdedCosmetics", "ResetModdedUnlocks", false, "⚠ DESTRUCTIVE ONE-SHOT TRIGGER ⚠\n\nRemoves from your save file ONLY the non-bridge modded cosmetics that\nwere unlocked by the AutoUnlockModdedCosmetics option.\nCosmetics you earned through normal gameplay are NOT affected.\nAuto-flips back to FALSE after running."); FixCosmeticsMenuPerformance = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "FixCosmeticsMenuPerformance", false, "Enable this if you have many cosmetics mods and the vanilla\ncosmetics tabs (HEAD/BODY/ARMS/LEGS) are stuttering or\ntaking too long to load. Default = FALSE."); RemoveBridgePhysics = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "RemoveBridgePhysics", true, "When TRUE (default), removes physics components (collider and rigidbody) from bridge\ncosmetic prefabs at load time. Prevents physics interference and the\ncharacter-rotation bug in the cosmetics preview menu.\nPer-cosmetic override (Shift+click) takes priority over this global setting.\nTakes effect on the next game launch."); LoopBridgeAnimation = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "LoopBridgeAnimation", true, "When TRUE (default), forces all Animation clips and Animator states on bridge\n(.hhh) cosmetic prefabs to loop. Useful for ambient idle animations.\nSet to FALSE for cosmetics with intentional one-shot animations.\nPer-cosmetic override (Shift+click) takes priority over this global setting.\nTakes effect on the next game launch."); BridgeEquipAnimationMode = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "BridgeEquipAnimationMode", VanillaEquipAnimationMode.Fixed, "Controls how vanilla equip animation behaves for bridge cosmetics.\nFixed = keep a small non-zero scale on spawn (prevents world animation collapse).\nNormal = vanilla behavior (scale to zero then pop out).\nDisabled= skip vanilla equip animation (spawn at final scale).\nPer-cosmetic override (Shift+click) takes priority."); UseTextureAsPlaceholder = ((BaseUnityPlugin)this).Config.Bind("BridgeIcons", "UseTextureAsPlaceholder", true, "When TRUE (default) — the cosmetic's texture is used as the icon, overlaid on the placeholder background.\nWhen FALSE — the texture is NOT applied to the placeholder; the slot keeps the plain placeholder icon\n until a captured icon (AutoCaptureIcons / GenerateAllIcons) replaces it."); UseIsolatedIconRender = ((BaseUnityPlugin)this).Config.Bind("BridgeIcons", "UseIsolatedIconRender", true, "When TRUE (default), bridge cosmetic icons are rendered in ISOLATION\nusing a dedicated camera + lights rig (mirroring vanilla's SemiIconMaker),\ninstead of cropping a region from the live menu-avatar preview. Isolated\nrenders are cleaner and independent of what else is equipped / the avatar pose.\nSet FALSE to use the avatar-crop capture instead. Delete the icon cache\n(Reset → DeleteIconCache) after toggling so icons regenerate with the chosen method."); AutoCaptureIcons = ((BaseUnityPlugin)this).Config.Bind("BridgeIcons", "AutoCaptureIcons", true, "Reactively capture icons while you browse the cosmetics menu.\n\nWhen TRUE — every time you HOVER a bridge cosmetic in the menu,\n the game's existing avatar preview is snapshotted and\n saved as a PNG icon for that cosmetic. Next time the UI\n asks for that icon it loads the PNG (instant).\n Icons fill in gradually as you explore the menu.\nWhen FALSE — no captures. Bridge cosmetics keep the texture/placeholder\n fallback icons.\n\nPNG cache lives in:\n %userprofile%\\AppData\\LocalLow\\semiwork\\REPO\\Cache\\Icons\\CosmeticsModded\\MoreHeadBridge_CosmeticsIcons\\\nDelete that folder to wipe all generated icons.\n(Icons are stored in Cache\\Icons\\CosmeticsModded\\ — a sibling of the vanilla\n Cache\\Icons\\Cosmetics\\ that REPOLib wipes, so ours are never touched.)"); GenerateAllIcons = ((BaseUnityPlugin)this).Config.Bind("BridgeIcons", "GenerateAllIcons", false, "ONE-SHOT trigger. When TRUE, the next time you open the cosmetics menu\nthe mod will cycle through EVERY bridge cosmetic without a cached icon,\npreview-equipping each one, snapshotting the avatar, and saving the PNG.\n\nEffects while running:\n * Equipped cosmetics are hidden by default (HideClothesWhileGenerating).\n * Body color is reset to default by default (ResetBodyColorWhileGenerating).\n * The avatar display is hidden by default (HideAvatarWhileGenerating).\n * Progress is shown on-screen where the avatar was.\n * Console logs progress every 50 items.\n * Expect ~1-3 minutes for 1600+ cosmetics.\n * Whatever you had previewing/equipped is restored at the end.\n * This flag auto-resets to FALSE so it doesn't fire again.\n\nUse this if you want all icons generated in one go instead of as you browse.\nRequires AutoCaptureIcons logic — keeps working even if AutoCaptureIcons=false."); HideAvatarWhileGenerating = ((BaseUnityPlugin)this).Config.Bind("BridgeIcons", "HideAvatarWhileGenerating", true, "When TRUE (default), hides the avatar preview display while\nGenerateAllIcons is running, so the rapid cosmetic cycling\nis not visible on screen. The avatar camera still renders\ninternally (icons are still captured correctly) — only the\non-screen preview image is hidden.\nSet to FALSE if you want to watch the batch progress visually."); HideClothesWhileGenerating = ((BaseUnityPlugin)this).Config.Bind("BridgeIcons", "HideClothesWhileGenerating", true, "When TRUE (default), only the cosmetic being captured is shown on the avatar\nduring GenerateAllIcons — all other equipped cosmetics are hidden.\nThis gives clean, isolated icons for each cosmetic.\nWhen FALSE, your full equipped loadout is kept visible alongside the\ncosmetic being captured."); ResetBodyColorWhileGenerating = ((BaseUnityPlugin)this).Config.Bind("BridgeIcons", "ResetBodyColorWhileGenerating", true, "When TRUE (default), the avatar body color is temporarily set to its default\n(index 0 for every color slot) while GenerateAllIcons is running,\nso each icon is captured on a neutral-colored avatar.\nYour actual body colors are not changed — they are restored\nautomatically after generation ends (or is interrupted)."); ResetBridgeUnlocks = ((BaseUnityPlugin)this).Config.Bind("Reset", "ResetBridgeUnlocks", false, "⚠ DESTRUCTIVE ONE-SHOT TRIGGER ⚠\n\nSetting this to TRUE causes the NEXT game launch to:\n 1. Remove EVERY bridge cosmetic from your unlocks list\n 2. Remove them from any saved outfit/preset you have equipped\n 3. Remove them from your history\n 4. Rewrite the REPOLib modded save file\n 5. Auto-flip this flag back to FALSE so it doesn't fire again\n\nUse this if you want to start over with bridge cosmetics.\nIf AutoUnlockBridgeCosmetics=true, cosmetics are wiped and immediately re-unlocked on the same launch.\nSet AutoUnlockBridgeCosmetics=false FIRST if you want to keep them locked after the reset.\n\nThis does NOT touch vanilla cosmetics or cosmetics from other mods.\nThis does NOT delete the .hhh files — only the unlock state."); ResetCosmeticCustomizer = ((BaseUnityPlugin)this).Config.Bind("Reset", "ResetCosmeticCustomizer", false, "ONE-SHOT trigger. When TRUE on the next launch:\n 1. Clears ALL per-cosmetic overrides (rarity, category, modded flag)\n set via the Cosmetic Customizer popup\n 2. Deletes CosmeticOverrides.json from BepInEx/config/MoreHeadBridge\n 3. Auto-flips this flag back to FALSE\n\nBridge cosmetics will revert to the global BridgeDefaultRarity and their\noriginal .hhh file category on the same launch."); DeleteIconCache = ((BaseUnityPlugin)this).Config.Bind("Reset", "DeleteIconCache", false, "ONE-SHOT trigger. When TRUE on launch, delete cached bridge icon PNGs from:\n %userprofile%\\AppData\\LocalLow\\semiwork\\REPO\\Cache\\Icons\\CosmeticsModded\\MoreHeadBridge_CosmeticsIcons\\\nUse DeleteIconsMatching to filter which ones to delete.\nAuto-resets to FALSE after running."); DeleteIconsMatching = ((BaseUnityPlugin)this).Config.Bind("Reset", "DeleteIconsMatching", "", "Optional comma-separated filter for DeleteIconCache. Case-insensitive\nsubstring match against the icon filename (which is the cosmetic's internal name).\nEmpty = delete ALL bridge icons.\nExample: 'PirateHat,Waluigi' deletes only icons whose name contains either."); ShowBridgeDebugLogs = ((BaseUnityPlugin)this).Config.Bind("Debug", "ShowBridgeDebugLogs", false, "If true, do NOT suppress NullReferenceExceptions for bridge cosmetics.\nUse this to diagnose bridge-only issues (will spam logs if the base game is noisy)."); } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; BridgePaths.Init(); BindConfig(); MenuLibAvailable = Chainloader.PluginInfos.ContainsKey("nickklmao.menulib"); if (MenuLibAvailable) { BridgeLog.Trace("MenuLib detected — CosmeticCustomizer UI enabled"); } PrintBanner(); PartShrinkerSuppressor.InstallWarningFilter(); PartShrinkerSuppressor.InstallNativeWarningFilter(_harmony); CustomizerStore.Load(); if (ResetCosmeticCustomizer.Value) { CustomizerStore.ResetAll(); ResetCosmeticCustomizer.Value = false; BceConsole.LogInfo("CosmeticCustomizer: all per-cosmetic overrides cleared", ConsoleColor.Magenta); } if (ImportOverrides.Value) { CustomizerIO.ImportMerge(); ImportOverrides.Value = false; } HhhCosmeticLoader.LoadAll(); PartShrinkerSuppressor.FlushSuppressedLog(); MiniSemibotCosmetic.Register(); if (ExportOverrides.Value) { CustomizerIO.ExportAll(); ExportOverrides.Value = false; } PerCosmeticColors.Load(); IconCacheCleaner.Run(); BridgePatcher.ApplyAll(_harmony); WireConfigHandlers(); PartShrinkerSuppressor.TryApply(_harmony); SetupCosmeticsModdedRpcPatch.TryApply(_harmony); REPOLibRpcOrderPatch.TryApply(_harmony); CustomGrabColorCompat.TryApply(_harmony); if (MenuLibAvailable) { HideMoreHeadButtonCreatePatch.TryApply(_harmony); } } private void WireConfigHandlers() { AllowMultipleCosmetics.SettingChanged += OnAllowMultipleCosmeticsChanged; EnableMiniSemibot.SettingChanged += delegate { OnEnableMiniSemibotChanged(); }; HideMoreHeadButton.SettingChanged += delegate { RuntimeConfigApplier.HideMoreHeadButtonsSoon(); }; HideMoreHeadDecorations.SettingChanged += delegate { MoreHeadHideSync.ApplyLocalAndBroadcast(); }; UseTextureAsPlaceholder.SettingChanged += delegate { ClearBridgeIconsWithoutCapture(); }; EnablePerCosmeticColors.SettingChanged += delegate { RuntimeConfigApplier.RefreshColorAnimations(); RuntimeConfigApplier.ReinstantiateAllLocalCosmetics(); RuntimeConfigApplier.RefreshCosmeticsMenu(); if (SemiFunc.IsMultiplayer()) { BridgeNetMux.BroadcastSnapshot(); } }; EnableBridgeTinting.SettingChanged += delegate { HhhCosmeticLoader.RefreshTintableFlags(); RuntimeConfigApplier.ReinstantiateAllLocalCosmetics(); RuntimeConfigApplier.RefreshCosmeticsMenu(); if (SemiFunc.IsMultiplayer()) { BridgeNetMux.BroadcastSnapshot(); } }; EnableBridgeColorAnimations.SettingChanged += delegate { RuntimeConfigApplier.RefreshColorAnimations(); RuntimeConfigApplier.ReapplyLocalCosmeticColors(); RuntimeConfigApplier.RefreshCosmeticsMenu(); }; SeeRemoteColorAnimations.SettingChanged += delegate { RuntimeConfigApplier.RefreshRemoteColorAnimations(); }; EnableBridgeCustomColors.SettingChanged += delegate { OnCustomColorToggle(); }; EnableVanillaCustomColors.SettingChanged += delegate { OnCustomColorToggle(); }; EnableModdedCustomColors.SettingChanged += delegate { OnCustomColorToggle(); }; HighlightBridgeCosmetics.SettingChanged += delegate { RuntimeConfigApplier.RefreshCosmeticsMenu(); }; HighlightModdedCosmetics.SettingChanged += delegate { RuntimeConfigApplier.RefreshCosmeticsMenu(); }; BridgeDefaultRarity.SettingChanged += delegate { HhhCosmeticLoader.RefreshDefaultRarity(); RuntimeConfigApplier.RefreshCosmeticsMenu(); }; ImportOverrides.SettingChanged += delegate { if (ImportOverrides.Value) { CustomizerIO.ImportMerge(); ImportOverrides.Value = false; ((BaseUnityPlugin)this).Config.Save(); RuntimeConfigApplier.RefreshCosmeticsMenu(); } }; ExportOverrides.SettingChanged += delegate { if (ExportOverrides.Value) { CustomizerIO.ExportAll(); ExportOverrides.Value = false; ((BaseUnityPlugin)this).Config.Save(); } }; AutoUnlockBridgeCosmetics.SettingChanged += delegate { if (AutoUnlockBridgeCosmetics.Value) { UnlockPatch.RunAutoUnlockNow(); RuntimeConfigApplier.RefreshCosmeticsMenu(); } }; AutoUnlockModdedCosmetics.SettingChanged += delegate { if (AutoUnlockModdedCosmetics.Value) { UnlockPatch.RunAutoUnlockModdedNow(); RuntimeConfigApplier.RefreshCosmeticsMenu(); } }; ResetBridgeUnlocks.SettingChanged += delegate { if (ResetBridgeUnlocks.Value) { UnlockPatch.RunResetNow(); RuntimeConfigApplier.RefreshCosmeticsMenu(); } }; ResetModdedUnlocks.SettingChanged += delegate { if (ResetModdedUnlocks.Value) { UnlockPatch.RunResetModdedNow(); RuntimeConfigApplier.RefreshCosmeticsMenu(); } }; ResetCosmeticCustomizer.SettingChanged += delegate { if (ResetCosmeticCustomizer.Value) { CustomizerStore.ResetAll(); MetaManager instance = MetaManager.instance; if ((Object)(object)instance != (Object)null) { foreach (CosmeticAsset cosmeticAsset in instance.cosmeticAssets) { if (!((Object)(object)cosmeticAsset == (Object)null) && BridgeIds.IsBridgeAsset(cosmeticAsset)) { HhhCosmeticLoader.ReapplyDefaults(cosmeticAsset); } } } ResetCosmeticCustomizer.Value = false; ((BaseUnityPlugin)this).Config.Save(); RuntimeConfigApplier.ReinstantiateAllLocalCosmetics(); RuntimeConfigApplier.RefreshCosmeticsMenu(); BceConsole.LogInfo("CosmeticCustomizer: all per-cosmetic overrides cleared (ingame)", ConsoleColor.Magenta); } }; static void OnCustomColorToggle() { RuntimeConfigApplier.ReapplyLocalCosmeticColors(); RuntimeConfigApplier.RefreshCosmeticsMenu(); PerCosmeticColorNetworkSync.BroadcastAll(); } } private void OnApplicationQuit() { CustomizerStore.FlushPendingWrites(); PerCosmeticColors.FlushPendingWrites(); BridgeFavoritesManager.FlushPendingWrites(); } private static void OnEnableMiniSemibotChanged() { if (EnableMiniSemibot.Value) { MiniSemibotCosmetic.Register(); if (AutoUnlockBridgeCosmetics.Value) { UnlockPatch.RunAutoUnlockNow(); } RuntimeConfigApplier.RefreshCosmeticsMenu(); return; } MetaManager instance = MetaManager.instance; CosmeticAsset asset = MiniSemibotCosmetic.Asset; if ((Object)(object)instance == (Object)null || (Object)(object)asset == (Object)null) { return; } int num = instance.cosmeticAssets.IndexOf(asset); if (num >= 0) { bool flag = instance.cosmeticEquipped.Remove(num); if (flag | instance.cosmeticEquippedPreview.Remove(num)) { instance.CosmeticPlayerUpdateLocal(SemiFunc.IsMultiplayer(), false); } } } private static void OnAllowMultipleCosmeticsChanged(object sender, EventArgs e) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } MultiEquipTypeFlags.Sync(); if (!AllowMultipleCosmetics.Value) { HashSet hashSet = new HashSet(); List list = new List(); foreach (int item in instance.cosmeticEquipped) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && !hashSet.Add(val.type)) { list.Add(item); } } } foreach (int item2 in list) { instance.cosmeticEquipped.Remove(item2); } } instance.CosmeticPlayerUpdateLocal(SemiFunc.IsMultiplayer(), false); } private static void ClearBridgeIconsWithoutCapture() { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } foreach (CosmeticAsset cosmeticAsset in instance.cosmeticAssets) { if (!((Object)(object)cosmeticAsset == (Object)null) && BridgeIds.IsBridgeAsset(cosmeticAsset) && !IconCapture.HasCache(cosmeticAsset)) { cosmeticAsset.icon = null; } } } private static void PrintBanner() { if (BceConsole.IsAvailable) { BceConsole.WriteLine("══════════════════════════════════════════════════════════════════════════════════", ConsoleColor.DarkCyan); BceConsole.Write("[Info : MoreHead Bridge] ", ConsoleColor.Cyan); BceConsole.WriteLine("► MoreHead Bridge v3.0.0 by Xuaun", ConsoleColor.DarkCyan); BceConsole.Write("[Info : MoreHead Bridge] ", ConsoleColor.Cyan); BceConsole.WriteLine(" Translating .hhh cosmetics into vanilla REPO", ConsoleColor.DarkCyan); BceConsole.WriteLine("══════════════════════════════════════════════════════════════════════════════════", ConsoleColor.DarkCyan); } else { BceConsole.LogInfo("MoreHead Bridge v3.0.0 by Xuaun"); } } } internal static class RuntimeConfigApplier { private const int HideMoreHeadRetries = 12; private const float HideMoreHeadInterval = 0.25f; internal static void HideMoreHeadButtonsSoon() { if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(HideMoreHeadButtonsRoutine()); } else { HideMoreHeadUIPatch.Apply(Plugin.HideMoreHeadButton.Value); } } private static IEnumerator HideMoreHeadButtonsRoutine() { for (int i = 0; i < 12; i++) { HideMoreHeadUIPatch.Apply(Plugin.HideMoreHeadButton.Value); yield return (object)new WaitForSecondsRealtime(0.25f); } } internal static void RefreshCosmeticsMenu() { MenuPageCosmetics val = CosmeticsMenuState.ActivePage ?? Object.FindObjectOfType(true); if (val != null) { val.RefreshScrollContent(); } } internal static void ReapplyLocalCosmeticColors() { PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { if (AvatarIdentity.IsLocalStyleTarget(val)) { val.SetupColors(false, (int[])null); } } LobbyHeadCustomColorPatch.RefreshAllHeads(); CustomGrabColorCompat.RefreshLocalBeam(); MiniSemibotSpawner.OnLocalColorsChanged(); } internal static void ReinstantiateAllLocalCosmetics() { PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { if (AvatarIdentity.IsLocalStyleTarget(val)) { val.SetupCosmetics(false, true, (List)null); val.SetupColors(false, (int[])null); } } } internal static void RefreshColorAnimations() { PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics pc in array) { ColorAnimatorRefresher.RefreshLiveAnimators(pc); } MiniSemibotSpawner.InvalidateLocalDeathHeads(); PerCosmeticColorNetworkSync.BroadcastAll(); } internal static void RefreshRemoteColorAnimations() { PerCosmeticColorSyncComponent[] array = Object.FindObjectsOfType(true); foreach (PerCosmeticColorSyncComponent perCosmeticColorSyncComponent in array) { PlayerCosmetics component = ((Component)perCosmeticColorSyncComponent).GetComponent(); if (!((Object)(object)component == (Object)null)) { perCosmeticColorSyncComponent.RefreshAnimators(component); RemoteColorSync.Apply(component); } } MiniSemibotSpawner.InvalidateRemoteMiniDeathHeads(); } internal static bool IsLivePaintTarget(PlayerCosmetics? pc) { if ((Object)(object)pc != (Object)null && AvatarIdentity.IsLocalStyleTarget(pc)) { return !MiniSemibotSpawner.IsPresetMini(pc); } return false; } } internal sealed class BridgeSwaySpring : MonoBehaviour { private readonly struct Preset { internal readonly float Speed; internal readonly float Damping; internal readonly bool Clamp; internal readonly float MaxAngle; internal readonly float Multiplier; internal readonly JumpDirection Direction; internal Preset(float speed, float damping, bool clamp, float maxAngle, float multiplier, JumpDirection direction) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Speed = speed; Damping = damping; Clamp = clamp; MaxAngle = maxAngle; Multiplier = multiplier; Direction = direction; } } private sealed class TargetSpring { internal Transform Target; internal Quaternion BaseLocalRotation; internal SpringQuaternion Spring; } private readonly List _targets = new List(); private Preset _preset = GetPreset((CosmeticType)0); private float _intensityFactor = 1f; private const float MaxLookDownTilt = 12f; private Transform? _lookDownSource; private bool _lookDownEnabled; internal void Init(Cosmetic cosmetic, float intensityFactor = 1f) { //IL_0013: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown RestoreBaseRotations(); _targets.Clear(); _preset = GetPreset(cosmetic.type); _intensityFactor = intensityFactor; _lookDownEnabled = IsHeadRegion(cosmetic.type); _lookDownSource = ((!_lookDownEnabled) ? null : (((Object)(object)cosmetic.playerCosmetics != (Object)null && (Object)(object)cosmetic.playerCosmetics.playerAvatarVisuals != (Object)null) ? cosmetic.playerCosmetics.playerAvatarVisuals.headLookAtTransform : null)); if (cosmetic.meshParents != null) { foreach (Transform meshParent in cosmetic.meshParents) { AddTarget(meshParent); } } if (_targets.Count == 0) { foreach (Transform item in ((Component)cosmetic).transform) { Transform target = item; AddTarget(target); } } ((Behaviour)this).enabled = _targets.Count > 0; } private static bool IsHeadRegion(CosmeticType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000f: 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_0014: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_0007: 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_000b: Invalid comparison between Unknown and I4 if ((int)type <= 6) { if ((int)type == 0 || type - 5 <= 1) { goto IL_001d; } } else if (type - 17 <= 1 || type - 30 <= 2) { goto IL_001d; } return false; IL_001d: return true; } internal void RestoreBaseRotations() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) foreach (TargetSpring target in _targets) { if ((Object)(object)target.Target != (Object)null) { target.Target.localRotation = target.BaseLocalRotation; } } } private void OnDestroy() { RestoreBaseRotations(); } private void AddTarget(Transform? target) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { return; } foreach (TargetSpring target2 in _targets) { if ((Object)(object)target2.Target == (Object)(object)target) { return; } } _targets.Add(new TargetSpring { Target = target, BaseLocalRotation = target.localRotation, Spring = NewSpring(_preset) }); } private void Update() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_006d: 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) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) for (int num = _targets.Count - 1; num >= 0; num--) { TargetSpring targetSpring = _targets[num]; Transform target = targetSpring.Target; if ((Object)(object)target == (Object)null) { _targets.RemoveAt(num); } else { Quaternion val = (((Object)(object)target.parent != (Object)null) ? (target.parent.rotation * targetSpring.BaseLocalRotation) : targetSpring.BaseLocalRotation); if (_lookDownEnabled && (Object)(object)_lookDownSource != (Object)null) { float num2 = Mathf.Clamp01(Vector3.Dot(_lookDownSource.forward, Vector3.down)); if (num2 > 0f) { Vector3 val2 = (((Object)(object)target.parent != (Object)null) ? target.parent.right : Vector3.right); val = Quaternion.AngleAxis(num2 * 12f, val2) * val; } } target.rotation = SemiFunc.SpringQuaternionGet(targetSpring.Spring, val, -1f); } } } internal void Impulse(float force, JumpDirection direction) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected I4, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) if (!((Behaviour)this).enabled) { return; } force *= _preset.Multiplier * _intensityFactor; foreach (TargetSpring target2 in _targets) { Transform target = target2.Target; if (!((Object)(object)target == (Object)null)) { Vector3 val = (Vector3)((int)direction switch { 0 => target.up, 1 => -target.up, 2 => -target.right, 4 => target.forward, 5 => -target.forward, _ => target.right, }); SpringQuaternion spring = target2.Spring; spring.springVelocity += val * force; } } } private static SpringQuaternion NewSpring(Preset preset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_001d: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown return new SpringQuaternion { damping = preset.Damping, speed = preset.Speed, clamp = preset.Clamp, maxAngle = preset.MaxAngle, bounce = 0.35f }; } internal static JumpDirection DefaultDirection(CosmeticType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return GetPreset(type).Direction; } private static Preset GetPreset(CosmeticType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected I4, but got Unknown return (int)type switch { 0 => new Preset(18f, 0.55f, clamp: false, 20f, 1f, (JumpDirection)3), 5 => new Preset(13f, 0.6f, clamp: false, 25f, 1f, (JumpDirection)3), 30 => new Preset(35f, 0.7f, clamp: true, 8f, 1f, (JumpDirection)3), 17 => new Preset(18f, 0.7f, clamp: true, 20f, 1f, (JumpDirection)3), 18 => new Preset(35f, 0.75f, clamp: false, 20f, 1f, (JumpDirection)3), 31 => new Preset(22f, 0.7f, clamp: true, 10f, 1f, (JumpDirection)3), 32 => new Preset(20f, 0.65f, clamp: false, 24f, 1f, (JumpDirection)3), 20 => new Preset(13f, 0.5f, clamp: false, 20f, 1.5f, (JumpDirection)3), 21 => new Preset(15f, 0.5f, clamp: false, 20f, 1.25f, (JumpDirection)3), 7 => new Preset(13f, 0.5f, clamp: false, 20f, 1f, (JumpDirection)3), 8 => new Preset(16f, 0.5f, clamp: true, 60f, 1f, (JumpDirection)2), 2 => new Preset(16f, 0.65f, clamp: false, 18f, 1f, (JumpDirection)3), 1 => new Preset(16f, 0.65f, clamp: false, 18f, 1f, (JumpDirection)3), 10 => new Preset(10f, 0.5f, clamp: false, 10f, 1f, (JumpDirection)3), 9 => new Preset(10f, 0.5f, clamp: false, 16f, 1f, (JumpDirection)3), 4 => new Preset(13f, 0.5f, clamp: false, 10f, 3f, (JumpDirection)3), 3 => new Preset(15f, 0.5f, clamp: false, 5f, 5f, (JumpDirection)3), 22 => new Preset(10f, 0.5f, clamp: false, 20f, 1f, (JumpDirection)3), 19 => new Preset(10f, 0.5f, clamp: false, 20f, 1f, (JumpDirection)3), 14 => new Preset(10f, 0.5f, clamp: false, 20f, 1f, (JumpDirection)3), 15 => new Preset(10f, 0.5f, clamp: false, 20f, 1f, (JumpDirection)3), _ => new Preset(18f, 0.55f, clamp: false, 20f, 1f, (JumpDirection)3), }; } } internal static class CosmeticSwayHelper { private static readonly HashSet _allTypes = new HashSet(SemiFunc.CosmeticGetTypes()); private const float MiniImpulseScaleMin = 0.25f; private const float MiniImpulseScaleMax = 1f; internal static bool ShouldSuppressSway(Cosmetic? cosmetic) { if ((Object)(object)cosmetic == (Object)null || !BridgeIds.IsBridgeAsset(cosmetic.cosmeticAsset)) { return false; } return GetEffectiveSway(cosmetic) == SwayMode.None; } private static SwayMode? GetEffectiveSway(Cosmetic cosmetic) { return ResolveSway(cosmetic.playerCosmetics, cosmetic.cosmeticAsset?.assetId); } private static SwayMode? ResolveSway(PlayerCosmetics? playerCosmetics, string? assetId) { if (assetId == null) { return null; } if (TryGetRemoteActor(playerCosmetics, out var actorNumber)) { CustomizerSync.TryGetRemote(actorNumber, assetId, out BridgeSyncPayload data); return data?.EnableSway; } return CustomizerStore.GetEffectiveSway(assetId); } internal static bool IsSwayEnabled(PlayerCosmetics playerCosmetics, string? assetId) { SwayMode? swayMode = ResolveSway(playerCosmetics, assetId); if (swayMode.HasValue) { SwayMode valueOrDefault = swayMode.GetValueOrDefault(); if ((uint)(valueOrDefault - 1) <= 2u) { return true; } } return false; } internal static float GetIntensityFactor(PlayerCosmetics playerCosmetics, string? assetId) { return SwayModeToFactor(ResolveSway(playerCosmetics, assetId)); } internal static float SwayModeToFactor(SwayMode? mode) { return mode switch { SwayMode.Light => 0.35f, SwayMode.Strong => 2.2f, _ => 1f, }; } internal static bool ShouldSuppressSway(CosmeticSprings? springs) { if ((Object)(object)springs == (Object)null) { return false; } Cosmetic val = springs.cosmetic; if ((Object)(object)val == (Object)null) { val = ((Component)springs).GetComponentInParent(); } return ShouldSuppressSway(val); } private static bool TryGetRemoteActor(PlayerCosmetics? instance, out int actorNumber) { actorNumber = -1; if ((Object)(object)instance == (Object)null || !SemiFunc.IsMultiplayer()) { return false; } actorNumber = MiniSemibotSpawner.RemoteMiniActorOf(instance); if (actorNumber > 0) { return true; } PhotonView val = ((Object.op_Implicit((Object)(object)instance.deathHead) && instance.deathHead.setup && Object.op_Implicit((Object)(object)instance.deathHead.playerAvatar)) ? instance.deathHead.playerAvatar.photonView : instance.photonView); if ((Object)(object)val == (Object)null || val.IsMine) { return false; } Player owner = val.Owner; actorNumber = ((owner != null) ? owner.ActorNumber : (-1)); return actorNumber > 0; } internal static void ImpulseBridgeSprings(PlayerCosmetics playerCosmetics, float force, JumpDirection direction, params CosmeticType[] affectedTypes) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) ImpulseCore(playerCosmetics, force, direction, affectedTypes); (PlayerCosmetics, float)? tuple = MiniSemibotSpawner.ActiveMiniOf(playerCosmetics); if (tuple.HasValue) { float num = Mathf.Clamp(tuple.Value.Item2, 0.25f, 1f); ImpulseCore(tuple.Value.Item1, force * num, direction, affectedTypes); } } private static void ImpulseCore(PlayerCosmetics playerCosmetics, float force, JumpDirection direction, CosmeticType[] affectedTypes) { //IL_0033: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = ((affectedTypes.Length != 0) ? new HashSet(affectedTypes) : _allTypes); foreach (Cosmetic item in playerCosmetics.cosmeticEquipped) { if (!((Object)(object)item == (Object)null) && hashSet.Contains(item.type) && BridgeIds.IsCustomizable(item.cosmeticAsset)) { JumpDirection direction2 = ((affectedTypes.Length != 0) ? direction : BridgeSwaySpring.DefaultDirection(item.type)); BridgeSwaySpring[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); foreach (BridgeSwaySpring bridgeSwaySpring in componentsInChildren) { bridgeSwaySpring.Impulse(force, direction2); } } } } } [HarmonyPatch(typeof(PlayerCosmetics), "InstantiateCosmetic")] internal static class BridgeSwaySpringInjectPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance, CosmeticAsset _cosmeticAsset, GameObject __result) { if (!((Object)(object)__result == (Object)null) && BridgeIds.IsBridgeAsset(_cosmeticAsset) && CosmeticSwayHelper.IsSwayEnabled(__instance, _cosmeticAsset.assetId) && __result.GetComponentsInChildren(true).Length == 0) { Cosmetic component = __result.GetComponent(); if (!((Object)(object)component == (Object)null)) { float intensityFactor = CosmeticSwayHelper.GetIntensityFactor(__instance, _cosmeticAsset.assetId); BridgeSwaySpring bridgeSwaySpring = __result.GetComponent() ?? __result.AddComponent(); bridgeSwaySpring.Init(component, intensityFactor); } } } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringJump")] internal static class BridgeSwaySpringJumpPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 10f, (JumpDirection)3); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringLand")] internal static class BridgeSwaySpringLandPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -10f, (JumpDirection)3); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringStandToCrouch")] internal static class BridgeSwaySpringStandToCrouchPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 10f, (JumpDirection)3); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringCrouchToStand")] internal static class BridgeSwaySpringCrouchToStandPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -10f, (JumpDirection)3); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringCrouchToCrawl")] internal static class BridgeSwaySpringCrouchToCrawlPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 5f, (JumpDirection)3); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringCrawlToCrouch")] internal static class BridgeSwaySpringCrawlToCrouchPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -5f, (JumpDirection)3); } } [HarmonyPatch(typeof(PlayerCosmetics), "TumbleStart")] internal static class BridgeSwaySpringTumbleStartPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 10f, (JumpDirection)4); } } [HarmonyPatch(typeof(PlayerCosmetics), "TumbleStop")] internal static class BridgeSwaySpringTumbleStopPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -10f, (JumpDirection)4); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootRightUp")] internal static class BridgeSwaySpringFootRightUpPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 2f, (JumpDirection)3, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootRightDown")] internal static class BridgeSwaySpringFootRightDownPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -2f, (JumpDirection)3, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootLeftUp")] internal static class BridgeSwaySpringFootLeftUpPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 2f, (JumpDirection)2, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootLeftDown")] internal static class BridgeSwaySpringFootLeftDownPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -2f, (JumpDirection)2, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootRightUpSlow")] internal static class BridgeSwaySpringFootRightUpSlowPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 1f, (JumpDirection)3, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootRightDownSlow")] internal static class BridgeSwaySpringFootRightDownSlowPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -1f, (JumpDirection)3, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootLeftUpSlow")] internal static class BridgeSwaySpringFootLeftUpSlowPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, 1f, (JumpDirection)2, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(PlayerCosmetics), "CosmeticSpringFootLeftDownSlow")] internal static class BridgeSwaySpringFootLeftDownSlowPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { CosmeticType[] array = new CosmeticType[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); CosmeticSwayHelper.ImpulseBridgeSprings(__instance, -1f, (JumpDirection)2, (CosmeticType[])(object)array); } } [HarmonyPatch(typeof(CosmeticSprings), "JumpImpulse")] internal static class CosmeticSpringsJumpPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "LandImpulse")] internal static class CosmeticSpringsLandPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "StandToCrouch")] internal static class CosmeticSpringsStandToCrouchPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "CrouchToStand")] internal static class CosmeticSpringsCrouchToStandPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "CrouchToCrawl")] internal static class CosmeticSpringsCrouchToCrawlPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "CrawlToCrouch")] internal static class CosmeticSpringsCrawlToCrouchPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "Impulse")] internal static class CosmeticSpringsImpulsePatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "TumbleStart")] internal static class CosmeticSpringsTumbleStartPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } [HarmonyPatch(typeof(CosmeticSprings), "TumbleStop")] internal static class CosmeticSpringsTumbleStopPatch { [HarmonyPrefix] private static bool Prefix(CosmeticSprings __instance) { return !CosmeticSwayHelper.ShouldSuppressSway(__instance); } } internal sealed class BridgeCustomTypesBroadcaster : MonoBehaviour { internal List Types = new List(); internal PlayerCosmetics? OwnerPc; internal bool SuppressNative; private void Update() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)OwnerPc == (Object)null || Types.Count == 0) { return; } foreach (Type type in Types) { OwnerPc.ConditionCustomSet(type, 0.1f); } } } [HarmonyPatch(typeof(NetworkManager), "OnDisconnected")] internal static class BridgeDisconnectPurge { [HarmonyPostfix] private static void Postfix() { BridgeNetMux.PurgeAll(); MoreHeadCosmeticMountPatch.PurgeAll(); } } internal static class BridgeNetMux { private sealed class Channel { internal readonly string Name; internal readonly Func Build; internal readonly Action OnRemote; internal readonly Action? PurgeActor; internal readonly Action? PurgeAll; internal Channel(string name, Func build, Action onRemote, Action? purgeActor = null, Action? purgeAll = null) { Name = name; Build = build; OnRemote = onRemote; PurgeActor = purgeActor; PurgeAll = purgeAll; } } private const byte EventCode = 187; private const string Magic = "MHB1"; internal const string ChOverrides = "Overrides"; internal const string ChMini = "Mini"; internal const string ChColors = "Colors"; internal const string ChAnims = "Anims"; internal const string ChCustom = "Custom"; internal const string ChSlotAnims = "SlotAnims"; internal const string ChMimicAudio = "MimicAudio"; internal const string ChHideMH = "HideMH"; private const string ChSnapshot = "Snap"; private static readonly Channel[] Channels = new Channel[7] { new Channel("Overrides", CustomizerSync.BuildSection, CustomizerSync.OnRemoteSection, CustomizerSync.PurgeActor, CustomizerSync.PurgeAll), new Channel("Mini", MiniSemibotSync.BuildSection, MiniSemibotSync.OnRemoteSection, MiniSemibotSync.PurgeActor, MiniSemibotSync.PurgeAll), new Channel("HideMH", MoreHeadHideSync.BuildSection, MoreHeadHideSync.OnRemoteSection, MoreHeadHideSync.PurgeActor, MoreHeadHideSync.PurgeAll), new Channel("Colors", PerCosmeticColorNetworkSync.BuildColorsSection, PerCosmeticColorNetworkSync.OnColorSection, PerCosmeticColorNetworkSync.PurgeActor, PerCosmeticColorNetworkSync.PurgeAll), new Channel("Anims", PerCosmeticColorNetworkSync.BuildAnimationsSection, PerCosmeticColorNetworkSync.OnAnimationSection), new Channel("Custom", PerCosmeticColorNetworkSync.BuildCustomColorsSection, PerCosmeticColorNetworkSync.OnCustomColorSection), new Channel("SlotAnims", PerCosmeticColorNetworkSync.BuildSlotAnimationsSection, PerCosmeticColorNetworkSync.OnSlotAnimSection) }; private const int MaxSnapshotChars = 131072; private static readonly Dictionary> _lastBodies = new Dictionary>(); private static bool _subscribed; internal static void Subscribe() { if (!_subscribed) { _subscribed = true; PhotonNetwork.NetworkingClient.EventReceived += OnEvent; Application.quitting += delegate { PhotonNetwork.NetworkingClient.EventReceived -= OnEvent; }; } } internal static void PurgeActor(int actorNumber) { _lastBodies.Remove(actorNumber); Channel[] channels = Channels; foreach (Channel channel in channels) { channel.PurgeActor?.Invoke(actorNumber); } } internal static void PurgeAll() { _lastBodies.Clear(); Channel[] channels = Channels; foreach (Channel channel in channels) { channel.PurgeAll?.Invoke(); } } internal static void BroadcastSnapshot() { if (!SemiFunc.IsMultiplayer()) { return; } Dictionary dictionary = new Dictionary(); Channel[] channels = Channels; foreach (Channel channel in channels) { string text = channel.Build(); if (text != null) { dictionary[channel.Name] = text; } } string json = JsonConvert.SerializeObject((object)dictionary); ClearMyBufferedSnapshot(); SendBufferedSnapshot(json); } private static void ClearMyBufferedSnapshot() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown PhotonNetwork.RaiseEvent((byte)187, (object)"", new RaiseEventOptions { CachingOption = (EventCaching)6 }, SendOptions.SendReliable); } private static void SendBufferedSnapshot(string json) { //IL_001f: 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_0026: 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_002d: 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_003c: Expected O, but got Unknown PhotonNetwork.RaiseEvent((byte)187, (object)new object[3] { "MHB1", "Snap", json }, new RaiseEventOptions { Receivers = (ReceiverGroup)0, CachingOption = (EventCaching)4 }, SendOptions.SendReliable); } internal static void SendTransient(string channel, object body) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown if (SemiFunc.IsMultiplayer()) { PhotonNetwork.RaiseEvent((byte)187, (object)new object[3] { "MHB1", channel, body }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } } private static void OnEvent(EventData ev) { if (ev.Code != 187) { return; } int sender = ev.Sender; if (sender <= 0 || !(ev.CustomData is object[] array) || array.Length != 3 || !(array[0] is string text) || text != "MHB1" || !(array[1] is string text2)) { return; } try { if (text2 == "Snap") { if (array[2] is string { Length: <=131072 } text3) { OnSnapshot(sender, text3); } } else if (text2 == "MimicAudio") { MiniSemibotMimicAudio.OnChunk(sender, array[2]); } } catch (Exception ex) { BridgeLog.Debug($"BridgeNetMux: dropped bad '{text2}' payload from actor {sender} — {ex.Message}"); } } private static void OnSnapshot(int actor, string json) { Dictionary dictionary = JsonConvert.DeserializeObject>(json); if (dictionary == null) { return; } Dictionary orCreateLast = GetOrCreateLast(actor); foreach (KeyValuePair item in dictionary) { string text = item.Value ?? ""; if (!orCreateLast.TryGetValue(item.Key, out var value) || !(value == text)) { try { DispatchSection(actor, item.Key, text); orCreateLast[item.Key] = text; } catch (Exception ex) { BridgeLog.Debug($"BridgeNetMux: section '{item.Key}' from actor {actor} failed — {ex.Message}"); } } } } private static void DispatchSection(int actor, string channel, string body) { Channel[] channels = Channels; foreach (Channel channel2 in channels) { if (!(channel2.Name != channel)) { channel2.OnRemote(actor, body); break; } } } private static Dictionary GetOrCreateLast(int actor) { if (!_lastBodies.TryGetValue(actor, out Dictionary value)) { value = (_lastBodies[actor] = new Dictionary()); } return value; } } [HarmonyPatch(typeof(NetworkManager), "OnPlayerLeftRoom")] internal static class BridgeRoomCallbacks { [HarmonyPostfix] private static void Postfix(Player otherPlayer) { if (otherPlayer != null) { int actorNumber = otherPlayer.ActorNumber; BridgeNetMux.PurgeActor(actorNumber); MoreHeadCosmeticMountPatch.PurgeActor(actorNumber); } } } internal sealed class BridgeSyncPayload { [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter))] public OverrideCosmeticType? Type { get; set; } [JsonProperty("enableSway")] [JsonConverter(typeof(NullableSwayModeConverter))] public SwayMode? EnableSway { get; set; } [JsonProperty("customTypes")] public List? CustomTypes { get; set; } [JsonProperty("offsets")] public List? Offsets { get; set; } [JsonProperty("crown")] public CosmeticCrownConfig? Crown { get; set; } [JsonProperty("fixAnim")] public bool? FixAnimation { get; set; } [JsonProperty("tintable")] public bool? Tintable { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? ShowOnDeathHead { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public DeathHeadFloorPose? FloorPose { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public CosmeticHideConfig? HideConditions { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? AvoidWalls { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public bool? HideOnKart { get; set; } internal static BridgeSyncPayload FromOverrideData(CosmeticOverrideData d) { BridgeSyncPayload obj = new BridgeSyncPayload { Type = d.Type, EnableSway = d.EnableSway }; List customTypes = d.CustomTypes; obj.CustomTypes = ((customTypes != null && customTypes.Count > 0) ? new List(d.CustomTypes) : null); List offsets = d.Offsets; obj.Offsets = ((offsets != null && offsets.Count > 0) ? new List(d.Offsets) : null); obj.Crown = d.Crown?.Clone(); obj.FixAnimation = d.FixAnimation; obj.Tintable = d.Tintable; obj.ShowOnDeathHead = d.ShowOnDeathHead; obj.FloorPose = d.FloorPose?.Clone(); CosmeticHideConfig hideConditions = d.HideConditions; obj.HideConditions = ((hideConditions != null && hideConditions.HasAny) ? d.HideConditions.Clone() : null); return obj; } internal CosmeticOverrideData ToOverrideData() { return new CosmeticOverrideData { Type = Type, EnableSway = EnableSway, CustomTypes = ((CustomTypes != null) ? new List(CustomTypes) : null), Offsets = ((Offsets != null) ? new List(Offsets) : null), Crown = Crown?.Clone(), FixAnimation = FixAnimation, Tintable = Tintable, ShowOnDeathHead = ShowOnDeathHead, FloorPose = FloorPose?.Clone(), HideConditions = HideConditions?.Clone() }; } internal void ClampValues() { if (Type.HasValue && !Enum.IsDefined(typeof(OverrideCosmeticType), Type.Value)) { Type = null; } if (EnableSway.HasValue && !Enum.IsDefined(typeof(SwayMode), EnableSway.Value)) { EnableSway = null; } CustomTypes?.RemoveAll((Type t) => !Enum.IsDefined(typeof(Type), t)); Offsets?.RemoveAll((CosmeticOffsetEntry e) => !Enum.IsDefined(typeof(Type), e.TriggerType)); if (HideConditions != null) { HideConditions.WhenTypes?.RemoveAll((CosmeticType t) => !Enum.IsDefined(typeof(CosmeticType), t)); HideConditions.WhenConditions?.RemoveAll((Type t) => !Enum.IsDefined(typeof(Type), t)); HideConditions.WhenPoses?.RemoveAll((Pose p) => !Enum.IsDefined(typeof(Pose), p)); HideConditions.WhenCosmetics?.RemoveAll((string n) => string.IsNullOrEmpty(n) || n.Length > 128); List whenTypes = HideConditions.WhenTypes; if (whenTypes != null && whenTypes.Count > 20) { HideConditions.WhenTypes.RemoveRange(20, HideConditions.WhenTypes.Count - 20); } List whenConditions = HideConditions.WhenConditions; if (whenConditions != null && whenConditions.Count > 20) { HideConditions.WhenConditions.RemoveRange(20, HideConditions.WhenConditions.Count - 20); } List whenPoses = HideConditions.WhenPoses; if (whenPoses != null && whenPoses.Count > 20) { HideConditions.WhenPoses.RemoveRange(20, HideConditions.WhenPoses.Count - 20); } List whenCosmetics = HideConditions.WhenCosmetics; if (whenCosmetics != null && whenCosmetics.Count > 20) { HideConditions.WhenCosmetics.RemoveRange(20, HideConditions.WhenCosmetics.Count - 20); } if (!HideConditions.HasAny) { HideConditions = null; } } if (CustomTypes != null && CustomTypes.Count > 20) { CustomTypes.RemoveRange(20, CustomTypes.Count - 20); } if (Offsets != null) { if (Offsets.Count > 20) { Offsets.RemoveRange(20, Offsets.Count - 20); } foreach (CosmeticOffsetEntry offset in Offsets) { offset.PosX = Mathf.Clamp(offset.PosX, -100f, 100f); offset.PosY = Mathf.Clamp(offset.PosY, -100f, 100f); offset.PosZ = Mathf.Clamp(offset.PosZ, -100f, 100f); offset.RotX = Mathf.Clamp(offset.RotX, -360f, 360f); offset.RotY = Mathf.Clamp(offset.RotY, -360f, 360f); offset.RotZ = Mathf.Clamp(offset.RotZ, -360f, 360f); offset.ScaleX = Mathf.Clamp(offset.ScaleX, 0.001f, 100f); offset.ScaleY = Mathf.Clamp(offset.ScaleY, 0.001f, 100f); offset.ScaleZ = Mathf.Clamp(offset.ScaleZ, 0.001f, 100f); offset.LerpSpeed = Mathf.Clamp(offset.LerpSpeed, 0.1f, 20f); } } if (Crown != null) { Crown.PosX = Mathf.Clamp(Crown.PosX, -100f, 100f); Crown.PosY = Mathf.Clamp(Crown.PosY, -100f, 100f); Crown.PosZ = Mathf.Clamp(Crown.PosZ, -100f, 100f); Crown.RotX = Mathf.Clamp(Crown.RotX, -360f, 360f); Crown.RotY = Mathf.Clamp(Crown.RotY, -360f, 360f); Crown.RotZ = Mathf.Clamp(Crown.RotZ, -360f, 360f); Crown.ScaleX = Mathf.Clamp(Crown.ScaleX, 0.001f, 100f); Crown.ScaleY = Mathf.Clamp(Crown.ScaleY, 0.001f, 100f); Crown.ScaleZ = Mathf.Clamp(Crown.ScaleZ, 0.001f, 100f); Crown.Priority = Mathf.Clamp(Crown.Priority, -999, 999); } if (FloorPose != null) { FloorPose.PosX = Mathf.Clamp(FloorPose.PosX, -100f, 100f); FloorPose.PosY = Mathf.Clamp(FloorPose.PosY, -100f, 100f); FloorPose.PosZ = Mathf.Clamp(FloorPose.PosZ, -100f, 100f); FloorPose.RotX = Mathf.Clamp(FloorPose.RotX, -360f, 360f); FloorPose.RotY = Mathf.Clamp(FloorPose.RotY, -360f, 360f); FloorPose.RotZ = Mathf.Clamp(FloorPose.RotZ, -360f, 360f); FloorPose.ScaleX = Mathf.Clamp(FloorPose.ScaleX, 0.001f, 100f); FloorPose.ScaleY = Mathf.Clamp(FloorPose.ScaleY, 0.001f, 100f); FloorPose.ScaleZ = Mathf.Clamp(FloorPose.ScaleZ, 0.001f, 100f); FloorPose.LerpSpeed = Mathf.Clamp(FloorPose.LerpSpeed, 0.1f, 20f); } } } internal static class CustomizerSync { private static readonly Dictionary> _remote = new Dictionary>(); private const float RefreshCooldownSeconds = 0.25f; private static readonly Dictionary _lastRefresh = new Dictionary(); private static readonly HashSet _refreshPending = new HashSet(); internal static event Action? OnRemoteDataChanged; internal static void PurgeActor(int actorNumber) { bool flag = _remote.Remove(actorNumber); _lastRefresh.Remove(actorNumber); _refreshPending.Remove(actorNumber); if (flag) { CustomizerSync.OnRemoteDataChanged?.Invoke(actorNumber); } } internal static void PurgeAll() { bool flag = _remote.Count > 0; _remote.Clear(); _lastRefresh.Clear(); _refreshPending.Clear(); if (flag) { CustomizerSync.OnRemoteDataChanged?.Invoke(-1); } } internal static void BroadcastAll() { BridgeNetMux.BroadcastSnapshot(); } internal static string BuildSection() { Dictionary allData = CustomizerStore.GetAllData(); HashSet equippedAssetIds = GetEquippedAssetIds(); Dictionary dictionary = new Dictionary(); bool flag = !Plugin.EnableBridgeTinting.Value; foreach (string item in equippedAssetIds) { BridgeSyncPayload bridgeSyncPayload = null; if (allData.TryGetValue(item, out var value)) { bridgeSyncPayload = BridgeSyncPayload.FromOverrideData(value); } if (WorldFollowPrefs.GetAvoidWalls(item)) { if (bridgeSyncPayload == null) { bridgeSyncPayload = new BridgeSyncPayload(); } bridgeSyncPayload.AvoidWalls = true; } if (WorldFollowPrefs.GetHideOnKart(item)) { if (bridgeSyncPayload == null) { bridgeSyncPayload = new BridgeSyncPayload(); } bridgeSyncPayload.HideOnKart = true; } if (flag && BridgeIds.IsBridgeAsset(item)) { if (bridgeSyncPayload == null) { bridgeSyncPayload = new BridgeSyncPayload(); } BridgeSyncPayload bridgeSyncPayload2 = bridgeSyncPayload; bool? tintable = bridgeSyncPayload2.Tintable; bool valueOrDefault = tintable == true; if (!tintable.HasValue) { valueOrDefault = false; bool? flag2 = (bridgeSyncPayload2.Tintable = valueOrDefault); } } if (bridgeSyncPayload != null) { dictionary[item] = bridgeSyncPayload; } } if (dictionary.Count != 0) { return JsonConvert.SerializeObject((object)dictionary); } return ""; } private static HashSet GetEquippedAssetIds() { HashSet hashSet = new HashSet(); MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return hashSet; } foreach (int item in instance.cosmeticEquipped) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[item]; if ((Object)(object)val != (Object)null) { hashSet.Add(val.assetId); } } } return hashSet; } internal static bool TryGetRemote(int actorNumber, string assetId, out BridgeSyncPayload? data) { data = null; if (_remote.TryGetValue(actorNumber, out Dictionary value)) { return value.TryGetValue(assetId, out data); } return false; } internal static List<(int actorNumber, string nickName, int overrideCount, bool isSteamFriend)> GetRemotePlayersWithData() { List<(int, string, int, bool)> list = new List<(int, string, int, bool)>(); if (!SemiFunc.IsMultiplayer()) { return list; } Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == null) { return list; } foreach (KeyValuePair player in currentRoom.Players) { int key = player.Key; Player value = player.Value; if (value != null && !value.IsLocal) { Dictionary value2; int item = (_remote.TryGetValue(key, out value2) ? value2.Count : 0); string item2 = ((!string.IsNullOrEmpty(value.NickName)) ? value.NickName : $"Player {key}"); bool item3 = IsSteamFriend(GetSteamIdForActor(key)); list.Add((key, item2, item, item3)); } } return list; } private static string? GetSteamIdForActor(int actorNumber) { List list = GameDirector.instance?.PlayerList; if (list == null) { return null; } foreach (PlayerAvatar item in list) { if ((Object)(object)item == (Object)null) { continue; } PhotonView photonView = item.photonView; if ((Object)(object)photonView != (Object)null) { Player owner = photonView.Owner; if (owner != null && owner.ActorNumber == actorNumber) { return item.steamID; } } } return null; } private static bool IsSteamFriend(string? steamIdStr) { //IL_001b: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!ulong.TryParse(steamIdStr, out var result)) { return false; } try { foreach (Friend friend in SteamFriends.GetFriends()) { if (SteamId.op_Implicit(friend.Id) == result) { return true; } } } catch { } return false; } internal static Dictionary? GetRemotePlayerData(int actorNumber) { if (!_remote.TryGetValue(actorNumber, out Dictionary value)) { return null; } return value; } internal static bool HasAnyRemoteData() { if (!SemiFunc.IsMultiplayer()) { return false; } Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == null) { return false; } foreach (KeyValuePair> item in _remote) { if (currentRoom.Players.ContainsKey(item.Key)) { return true; } } return false; } internal static void OnRemoteSection(int actor, string json) { if (string.IsNullOrEmpty(json)) { if (_remote.Remove(actor)) { RequestRemoteRefresh(actor); CustomizerSync.OnRemoteDataChanged?.Invoke(actor); } return; } if (json.Length > 32768) { BceConsole.LogWarning($"OverrideSync: actor={actor} payload too large ({json.Length} chars), ignoring"); return; } Dictionary dictionary = JsonConvert.DeserializeObject>(json); if (dictionary == null) { BceConsole.LogWarning($"OverrideSync: actor={actor} — JSON deserialization returned null"); return; } foreach (BridgeSyncPayload value in dictionary.Values) { value.ClampValues(); } _remote[actor] = dictionary; RequestRemoteRefresh(actor); CustomizerSync.OnRemoteDataChanged?.Invoke(actor); } private static void RequestRemoteRefresh(int actor) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (_lastRefresh.TryGetValue(actor, out var value) && realtimeSinceStartup - value < 0.25f) { if (_refreshPending.Add(actor) && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(TrailingRefresh(actor)); } } else { _lastRefresh[actor] = realtimeSinceStartup; MoreHeadCosmeticMountPatch.RefreshRemoteCosmetics(actor); } } private static IEnumerator TrailingRefresh(int actor) { yield return (object)new WaitForSeconds(0.25f); _refreshPending.Remove(actor); _lastRefresh[actor] = Time.realtimeSinceStartup; MoreHeadCosmeticMountPatch.RefreshRemoteCosmetics(actor); } } internal static class MoreHeadHideSync { private static readonly HashSet _remoteHidden = new HashSet(); internal static string BuildSection() { if (!Plugin.HideMoreHeadDecorations.Value) { return ""; } return "1"; } internal static void OnRemoteSection(int actor, string body) { bool flag = body == "1"; if (flag != _remoteHidden.Contains(actor)) { if (flag) { _remoteHidden.Add(actor); } else { _remoteHidden.Remove(actor); } ApplyToActor(actor, flag); } } internal static void PurgeActor(int actor) { if (_remoteHidden.Remove(actor)) { ApplyToActor(actor, hide: false); } } internal static void PurgeAll() { _remoteHidden.Clear(); } internal static bool IsActorHidden(int actor) { return _remoteHidden.Contains(actor); } internal static void ApplyLocalAndBroadcast() { bool value = Plugin.HideMoreHeadDecorations.Value; int num = 0; PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics pc in array) { if (AvatarIdentity.IsLocalOrMenu(pc)) { SetHider(pc, value); num++; } } BridgeLog.Debug($"HideMoreHeadDecorations={value} applied to {num} local/menu avatar(s)"); CustomizerSync.BroadcastAll(); } private static void ApplyToActor(int actor, bool hide) { PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { PhotonView photonView = val.photonView; if (((photonView != null) ? photonView.Owner : null) != null && val.photonView.Owner.ActorNumber == actor) { SetHider(val, hide); } } } internal static void SetHider(PlayerCosmetics pc, bool hide) { PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if (!((Object)(object)playerAvatarVisuals == (Object)null)) { MoreHeadDecorationHider component = ((Component)playerAvatarVisuals).GetComponent(); if (hide) { (component ?? ((Component)playerAvatarVisuals).gameObject.AddComponent()).Init(((Component)playerAvatarVisuals).transform); } else if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupCosmeticsLogic")] internal static class MoreHeadHideApplyPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { if ((Object)(object)__instance.playerAvatarVisuals == (Object)null) { return; } if (AvatarIdentity.IsLocalOrMenu(__instance)) { MoreHeadHideSync.SetHider(__instance, Plugin.HideMoreHeadDecorations.Value); return; } PhotonView photonView = __instance.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : ((int?)null)); } int num = obj ?? (-1); if (num > 0) { MoreHeadHideSync.SetHider(__instance, MoreHeadHideSync.IsActorHidden(num)); } } } [HarmonyPatch(typeof(RunManager), "Awake")] internal static class BridgeNetMuxSubscribePatch { [HarmonyPostfix] private static void Postfix() { BridgeNetMux.Subscribe(); } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupCosmeticsLogic")] internal static class BridgeSyncBroadcastPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance) { if (SemiFunc.IsMultiplayer() && !((Object)(object)__instance.photonView == (Object)null) && __instance.photonView.IsMine) { CustomizerSync.BroadcastAll(); } } } internal static class BridgeTintHelper { private static readonly string[] PrimaryColorProps = new string[4] { "_AlbedoColor", "_BaseColor", "_Color", "_TintColor" }; private const string EmissionProp = "_EmissionColor"; internal static bool DetectTintable(GameObject prefab) { Renderer[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if ((Object)(object)val2 == (Object)null) { continue; } string[] primaryColorProps = PrimaryColorProps; foreach (string text in primaryColorProps) { if (val2.HasProperty(text)) { return true; } } } } return false; } internal static void InjectBridgeTintMaterials(GameObject go, CosmeticAsset asset, bool? tintableOverride = null) { if (!(tintableOverride ?? asset.tintable)) { return; } Cosmetic cosmetic = go.GetComponentInChildren(true) ?? go.GetComponent(); int num = 0; int num2 = 0; Renderer[] componentsInChildren = go.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)((Component)val).GetComponent() != (Object)null)) { BridgeTintMaterial bridgeTintMaterial = TryAddBridgeTintMaterial(val, asset, cosmetic, num, num2); if (!((Object)(object)bridgeTintMaterial == (Object)null)) { num++; int num3 = num2; Material[]? materials = bridgeTintMaterial.materials; num2 = num3 + ((materials != null) ? materials.Length : val.sharedMaterials.Length); } } } } internal static BridgeTintMaterial? TryAddBridgeTintMaterial(Renderer r, CosmeticAsset asset, Cosmetic? cosmetic, int btmIndex, int materialSlotOffset, bool suppressEmission = false) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)r).GetComponent() != (Object)null) { return null; } Material val = null; Material[] sharedMaterials = r.sharedMaterials; foreach (Material val2 in sharedMaterials) { if ((Object)(object)val2 != (Object)null) { val = val2; break; } } if ((Object)(object)val == (Object)null) { return null; } string text = null; string[] primaryColorProps = PrimaryColorProps; foreach (string text2 in primaryColorProps) { if (val.HasProperty(text2)) { text = text2; break; } } if (text == null) { return null; } bool flag = !suppressEmission && text == "_AlbedoColor" && val.HasProperty("_EmissionColor"); BridgeTintMaterial bridgeTintMaterial = ((Component)r).gameObject.AddComponent(); bridgeTintMaterial.primaryPropId = Shader.PropertyToID(text); bridgeTintMaterial.emissionPropId = (flag ? Shader.PropertyToID("_EmissionColor") : 0); bridgeTintMaterial.hasEmission = flag; bridgeTintMaterial.cosmeticType = asset.type; bridgeTintMaterial.cosmetic = cosmetic; bridgeTintMaterial.btmIndex = btmIndex; bridgeTintMaterial.materialSlotOffset = materialSlotOffset; bridgeTintMaterial.Setup(); return bridgeTintMaterial; } internal static void ApplySlotColorToLiveInstances(CosmeticAsset asset, int flatSlot, int colorIndex) { BridgeTintMaterial[] array = Object.FindObjectsOfType(true); BridgeTintMaterial[] array2 = array; foreach (BridgeTintMaterial bridgeTintMaterial in array2) { if ((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset != (Object)(object)asset || bridgeTintMaterial.materials == null || !RuntimeConfigApplier.IsLivePaintTarget(bridgeTintMaterial.cosmetic?.playerCosmetics)) { continue; } for (int j = 0; j < bridgeTintMaterial.materials.Length; j++) { if (bridgeTintMaterial.SlotIdOf(j) == flatSlot) { if (colorIndex == -1) { bridgeTintMaterial.RestoreOriginalColorInSlot(j); } else { bridgeTintMaterial.ApplyColorToSlot(j, colorIndex); } } } } } internal static void ApplyWholeAssetColorToLiveInstances(CosmeticAsset asset, int colorIndex) { BridgeTintMaterial[] array = Object.FindObjectsOfType(true); foreach (BridgeTintMaterial bridgeTintMaterial in array) { if (!((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset != (Object)(object)asset) && RuntimeConfigApplier.IsLivePaintTarget(bridgeTintMaterial.cosmetic?.playerCosmetics)) { if (colorIndex == -1) { bridgeTintMaterial.RestoreOriginalColor(); } else { bridgeTintMaterial.ApplyColor(colorIndex); } } } } internal static void ApplyWholeAssetRGBToLiveInstances(CosmeticAsset asset, Color color) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) BridgeTintMaterial[] array = Object.FindObjectsOfType(true); foreach (BridgeTintMaterial bridgeTintMaterial in array) { if ((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset == (Object)(object)asset && RuntimeConfigApplier.IsLivePaintTarget(bridgeTintMaterial.cosmetic?.playerCosmetics)) { bridgeTintMaterial.ApplyColorRGB(color); } } } internal static void ApplySlotRGBToLiveInstances(CosmeticAsset asset, int flatSlot, Color color) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) BridgeTintMaterial[] array = Object.FindObjectsOfType(true); foreach (BridgeTintMaterial bridgeTintMaterial in array) { if ((Object)(object)bridgeTintMaterial?.cosmetic?.cosmeticAsset != (Object)(object)asset || bridgeTintMaterial.materials == null || !RuntimeConfigApplier.IsLivePaintTarget(bridgeTintMaterial.cosmetic?.playerCosmetics)) { continue; } for (int j = 0; j < bridgeTintMaterial.materials.Length; j++) { if (bridgeTintMaterial.SlotIdOf(j) == flatSlot) { bridgeTintMaterial.ApplyColorRGBToSlot(j, color); } } } } internal static bool CanBridgeCosmeticReceivePaint(CosmeticAsset? asset) { if ((Object)(object)asset == (Object)null) { return false; } if (!BridgeIds.IsBridgeAsset(asset)) { return false; } if (CustomizerStore.TryGet(asset.assetId, out CosmeticOverrideData data) && data.Tintable.HasValue) { return data.Tintable.Value; } if (!Plugin.EnableBridgeTinting.Value) { return false; } if (!asset.tintable) { return false; } return true; } internal static void ApplyTypeColors(PlayerCosmetics pc) { //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected I4, but got Unknown if ((Object)(object)pc?.playerAvatarVisuals == (Object)null) { return; } BridgeTintMaterial[] componentsInChildren = ((Component)pc.playerAvatarVisuals).GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return; } int[] colorsEquipped = pc.colorsEquipped; if (colorsEquipped == null) { return; } PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; int num; if (!playerAvatarVisuals.isMenuAvatar) { PlayerAvatar playerAvatar = playerAvatarVisuals.playerAvatar; num = ((playerAvatar == null || !playerAvatar.isLocal) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; PerCosmeticColorSyncComponent perCosmeticColorSyncComponent = (flag ? ((Component)pc).GetComponent() : null); BridgeTintMaterial[] array = componentsInChildren; foreach (BridgeTintMaterial bridgeTintMaterial in array) { if ((Object)(object)bridgeTintMaterial == (Object)null) { continue; } string text = bridgeTintMaterial.cosmetic?.cosmeticAsset?.assetId; CosmeticAsset val = bridgeTintMaterial.cosmetic?.cosmeticAsset; bool flag2 = (Object)(object)val != (Object)null && BridgeIds.IsBridgeAsset(val); bool flag3 = (Object)(object)val != (Object)null && !flag2 && ModdedSlotLayout.Handles(val); if (flag2 || flag3) { bool flag4; if (flag) { flag4 = PerCosmeticColors.FeatureEnabled && text != null && (Object)(object)perCosmeticColorSyncComponent != (Object)null && perCosmeticColorSyncComponent.HasRemoteOverride(text); } else { bool effectiveCustomColors = CustomizerStore.GetEffectiveCustomColors(val); bool effectiveColorAnimations = CustomizerStore.GetEffectiveColorAnimations(val); flag4 = PerCosmeticColors.FeatureEnabled && text != null && (PerCosmeticColors.HasOverride(text) || (effectiveColorAnimations && PerCosmeticColors.HasAnimation(text)) || (effectiveCustomColors && (PerCosmeticColors.HasCustomColor(text) || PerCosmeticColors.HasAnyCustomSlotColor(text)))); } if (flag4) { continue; } if (flag2) { bridgeTintMaterial.RestoreOriginalColor(); continue; } } if (PerCosmeticColors.IsOriginalMode(text)) { continue; } int num2 = (int)bridgeTintMaterial.cosmeticType; if (num2 >= 0 && num2 < colorsEquipped.Length) { int num3 = colorsEquipped[num2]; if (num3 >= 0) { bridgeTintMaterial.ApplyColor(num3); } } } } } internal sealed class BridgeTintMaterial : MonoBehaviour { internal Material[]? materials; internal int primaryPropId; internal int emissionPropId; internal bool hasEmission; internal CosmeticType cosmeticType; internal Cosmetic? cosmetic; internal int btmIndex; internal int materialSlotOffset; internal int[]? slotIds; internal Color[]? originalPrimaryColors; internal Color[]? originalEmissionColors; private bool _setup; internal int SlotIdOf(int localIndex) { if (slotIds == null || localIndex < 0 || localIndex >= slotIds.Length) { return materialSlotOffset + localIndex; } return slotIds[localIndex]; } internal void EnsureSetup() { if (!_setup) { Setup(); } } internal void Setup() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (_setup) { return; } Renderer component = ((Component)this).GetComponent(); if ((Object)(object)component == (Object)null) { return; } materials = component.materials; originalPrimaryColors = (Color[]?)(object)new Color[materials.Length]; originalEmissionColors = (Color[]?)(object)new Color[materials.Length]; for (int i = 0; i < materials.Length; i++) { Material val = materials[i]; if (!((Object)(object)val == (Object)null) && val.HasProperty(primaryPropId)) { originalPrimaryColors[i] = val.GetColor(primaryPropId); if (hasEmission && val.HasProperty(emissionPropId)) { originalEmissionColors[i] = val.GetColor(emissionPropId); } } } Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Collider val2 in componentsInChildren) { val2.isTrigger = true; } _setup = true; } internal void ApplyColor(int colorIndex) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) EnsureSetup(); if (!_setup || materials == null || MetaManager.instance?.colors == null || colorIndex < 0 || colorIndex >= MetaManager.instance.colors.Count) { return; } Color color = MetaManager.instance.colors[colorIndex].color; for (int i = 0; i < materials.Length; i++) { Material val = materials[i]; if (!((Object)(object)val == (Object)null) && val.HasProperty(primaryPropId)) { TintSlot(val, color, color); } } } internal void ApplyColorRGB(Color c) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) EnsureSetup(); if (!_setup || materials == null) { return; } for (int i = 0; i < materials.Length; i++) { Material val = materials[i]; if (!((Object)(object)val == (Object)null) && val.HasProperty(primaryPropId)) { TintSlot(val, c, c); } } } internal void ApplyColorToSlot(int localSlot, int colorIndex) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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) EnsureSetup(); if (_setup && materials != null && localSlot >= 0 && localSlot < materials.Length && MetaManager.instance?.colors != null && colorIndex >= 0 && colorIndex < MetaManager.instance.colors.Count) { Material val = materials[localSlot]; if (!((Object)(object)val == (Object)null) && val.HasProperty(primaryPropId)) { Color color = MetaManager.instance.colors[colorIndex].color; TintSlot(val, color, color); } } } internal void ApplyColorRGBToSlot(int localSlot, Color c) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) EnsureSetup(); if (_setup && materials != null && localSlot >= 0 && localSlot < materials.Length) { Material val = materials[localSlot]; if (!((Object)(object)val == (Object)null) && val.HasProperty(primaryPropId)) { TintSlot(val, c, c); } } } internal void RestoreOriginalColorInSlot(int localSlot) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) EnsureSetup(); if (_setup && materials != null && originalPrimaryColors != null && originalEmissionColors != null && localSlot >= 0 && localSlot < materials.Length) { Material val = materials[localSlot]; if (!((Object)(object)val == (Object)null) && val.HasProperty(primaryPropId)) { TintSlot(val, originalPrimaryColors[localSlot], originalEmissionColors[localSlot]); } } } internal void RestoreOriginalColor() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) EnsureSetup(); if (!_setup || materials == null || originalPrimaryColors == null || originalEmissionColors == null) { return; } for (int i = 0; i < materials.Length; i++) { Material val = materials[i]; if (!((Object)(object)val == (Object)null) && val.HasProperty(primaryPropId)) { TintSlot(val, originalPrimaryColors[i], originalEmissionColors[i]); } } } private void TintSlot(Material mat, Color primaryRgb, Color emissionRgb) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0026: 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) //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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) Color color = mat.GetColor(primaryPropId); mat.SetColor(primaryPropId, new Color(primaryRgb.r, primaryRgb.g, primaryRgb.b, color.a)); if (hasEmission && mat.HasProperty(emissionPropId)) { Color color2 = mat.GetColor(emissionPropId); mat.SetColor(emissionPropId, new Color(emissionRgb.r, emissionRgb.g, emissionRgb.b, color2.a)); } } } internal static class ModdedSlotLayout { private const string YoshiPrefix = "yoshicarry:bbm"; private const string BodyBot = "mesh_body_bot"; private const string LegL = "mesh_leg_l"; private const string LegR = "mesh_leg_r"; internal static bool Handles(CosmeticAsset? asset) { if ((Object)(object)asset != (Object)null) { return (asset.assetId ?? "").StartsWith("yoshicarry:bbm", StringComparison.OrdinalIgnoreCase); } return false; } private static bool IsCustom(CosmeticAsset asset) { string text = asset.assetId ?? ""; if (text.Length <= "yoshicarry:bbm".Length) { return false; } return text.Substring("yoshicarry:bbm".Length).StartsWith("custom", StringComparison.OrdinalIgnoreCase); } internal static int SlotCount(CosmeticAsset asset) { if (!IsCustom(asset)) { return 3; } return 4; } internal static int SlotIdForRenderer(CosmeticAsset asset, GameObject go) { bool flag = IsCustom(asset); int result = (flag ? 1 : 0); int result2 = ((!flag) ? 1 : 2); int result3 = (flag ? 3 : 2); switch (((Object)go).name) { case "mesh_body_bot": return result; case "mesh_leg_l": return result2; case "mesh_leg_r": return result3; default: if (!flag) { return -1; } return 0; } } } internal static class ModdedTintInjector { internal static void Inject(Cosmetic? cosmetic) { if ((Object)(object)cosmetic == (Object)null) { return; } CosmeticAsset cosmeticAsset = cosmetic.cosmeticAsset; if ((Object)(object)cosmeticAsset == (Object)null || !ModdedSlotLayout.Handles(cosmeticAsset) || !PerCosmeticColors.FeatureEnabled) { return; } int num = 0; PlayerMaterial[] componentsInChildren = ((Component)cosmetic).GetComponentsInChildren(true); foreach (PlayerMaterial val in componentsInChildren) { if ((Object)(object)val == (Object)null || !val.tintable) { continue; } Renderer component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { continue; } int num2 = ModdedSlotLayout.SlotIdForRenderer(cosmeticAsset, ((Component)val).gameObject); if (num2 < 0) { continue; } BridgeTintMaterial bridgeTintMaterial = BridgeTintHelper.TryAddBridgeTintMaterial(component, cosmeticAsset, cosmetic, num, num2, suppressEmission: true); if (!((Object)(object)bridgeTintMaterial == (Object)null)) { num++; Material[]? materials = bridgeTintMaterial.materials; int num3 = ((materials == null) ? 1 : materials.Length); int[] array = new int[num3]; for (int j = 0; j < num3; j++) { array[j] = num2; } bridgeTintMaterial.slotIds = array; val.tintable = false; } } } } [HarmonyPatch(typeof(Cosmetic), "Setup")] internal static class ModdedTintInjectorPatch { [HarmonyPrefix] private static void Prefix(Cosmetic __instance) { ModdedTintInjector.Inject(__instance); } } internal static class VanillaTintHelper { private static readonly LazyFieldRef _materialRef = new LazyFieldRef("material", "custom RGB colors"); private static Material? MaterialOf(PlayerMaterial pm) { if (!_materialRef.TryGet(pm, out Material value)) { return null; } return value; } internal static bool IsEligibleForCustomColor(CosmeticAsset? asset) { if ((Object)(object)asset == (Object)null || BridgeIds.IsBridgeAsset(asset)) { return false; } if (!asset.tintable) { return false; } return CustomizerStore.GetEffectiveCustomColors(asset); } internal static void ApplyCustomRGB(PlayerMaterial pm, Color color) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_005e: 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) //IL_0032: Invalid comparison between Unknown and I4 //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pm == (Object)null || !pm.tintable) { return; } Material val = MaterialOf(pm); if (!((Object)(object)val == (Object)null)) { if ((int)pm.tintType == 0 || (int)pm.tintType == 2) { Color color2 = val.GetColor(PerCosmeticColors.PropAlbedo); val.SetColor(PerCosmeticColors.PropAlbedo, new Color(color.r, color.g, color.b, color2.a)); } if ((int)pm.tintType == 1 || (int)pm.tintType == 2) { Color color3 = val.GetColor(PerCosmeticColors.PropEmission); val.SetColor(PerCosmeticColors.PropEmission, new Color(color.r, color.g, color.b, color3.a)); } if (pm.tintFresnel) { val.SetColor(PerCosmeticColors.PropFresnel, new Color(color.r, color.g, color.b, color.a)); } } } internal static void RepaintPalette(PlayerMaterial pm, PlayerCosmetics pc) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected I4, but got Unknown int num = (int)pm.cosmeticType; int[] colorsEquipped = pc.colorsEquipped; if (colorsEquipped != null && num >= 0 && num < colorsEquipped.Length) { int num2 = colorsEquipped[num]; if (num2 >= 0 && !((Object)(object)MetaManager.instance == (Object)null) && num2 < MetaManager.instance.colors.Count) { pm.ColorSet(PerCosmeticColors.PropAlbedo, PerCosmeticColors.PropEmission, PerCosmeticColors.PropFresnel, num2); } } } internal static void ApplyCustomRGBToLiveInstances(CosmeticAsset asset, Color color) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val in array) { if (val?.playerMaterials == null || !RuntimeConfigApplier.IsLivePaintTarget(val)) { continue; } foreach (PlayerMaterial playerMaterial in val.playerMaterials) { if (!((Object)(object)playerMaterial == (Object)null) && playerMaterial.tintable && !((Object)(object)playerMaterial.cosmetic?.cosmeticAsset != (Object)(object)asset)) { ApplyCustomRGB(playerMaterial, color); } } } } internal static string BaseMeshAssetId(int cosmeticTypeIndex) { return $"__base_{cosmeticTypeIndex}__"; } internal static bool IsBaseMeshId(string assetId) { if (assetId.StartsWith("__base_")) { return assetId.EndsWith("__"); } return false; } internal static void ReapplyBaseMeshColors(PlayerCosmetics? pc) { if (!Plugin.EnableVanillaCustomColors.Value || pc?.playerMaterials == null) { return; } PlayerAvatarVisuals playerAvatarVisuals = pc.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null) { return; } if (!playerAvatarVisuals.isMenuAvatar) { PlayerAvatar playerAvatar = playerAvatarVisuals.playerAvatar; if (playerAvatar == null || !playerAvatar.isLocal) { return; } } if (AvatarIdentity.IsRemoteMini(pc)) { return; } if (!PerCosmeticColors.MiniPresetContextActive) { int num = MiniSemibotSpawner.PresetSlotOf(pc); if (num >= 0) { PerCosmeticColors.RunWithPresetContext(num, delegate { ReapplyBaseMeshColors(pc); }); return; } } foreach (PlayerMaterial playerMaterial in pc.playerMaterials) { if (!((Object)(object)playerMaterial == (Object)null) && !((Object)(object)playerMaterial.cosmetic != (Object)null) && playerMaterial.tintable) { PerCosmeticColors.ApplyBaseMeshColor(playerMaterial, pc.colorsEquipped); } } } internal static bool IsEligibleForSectionCustom(CosmeticAsset asset) { if (!asset.tintable) { return false; } return CustomizerStore.GetEffectiveCustomColors(asset); } internal static bool HasAnyTintableForSection(MenuPageColor menuPageColor) { //IL_00a4: 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) MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return false; } int num = (SectionColorButtonPatch.PendingWorldSection ? 2147483646 : menuPageColor.colorKey); foreach (int item in instance.cosmeticEquipped) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && IsEligibleForSectionCustom(val) && CosmeticMatchesSection(val, num, menuPageColor.pageMode)) { return true; } } } if (BaseMeshTypesForSection(num, menuPageColor.pageMode).Count > 0) { return true; } return false; } private static List BaseMeshTypesForSection(int ck, ColorPageType pageMode) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected I4, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 List list = new List(); if (!Plugin.EnableVanillaCustomColors.Value) { return list; } if (ck == 2147483646) { return list; } List list2 = MetaManager.instance?.cosmeticTypeAssets; if (list2 == null) { return list; } foreach (CosmeticTypeAsset item in list2) { if ((Object)(object)item == (Object)null || !item.meshSwitch) { continue; } int num = (int)item.type; if (ck >= 0) { if (num != ck) { continue; } } else if ((int)pageMode == 1) { continue; } if (HasTintableBaseMesh(num)) { list.Add(num); } } return list; } internal static bool RemoveSectionBaseMeshCustomsNoSave(int colorKey, ColorPageType pageMode) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) bool flag = false; foreach (int item in BaseMeshTypesForSection(colorKey, pageMode)) { flag |= PerCosmeticColors.RemoveCustomColorNoSave(BaseMeshAssetId(item)); } return flag; } internal static bool HasTintableBaseMesh(int cosmeticTypeIndex) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 List list = PlayerAvatar.instance?.playerCosmetics?.cosmeticParents; if (list == null) { return false; } foreach (CosmeticParent item in list) { if ((int)item.cosmeticType != cosmeticTypeIndex) { continue; } foreach (Transform baseMesh in item.baseMeshes) { PlayerMaterial component = ((Component)baseMesh).GetComponent(); if ((Object)(object)component != (Object)null && component.tintable) { return true; } } } return false; } internal static void ApplyCustomRGBToSectionLive(int colorKey, ColorPageType pageMode, Color color) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected I4, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return; } int num = (SectionColorButtonPatch.PendingWorldSection ? 2147483646 : colorKey); foreach (int item in instance.cosmeticEquipped) { if (item < 0 || item >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && IsEligibleForSectionCustom(val) && CosmeticMatchesSection(val, num, pageMode)) { if (BridgeIds.IsBridgeAsset(val)) { BridgeTintHelper.ApplyWholeAssetRGBToLiveInstances(val, color); } else { ApplyCustomRGBToLiveInstances(val, color); } } } List list = BaseMeshTypesForSection(num, pageMode); if (list.Count <= 0) { return; } PlayerCosmetics[] array = Object.FindObjectsOfType(true); foreach (PlayerCosmetics val2 in array) { if (val2?.playerMaterials == null || !RuntimeConfigApplier.IsLivePaintTarget(val2)) { continue; } foreach (PlayerMaterial playerMaterial in val2.playerMaterials) { if (!((Object)(object)playerMaterial == (Object)null) && playerMaterial.tintable && !((Object)(object)playerMaterial.cosmetic != (Object)null) && list.Contains((int)playerMaterial.cosmeticType)) { ApplyCustomRGB(playerMaterial, color); } } } } internal static void SaveCustomColorToSection(int colorKey, ColorPageType pageMode, Color color) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return; } int num = (SectionColorButtonPatch.PendingWorldSection ? 2147483646 : colorKey); bool flag = false; bool flag2 = false; foreach (int item in instance.cosmeticEquipped) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && IsEligibleForSectionCustom(val) && CosmeticMatchesSection(val, num, pageMode)) { PerCosmeticColors.SetCustomColorNoSave(val.assetId, color); flag = true; flag2 = true; } } } foreach (int item2 in BaseMeshTypesForSection(num, pageMode)) { PerCosmeticColors.SetCustomColorNoSave(BaseMeshAssetId(item2), color); flag = true; } if (flag) { PerCosmeticColors.SaveCustom(); PerCosmeticColors.Save(); PerCosmeticColors.SaveSlots(); PerCosmeticColors.SaveAnimations(); PerCosmeticColors.SaveSlotAnimations(); PerCosmeticColors.SaveCustomSlots(); if (flag2) { ColorAnimatorRefresher.RefreshLocal(); } RuntimeConfigApplier.ReapplyLocalCosmeticColors(); if (SemiFunc.IsMultiplayer()) { PerCosmeticColorNetworkSync.BroadcastAll(); } } } internal static void RemoveCustomColorFromSection(int colorKey, ColorPageType pageMode) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return; } int num = (SectionColorButtonPatch.PendingWorldSection ? 2147483646 : colorKey); bool flag = false; foreach (int item in instance.cosmeticEquipped) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && IsEligibleForSectionCustom(val) && CosmeticMatchesSection(val, num, pageMode) && PerCosmeticColors.RemoveCustomColorNoSave(val.assetId)) { flag = true; } } } foreach (int item2 in BaseMeshTypesForSection(num, pageMode)) { if (PerCosmeticColors.RemoveCustomColorNoSave(BaseMeshAssetId(item2))) { flag = true; } } if (flag) { PerCosmeticColors.SaveCustom(); RuntimeConfigApplier.ReapplyLocalCosmeticColors(); if (SemiFunc.IsMultiplayer()) { PerCosmeticColorNetworkSync.BroadcastAll(); } } } internal static bool CosmeticMatchesSection(CosmeticAsset asset, int colorKey, ColorPageType pageMode) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_001f: Invalid comparison between Unknown and I4 bool flag = HhhCosmeticLoader.IsWorldAsset(asset); if (colorKey == 2147483646) { return flag; } if (flag) { bool flag2 = colorKey < 0; bool flag3 = (int)pageMode == 2; if (flag2) { return !flag3; } return false; } return SectionTypeScope(asset.type, colorKey, pageMode); } internal static bool SectionTypeScope(CosmeticType type, int colorKey, ColorPageType pageMode) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected I4, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 if (colorKey >= 0) { return (int)type == colorKey; } if ((int)pageMode == 0) { return true; } MetaManager instance = MetaManager.instance; int num = (int)type; if (instance?.cosmeticTypeAssets == null || num < 0 || num >= instance.cosmeticTypeAssets.Count) { return true; } bool meshSwitch = instance.cosmeticTypeAssets[num].meshSwitch; if ((int)pageMode != 1) { return meshSwitch; } return !meshSwitch; } } public enum FollowSpringMode { Off, Soft, Springy } internal struct FollowSpring { private Vector3 _vel; private bool _seeded; private const float TeleportDistance = 4f; private static (float k, float c) Tuning(FollowSpringMode mode) { if (mode == FollowSpringMode.Springy) { return (k: 160f, c: 17f); } return (k: 130f, c: 23f); } internal Vector3 StepPosition(Vector3 current, Vector3 target, float dt, FollowSpringMode mode) { //IL_000d: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0028: 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_002a: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00b7: Unknown result type (might be due to invalid IL or missing references) if (mode == FollowSpringMode.Off || dt <= 0f) { _vel = Vector3.zero; _seeded = true; return target; } if (_seeded) { Vector3 val = current - target; if (!(((Vector3)(ref val)).sqrMagnitude > 16f)) { dt = Mathf.Min(dt, 0.05f); (float k, float c) tuple = Tuning(mode); float item = tuple.k; float item2 = tuple.c; Vector3 val2 = (target - current) * item - _vel * item2; _vel += val2 * dt; return current + _vel * dt; } } _vel = Vector3.zero; _seeded = true; return target; } internal static Quaternion StepRotation(Quaternion current, Quaternion target, float dt, FollowSpringMode mode) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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: Unknown result type (might be due to invalid IL or missing references) if (mode == FollowSpringMode.Off || dt <= 0f) { return target; } float num = ((mode == FollowSpringMode.Springy) ? 9f : 13f); return Quaternion.Slerp(current, target, 1f - Mathf.Exp((0f - num) * dt)); } } [DefaultExecutionOrder(32000)] internal sealed class MiniCrownDriver : MonoBehaviour { private static readonly FieldInfo? PlayerAvatarField = AccessTools.Field(typeof(PlayerCrown), "playerAvatar"); private static readonly FieldInfo? CrownCurrentField = AccessTools.Field(typeof(PlayerCrown), "cosmeticPlayerCrownCurrent"); internal PlayerAvatar? WearerAvatar; internal MiniSemibotFollow? Follow; private PlayerCrown? _crown; private float _retargetTimer; private void Awake() { _crown = ((Component)this).GetComponentInChildren(true); } private void LateUpdate() { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_crown == (Object)null) { return; } if ((Object)(object)WearerAvatar == (Object)null && (Object)(object)Follow != (Object)null && (Object)(object)Follow.WearerVisuals != (Object)null) { WearerAvatar = Follow.WearerVisuals.playerAvatar; } if ((Object)(object)WearerAvatar != (Object)null && PlayerAvatarField != null && PlayerAvatarField.GetValue(_crown) != WearerAvatar) { PlayerAvatarField.SetValue(_crown, WearerAvatar); } _retargetTimer -= Time.deltaTime; if (_retargetTimer <= 0f) { _retargetTimer = 0.5f; _crown.UpdateTarget(); } object? obj = CrownCurrentField?.GetValue(_crown); CosmeticPlayerCrown val = (CosmeticPlayerCrown)((obj is CosmeticPlayerCrown) ? obj : null); Transform val2 = null; if ((Object)(object)val != (Object)null) { val2 = (((Object)(object)val.cosmeticBlocked == (Object)null) ? val.targetMain : (val.cosmeticBlocked.blocked ? val.targetBlocked : val.targetUnblocked)); } if ((Object)(object)val2 == (Object)null) { val2 = _crown.defaultPosition; } if ((Object)(object)val2 != (Object)null) { ((Component)_crown).transform.position = val2.position; ((Component)_crown).transform.rotation = val2.rotation; if ((Object)(object)val != (Object)null && val.disableSpring && (Object)(object)_crown.spring?.transform != (Object)null) { _crown.spring.transform.localRotation = val2.localRotation; } } PlayerCrown val3 = (((Object)(object)Follow != (Object)null && (Object)(object)Follow.WearerVisuals != (Object)null && (Object)(object)Follow.WearerVisuals.playerCosmetics != (Object)null) ? Follow.WearerVisuals.playerCosmetics.playerCrown : null); bool flag = (Object)(object)val3 != (Object)null && (Object)(object)val3.crownMesh != (Object)null && ((Component)val3.crownMesh).gameObject.activeInHierarchy && (!((Object)(object)Follow != (Object)null) || !Follow.BodyHidden); if ((Object)(object)_crown.crownMesh != (Object)null && ((Component)_crown.crownMesh).gameObject.activeSelf != flag) { ((Component)_crown.crownMesh).gameObject.SetActive(flag); } } } internal sealed class MiniDeathHead { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func <>9__9_0; public static Func <>9__9_3; public static Func <>9__9_4; public static Func <>9__9_2; internal AnimSet b__9_0(string _) { return default(AnimSet); } internal AnimSet b__9_3(string _) { return default(AnimSet); } internal AnimSet b__9_4(string _) { return default(AnimSet); } internal AnimSet b__9_2(string id) { if (!CustomizerStore.GetEffectiveColorAnimations(id)) { return default(AnimSet); } return PerCosmeticColors.GetAnimSet(id); } } private DeathHeadPreviewInstance? _instance; private GameObject? _holder; private bool _built; private bool _failed; private int _builtStoreVersion = -1; internal bool ShowAt(PlayerAvatarVisuals miniVisuals, Vector3 worldPos, Quaternion rot, float scale, bool crown) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (_failed) { return false; } if (_built && _builtStoreVersion >= 0 && _builtStoreVersion != PerCosmeticColors.StoreVersion) { Destroy(); } if (!_built && !Build(miniVisuals, crown)) { return false; } if ((Object)(object)_holder != (Object)null) { _holder.transform.position = worldPos; _holder.transform.rotation = rot; _holder.transform.localScale = Vector3.one * Mathf.Max(0.0001f, scale); } return true; } private bool Build(PlayerAvatarVisuals miniVisuals, bool crown) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown _built = true; PlayerCosmetics miniPc = (((Object)(object)miniVisuals != (Object)null) ? miniVisuals.playerCosmetics : null); if ((Object)(object)miniPc == (Object)null) { _failed = true; return false; } _builtStoreVersion = (AvatarIdentity.IsRemoteMini(miniPc) ? (-1) : PerCosmeticColors.StoreVersion); try { _holder = new GameObject("MHB_MiniDeathHead"); _instance = new DeathHeadPreviewInstance(); int num = MiniSemibotSpawner.PresetSlotOf(miniPc); bool flag; if (num >= 0) { bool ok = false; PerCosmeticColors.RunWithPresetContext(num, delegate { ok = _instance.TryEnsure(_holder.transform, miniPc); }); flag = ok; } else { flag = _instance.TryEnsure(_holder.transform, miniPc); } if (!flag) { Destroy(); _failed = true; return false; } _instance.SetAnimOverride(BuildAnimResolver(miniPc)); GameObject val = (((Object)(object)miniVisuals != (Object)null) ? ((Component)miniVisuals).gameObject : null); bool flag2 = false; if ((Object)(object)val != (Object)null && !val.activeSelf) { val.SetActive(true); flag2 = true; } try { List<(GameObject, CosmeticAsset)> list = GatherMiniCosmetics(miniPc); foreach (var item2 in list) { GameObject item = item2.Item1; if ((Object)(object)item != (Object)null) { CosmeticEquipAnimation.Finish(item); } } _instance.MountCosmetics(list, null); } finally { if (flag2 && (Object)(object)val != (Object)null) { val.SetActive(false); } } _instance.ApplyOffset(null); _instance.ApplyDeathHeadOffsets(BuildDeathHeadOffsetResolver(miniPc)); _instance.SetCrownVisible(crown); _instance.Show(show: true); return true; } catch { Destroy(); _failed = true; return false; } } private static List<(GameObject go, CosmeticAsset asset)> GatherMiniCosmetics(PlayerCosmetics pc) { List<(GameObject, CosmeticAsset)> list = new List<(GameObject, CosmeticAsset)>(); int actor; bool isRemote = AvatarIdentity.TryGetRemoteActor(pc, out actor); List equippedCosmetics = MoreHeadCosmeticMountPatch.GetEquippedCosmetics(pc); if (equippedCosmetics != null) { foreach (Cosmetic item2 in equippedCosmetics) { if (!((Object)(object)item2 == (Object)null)) { CosmeticAsset cosmeticAsset = MoreHeadCosmeticMountPatch.GetCosmeticAsset(item2); if ((Object)(object)cosmeticAsset != (Object)null && Supported(cosmeticAsset)) { list.Add((((Component)item2).gameObject, cosmeticAsset)); } } } } return list; bool Supported(CosmeticAsset asset) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) CosmeticType item; if (isRemote) { CustomizerSync.TryGetRemote(actor, asset.assetId, out BridgeSyncPayload data); item = MoreHeadCosmeticMountPatch.GetRemoteEffectiveType(asset, data).cosmeticType; } else { item = asset.type; } if (DeathHeadPrefabProvider.SupportedTypes.Contains(item)) { return !BridgeDeathHeadGameplayMount.IsHiddenOnDeathHead(asset, isRemote, actor); } return false; } } private static Func BuildDeathHeadOffsetResolver(PlayerCosmetics miniPc) { int actor; bool isRemote = AvatarIdentity.TryGetRemoteActor(miniPc, out actor); return delegate(string id) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 List list; if (isRemote) { CustomizerSync.TryGetRemote(actor, id, out BridgeSyncPayload data); list = data?.Offsets; } else { CustomizerStore.TryGet(id, out CosmeticOverrideData data2); list = data2?.Offsets; } if (list == null) { return (CosmeticOffsetEntry?)null; } foreach (CosmeticOffsetEntry item in list) { if ((int)item.TriggerType == 2) { return item; } } return (CosmeticOffsetEntry?)null; }; } private static Func BuildAnimResolver(PlayerCosmetics miniPc) { if (!PerCosmeticColors.FeatureEnabled || !Plugin.EnableBridgeColorAnimations.Value) { return (string _) => default(AnimSet); } if (AvatarIdentity.IsRemoteMini(miniPc)) { if (!Plugin.SeeRemoteColorAnimations.Value) { return (string _) => default(AnimSet); } PerCosmeticColorSyncComponent component = ((Component)miniPc).GetComponent(); Func func; if (!((Object)(object)component != (Object)null)) { func = <>c.<>9__9_4; if (func == null) { return <>c.<>9__9_4 = (string _) => default(AnimSet); } } else { func = component.GetRemoteAnimSet; } return func; } int slot = MiniSemibotSpawner.PresetSlotOf(miniPc); if (slot >= 0) { return delegate(string id) { AnimSet r = default(AnimSet); PerCosmeticColors.RunWithPresetContext(slot, delegate { r = (CustomizerStore.GetEffectiveColorAnimations(id) ? PerCosmeticColors.GetPreviewAnimSet(id) : default(AnimSet)); }); return r; }; } return (string id) => (!CustomizerStore.GetEffectiveColorAnimations(id)) ? default(AnimSet) : PerCosmeticColors.GetAnimSet(id); } internal void Destroy() { _instance?.Destroy(); _instance = null; if ((Object)(object)_holder != (Object)null) { Object.Destroy((Object)(object)_holder); _holder = null; } _built = false; _failed = false; } } internal sealed class MiniFlashlightHold : MonoBehaviour { private const float IntensityScale = 0.35f; private const float ArmPoseSpeed = 6f; private const float ForwardNudge = 0.1f; internal PlayerAvatar? WearerAvatar; internal MiniSemibotFollow? Follow; private FlashlightController? _src; private float _searchTimer; private GameObject? _clone; private Light? _cloneLight; private bool _buildFailed; private Transform? _leftArm; private Vector3 _basePose; private Vector3 _flashPose; private bool _armResolved; private float _armLerp; private void LateUpdate() { PlayerAvatarVisuals val = (((Object)(object)Follow != (Object)null) ? Follow.MiniVisuals : null); if ((Object)(object)_src == (Object)null || (Object)(object)_src.PlayerAvatar != (Object)(object)WearerAvatar) { _src = null; _searchTimer -= Time.deltaTime; if (_searchTimer <= 0f) { _searchTimer = 1f; FlashlightController[] array = Object.FindObjectsOfType(); foreach (FlashlightController val2 in array) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2.PlayerAvatar == (Object)(object)WearerAvatar) { _src = val2; break; } } } } bool flag = MiniSemibotVisualPrefs.MiniFlashlight && ((Object)(object)Follow == (Object)null || !MiniSemibotSpawner.IsMenuOrPreviewWearer(Follow.WearerVisuals)) && ((Object)(object)Follow == (Object)null || !Follow.BodyHidden) && (Object)(object)_src != (Object)null && (Object)(object)_src.mesh != (Object)null && ((Renderer)_src.mesh).enabled && (Object)(object)val != (Object)null; DriveArm(flag, val); if (!flag) { if ((Object)(object)_clone != (Object)null && _clone.activeSelf) { _clone.SetActive(false); } return; } if ((Object)(object)_clone == (Object)null && !_buildFailed) { BuildClone(_src, val); } if ((Object)(object)_clone == (Object)null) { return; } if (!_clone.activeSelf) { _clone.SetActive(true); } if ((Object)(object)_cloneLight != (Object)null) { float scale = MiniSemibotSync.Resolve(WearerAvatar).Scale; Light spotlight = _src.spotlight; bool flag2 = (Object)(object)spotlight != (Object)null && ((Behaviour)spotlight).enabled && spotlight.intensity > 0.01f; ((Behaviour)_cloneLight).enabled = flag2; if (flag2) { _cloneLight.intensity = spotlight.intensity * 0.35f; _cloneLight.range = spotlight.range * Mathf.Clamp(scale, 0.2f, 1f); _cloneLight.spotAngle = spotlight.spotAngle; } } } private void DriveArm(bool want, PlayerAvatarVisuals? mv) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) ResolveArm(mv); if (!((Object)(object)_leftArm == (Object)null)) { _armLerp = Mathf.MoveTowards(_armLerp, want ? 1f : 0f, 6f * Time.deltaTime); if (!(_armLerp <= 0.001f)) { Vector3 localEulerAngles = Vector3.Lerp(_basePose, _flashPose, _armLerp); _leftArm.localEulerAngles = localEulerAngles; } } } private void ResolveArm(PlayerAvatarVisuals? mv) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!_armResolved && !((Object)(object)mv == (Object)null)) { PlayerAvatarLeftArm componentInChildren = ((Component)mv).GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren.leftArmTransform == (Object)null)) { _leftArm = componentInChildren.leftArmTransform; _basePose = componentInChildren.basePose; _flashPose = componentInChildren.flashlightPose; _armResolved = true; } } } private void BuildClone(FlashlightController src, PlayerAvatarVisuals mv) { //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) try { Transform val = null; if ((Object)(object)src.FollowTransformClient != (Object)null) { val = FindByName(((Component)mv).transform, ((Object)src.FollowTransformClient).name); } if ((Object)(object)val == (Object)null) { val = mv.headLookAtTransform; } if ((Object)(object)val == (Object)null) { _buildFailed = true; return; } GameObject val2 = Object.Instantiate(((Component)src).gameObject); ((Object)val2).name = "MHB_MiniFlashlight"; FlashlightController componentInChildren = val2.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.meshShadows != (Object)null) { ((Renderer)componentInChildren.meshShadows).enabled = false; ((Component)componentInChildren.meshShadows).gameObject.SetActive(false); } MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (MonoBehaviour val3 in componentsInChildren) { if ((Object)(object)val3 != (Object)null) { ((Behaviour)val3).enabled = false; } } AudioSource[] componentsInChildren2 = val2.GetComponentsInChildren(true); foreach (AudioSource val4 in componentsInChildren2) { ((Behaviour)val4).enabled = false; } int num = LayerMask.NameToLayer("Triggers"); if (num >= 0) { Transform[] componentsInChildren3 = val2.GetComponentsInChildren(true); foreach (Transform val5 in componentsInChildren3) { ((Component)val5).gameObject.layer = num; } } Transform transform = val2.transform; transform.SetParent(val, false); transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one; if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.mesh != (Object)null) { transform.localPosition = -val.InverseTransformPoint(((Component)componentInChildren.mesh).transform.position) + Vector3.forward * 0.1f; } _cloneLight = val2.GetComponentInChildren(true); if ((Object)(object)_cloneLight != (Object)null) { ((Behaviour)_cloneLight).enabled = false; } _clone = val2; } catch (Exception ex) { _buildFailed = true; BceConsole.LogWarning("Mini-Semibot flashlight clone failed: " + ex.Message); _clone = null; } } private static Transform? FindByName(Transform root, string name) { if (((Object)root).name == name) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindByName(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private void OnDestroy() { if ((Object)(object)_clone != (Object)null) { Object.Destroy((Object)(object)_clone); } } } internal sealed class MiniGrabBeam : MonoBehaviour { internal PlayerAvatar? WearerAvatar; internal PlayerAvatarRightArm? MiniArm; internal MiniSemibotFollow? Follow; private PhysGrabBeam? _wearerBeam; private LineRenderer? _line; private bool _built; private const int Res = 20; private readonly Vector3[] _pts = (Vector3[])(object)new Vector3[20]; private Material? _miniBeamMat; private Material? _srcMat; private static readonly int EmissionId = Shader.PropertyToID("_EmissionColor"); private GameObject? _overchargeGO; private Light? _overchargeLight; private ParticleSystem? _overchargeParticles; private AnimationCurve? _overchargeCurve; private Sound? _overchargeSound; private bool _overchargeTried; private PlayerCosmetics? _miniCosmetics; private void LateUpdate() { //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_wearerBeam == (Object)null && (Object)(object)WearerAvatar != (Object)null && (Object)(object)WearerAvatar.physGrabber != (Object)null) { _wearerBeam = WearerAvatar.physGrabber.physGrabBeamComponent; } MiniSemibotConfig cfg = MiniSemibotSync.Resolve(WearerAvatar); Transform val = (((Object)(object)MiniArm != (Object)null) ? MiniArm.grabberTransform : null); if (cfg.Grabber == MiniSemibotGrabberVisual.CleanArm || (!((Object)(object)Follow == (Object)null) && MiniSemibotSpawner.IsMenuOrPreviewWearer(Follow.WearerVisuals)) || (!((Object)(object)Follow == (Object)null) && Follow.BodyHidden) || cfg.Position != MiniSemibotPosition.Front || !((Object)(object)_wearerBeam != (Object)null) || !((Object)(object)_wearerBeam.lineRenderer != (Object)null) || !((Renderer)_wearerBeam.lineRenderer).enabled || !((Object)(object)_wearerBeam.PhysGrabPoint != (Object)null) || !((Object)(object)val != (Object)null)) { if ((Object)(object)_line != (Object)null && ((Renderer)_line).enabled) { ((Renderer)_line).enabled = false; } OverchargeUpdate(0f, Vector3.zero, 1f); return; } if (!_built) { Build(); } if (!((Object)(object)_line == (Object)null)) { if (!((Renderer)_line).enabled) { ((Renderer)_line).enabled = true; } Vector3 position = val.position; Vector3 position2 = _wearerBeam.PhysGrabPoint.position; Vector3 p = (((Object)(object)_wearerBeam.PhysGrabPointPuller != (Object)null) ? _wearerBeam.PhysGrabPointPuller.position : Vector3.Lerp(position, position2, 0.5f)); for (int i = 0; i < 20; i++) { float t = (float)i / 19f; _pts[i] = Bezier(t, position, p, position2); } _line.positionCount = 20; _line.SetPositions(_pts); LineRenderer lineRenderer = _wearerBeam.lineRenderer; Material sharedMaterial = ((Renderer)lineRenderer).sharedMaterial; EnsureBeamMaterial(sharedMaterial); _line.widthCurve = lineRenderer.widthCurve; _line.widthMultiplier = lineRenderer.widthMultiplier * cfg.Scale * 1.5f; if ((Object)(object)_miniBeamMat != (Object)null && (Object)(object)sharedMaterial != (Object)null) { _miniBeamMat.mainTexture = sharedMaterial.mainTexture; _miniBeamMat.mainTextureOffset = sharedMaterial.mainTextureOffset; Color hue = ResolveBeamRgb(in cfg, sharedMaterial); ApplyBeamHue(_miniBeamMat, hue, sharedMaterial); } PhysGrabber val2 = (((Object)(object)WearerAvatar != (Object)null && !WearerAvatar.isDisabled) ? WearerAvatar.physGrabber : null); float charge = (((Object)(object)val2 != (Object)null) ? ((float)(int)val2.physGrabBeamOverCharge / 2f / 100f) : 0f); OverchargeUpdate(charge, position, cfg.Scale); } } private void OverchargeUpdate(float charge, Vector3 origin, float scale) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) if (charge <= 0f) { if ((Object)(object)_overchargeLight != (Object)null && ((Behaviour)_overchargeLight).enabled) { ((Behaviour)_overchargeLight).enabled = false; if ((Object)(object)_overchargeParticles != (Object)null) { _overchargeParticles.Stop(); } } Sound? overchargeSound = _overchargeSound; if (overchargeSound != null) { overchargeSound.PlayLoop(false, 0.5f, 0.5f, 1f, 1f); } return; } EnsureOverchargeRig(); if ((Object)(object)_overchargeGO == (Object)null || (Object)(object)_overchargeLight == (Object)null) { return; } _overchargeGO.transform.position = origin; float num = ((_overchargeCurve != null) ? _overchargeCurve.Evaluate(charge) : charge); if (!((Behaviour)_overchargeLight).enabled) { ((Behaviour)_overchargeLight).enabled = true; if ((Object)(object)_overchargeParticles != (Object)null) { _overchargeParticles.Play(); } } _overchargeLight.intensity = (8f * num + charge * Mathf.Sin(Time.time * (10f + 20f * num))) * scale; if ((Object)(object)_overchargeParticles != (Object)null) { EmissionModule emission = _overchargeParticles.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(num * 50f); ((Component)_overchargeParticles).transform.localScale = Vector3.one * ((0.1f + 0.8f * num) * scale); } if (_overchargeSound != null) { _overchargeSound.LoopVolumeCurrent = 0.5f * num * Mathf.Clamp01(scale); _overchargeSound.PlayLoop(true, 0.5f, 0.5f, 1f + 2f * num, 1f); } } private void EnsureOverchargeRig() { if (_overchargeTried) { return; } _overchargeTried = true; try { PlayerAvatarOverchargeVisuals val = FindWearerOvercharge(); if (!((Object)(object)val == (Object)null)) { _overchargeGO = Object.Instantiate(((Component)val).gameObject); ((Object)_overchargeGO).name = "MHB_MiniOvercharge"; PlayerAvatarOverchargeVisuals component = _overchargeGO.GetComponent(); if ((Object)(object)component != (Object)null) { _overchargeCurve = component.overchargeIntensityCurve; _overchargeSound = component.soundOverchargeLoop; Object.DestroyImmediate((Object)(object)component); } _overchargeLight = _overchargeGO.GetComponentInChildren(true); _overchargeParticles = _overchargeGO.GetComponentInChildren(true); if ((Object)(object)_overchargeLight != (Object)null) { ((Behaviour)_overchargeLight).enabled = false; } if ((Object)(object)_overchargeParticles != (Object)null) { _overchargeParticles.Stop(); } if (_overchargeSound != null && ((Object)(object)_overchargeSound.Source == (Object)null || !((Component)_overchargeSound.Source).transform.IsChildOf(_overchargeGO.transform))) { _overchargeSound = null; } } } catch (Exception ex) { BridgeLog.Debug("Mini-Semibot overcharge rig unavailable: " + ex.Message); if ((Object)(object)_overchargeGO != (Object)null) { Object.Destroy((Object)(object)_overchargeGO); _overchargeGO = null; } _overchargeLight = null; _overchargeParticles = null; _overchargeSound = null; } } private PlayerAvatarOverchargeVisuals? FindWearerOvercharge() { if ((Object)(object)WearerAvatar == (Object)null || (Object)(object)WearerAvatar.physGrabber == (Object)null) { return null; } PhysGrabBeam physGrabBeamComponent = WearerAvatar.physGrabber.physGrabBeamComponent; PlayerAvatarOverchargeVisuals val = (((Object)(object)physGrabBeamComponent != (Object)null) ? ((Component)physGrabBeamComponent).GetComponentInChildren(true) : null); if ((Object)(object)val != (Object)null) { return val; } PlayerAvatarOverchargeVisuals[] array = Object.FindObjectsOfType(); foreach (PlayerAvatarOverchargeVisuals val2 in array) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2.playerAvatar == (Object)(object)WearerAvatar) { return val2; } } return null; } private Color ResolveBeamRgb(in MiniSemibotConfig cfg, Material? wearerMat) { //IL_0011: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Color result = (((Object)(object)wearerMat != (Object)null) ? wearerMat.color : Color.white); if (!MiniSemibotModCompat.HasCustomGrabColor) { return result; } if (cfg.Beam == MiniSemibotBeamColor.MiniGrabber && TryMiniGrabberColor(out var color)) { return color; } if ((Object)(object)WearerAvatar != (Object)null && WearerAvatar.isLocal && Plugin.EnableVanillaCustomColors.Value && PerCosmeticColors.TryGetCustomColor(VanillaTintHelper.BaseMeshAssetId(9), out var color2)) { return color2; } return result; } private void EnsureBeamMaterial(Material? wearerMat) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_line == (Object)null) && !((Object)(object)wearerMat == (Object)null) && (!((Object)(object)_miniBeamMat != (Object)null) || !((Object)(object)_srcMat == (Object)(object)wearerMat))) { if ((Object)(object)_miniBeamMat != (Object)null) { Object.Destroy((Object)(object)_miniBeamMat); } _miniBeamMat = new Material(wearerMat); _srcMat = wearerMat; ((Renderer)_line).sharedMaterial = _miniBeamMat; _line.startColor = Color.white; _line.endColor = Color.white; } } private static void ApplyBeamHue(Material mat, Color hue, Material wearerMat) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) Color color = wearerMat.color; Color val = (wearerMat.HasProperty(EmissionId) ? wearerMat.GetColor(EmissionId) : color); float num = Mathf.Max(hue.r, Mathf.Max(hue.g, hue.b)); if (num > 0.0001f) { ((Color)(ref hue))..ctor(hue.r / num, hue.g / num, hue.b / num, 1f); } float num2 = Mathf.Max(color.r, Mathf.Max(color.g, color.b)); float num3 = Mathf.Max(val.r, Mathf.Max(val.g, val.b)); mat.color = new Color(hue.r * num2, hue.g * num2, hue.b * num2, color.a); if (mat.HasProperty(EmissionId)) { mat.SetColor(EmissionId, new Color(hue.r * num3, hue.g * num3, hue.b * num3, val.a)); } } private bool TryMiniGrabberColor(out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Invalid comparison between Unknown and I4 //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) color = Color.white; int num = 9; if (_miniCosmetics == null) { _miniCosmetics = ((Component)this).GetComponentInChildren(true); } PlayerCosmetics miniCosmetics = _miniCosmetics; if ((Object)(object)miniCosmetics == (Object)null) { return false; } if (miniCosmetics.playerMaterials != null) { foreach (PlayerMaterial playerMaterial in miniCosmetics.playerMaterials) { if (!((Object)(object)playerMaterial == (Object)null) && !((Object)(object)playerMaterial.cosmetic != (Object)null) && (int)playerMaterial.cosmeticType == num) { if ((Object)(object)playerMaterial.material == (Object)null) { break; } Color color2 = playerMaterial.material.GetColor(PerCosmeticColors.PropAlbedo); color = new Color(color2.r, color2.g, color2.b, 1f); return true; } } } MetaManager instance = MetaManager.instance; if (miniCosmetics.colorsEquipped == null || (Object)(object)instance == (Object)null || instance.colors == null) { return false; } if (num < 0 || num >= miniCosmetics.colorsEquipped.Length) { return false; } int num2 = miniCosmetics.colorsEquipped[num]; if (num2 < 0 || num2 >= instance.colors.Count) { return false; } color = instance.colors[num2].color; return true; } private void Build() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) _built = true; try { GameObject val = new GameObject("MHB_MiniBeam"); _line = val.AddComponent(); _line.useWorldSpace = true; _line.numCapVertices = 2; _line.numCornerVertices = 2; ((Renderer)_line).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)_line).receiveShadows = false; LineRenderer val2 = (((Object)(object)_wearerBeam != (Object)null) ? _wearerBeam.lineRenderer : null); if ((Object)(object)val2 != (Object)null) { _line.widthCurve = val2.widthCurve; _line.widthMultiplier = val2.widthMultiplier * MiniSemibotSettings.Scale * 1.5f; _line.textureMode = val2.textureMode; } ((Renderer)_line).enabled = false; } catch (Exception ex) { BceConsole.LogWarning("Mini-Semibot beam build failed: " + ex.Message); _line = null; } } private static Vector3 Bezier(float t, Vector3 p0, Vector3 p1, Vector3 p2) { //IL_0011: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) return Mathf.Pow(1f - t, 2f) * p0 + 2f * (1f - t) * t * p1 + Mathf.Pow(t, 2f) * p2; } private void OnDestroy() { if ((Object)(object)_line != (Object)null) { Object.Destroy((Object)(object)((Component)_line).gameObject); } if ((Object)(object)_miniBeamMat != (Object)null) { Object.Destroy((Object)(object)_miniBeamMat); } if ((Object)(object)_overchargeGO != (Object)null) { Object.Destroy((Object)(object)_overchargeGO); } } } internal sealed class MiniMapHold : MonoBehaviour { internal PlayerAvatar? WearerAvatar; internal PlayerAvatarRightArm? MiniArm; internal MiniSemibotFollow? Follow; private static readonly Vector3 MapLocalPos = new Vector3(0f, 0f, 0f); private static readonly Vector3 MapLocalEuler = new Vector3(90f, 90f, 0f); private GameObject? _mapClone; private Transform? _src; private bool _built; internal Transform? ActiveCloneTransform { get { if (!((Object)(object)_mapClone != (Object)null) || !_mapClone.activeSelf) { return null; } return _mapClone.transform; } } private void LateUpdate() { //IL_0125: 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_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) MiniSemibotConfig miniSemibotConfig = MiniSemibotSync.Resolve(WearerAvatar); MapToolController val = (((Object)(object)WearerAvatar != (Object)null) ? WearerAvatar.mapToolController : null); Transform val2 = (((Object)(object)MiniArm != (Object)null) ? MiniArm.grabberTransform : null); if (miniSemibotConfig.Grabber == MiniSemibotGrabberVisual.CleanArm || (!((Object)(object)Follow == (Object)null) && MiniSemibotSpawner.IsMenuOrPreviewWearer(Follow.WearerVisuals)) || (!((Object)(object)Follow == (Object)null) && Follow.BodyHidden) || !((Object)(object)val != (Object)null) || !val.Active || !((Object)(object)val.VisualTransform != (Object)null) || !((Object)(object)val2 != (Object)null)) { if ((Object)(object)_mapClone != (Object)null && _mapClone.activeSelf) { _mapClone.SetActive(false); } return; } if (!_built) { BuildClone(val); } if (!((Object)(object)_mapClone == (Object)null)) { if (!_mapClone.activeSelf) { _mapClone.SetActive(true); } Transform transform = _mapClone.transform; transform.position = val2.TransformPoint(MapLocalPos); PlayerAvatarVisuals val3 = (((Object)(object)Follow != (Object)null) ? Follow.WearerVisuals : null); PlayerAvatarVisuals val4 = (((Object)(object)Follow != (Object)null) ? Follow.MiniVisuals : null); if ((Object)(object)_src != (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null) { transform.rotation = ((Component)val4).transform.rotation * (Quaternion.Inverse(((Component)val3).transform.rotation) * _src.rotation); } else { transform.rotation = val2.rotation * Quaternion.Euler(MapLocalEuler); } if ((Object)(object)_src != (Object)null) { transform.localScale = _src.lossyScale * miniSemibotConfig.Scale; } } } private void BuildClone(MapToolController map) { _built = true; if ((Object)(object)map.VisualTransform == (Object)null) { return; } try { _src = map.VisualTransform; GameObject val = Object.Instantiate(((Component)_src).gameObject); ((Object)val).name = "MHB_MiniMap"; Camera[] componentsInChildren = val.GetComponentsInChildren(true); foreach (Camera val2 in componentsInChildren) { ((Behaviour)val2).enabled = false; } Light[] componentsInChildren2 = val.GetComponentsInChildren(true); foreach (Light val3 in componentsInChildren2) { ((Behaviour)val3).enabled = false; } AudioListener[] componentsInChildren3 = val.GetComponentsInChildren(true); foreach (AudioListener val4 in componentsInChildren3) { ((Behaviour)val4).enabled = false; } MonoBehaviour[] componentsInChildren4 = val.GetComponentsInChildren(true); foreach (MonoBehaviour val5 in componentsInChildren4) { if ((Object)(object)val5 != (Object)null) { ((Behaviour)val5).enabled = false; } } int num = LayerMask.NameToLayer("Triggers"); if (num >= 0) { Transform[] componentsInChildren5 = val.GetComponentsInChildren(true); foreach (Transform val6 in componentsInChildren5) { ((Component)val6).gameObject.layer = num; } } if ((Object)(object)map.DisplayMesh != (Object)null && (Object)(object)map.DisplayMaterialClient != (Object)null) { string name = ((Object)((Component)map.DisplayMesh).gameObject).name; MeshRenderer[] componentsInChildren6 = val.GetComponentsInChildren(true); foreach (MeshRenderer val7 in componentsInChildren6) { if (((Object)((Component)val7).gameObject).name == name) { ((Renderer)val7).material = map.DisplayMaterialClient; break; } } } _mapClone = val; _mapClone.SetActive(true); } catch (Exception ex) { BceConsole.LogWarning("Mini-Semibot map clone failed: " + ex.Message); _mapClone = null; } } private void OnDestroy() { if ((Object)(object)_mapClone != (Object)null) { Object.Destroy((Object)(object)_mapClone); } } } [DefaultExecutionOrder(10000)] internal sealed class MiniSemibotAnimSync : MonoBehaviour { internal PlayerAvatarVisuals? SourceVisuals; internal PlayerAvatarVisuals? TargetVisuals; internal MiniPoseOverride Override; private Animator? _source; private Animator? _target; private PlayerAvatarMenu? _targetMenu; private AnimatorControllerParameter[]? _params; private static readonly int HMoving = Animator.StringToHash("Moving"); private static readonly int HSprinting = Animator.StringToHash("Sprinting"); private static readonly int HSliding = Animator.StringToHash("Sliding"); private static readonly int HJumping = Animator.StringToHash("Jumping"); private static readonly int HFalling = Animator.StringToHash("Falling"); private static readonly int HCrouching = Animator.StringToHash("Crouching"); private static readonly int HCrawling = Animator.StringToHash("Crawling"); private static readonly int HTumbling = Animator.StringToHash("Tumbling"); private static readonly int HTumblingMove = Animator.StringToHash("TumblingMove"); private static readonly int HTurning = Animator.StringToHash("Turning"); private static readonly int HGrabbing = Animator.StringToHash("Grabbing"); private static readonly int HSprintImpulse = Animator.StringToHash("SprintingImpulse"); private static readonly int HSlideImpulse = Animator.StringToHash("SlidingImpulse"); private static readonly int HJumpImpulse = Animator.StringToHash("JumpingImpulse"); private static readonly int HFallImpulse = Animator.StringToHash("FallingImpulse"); private static readonly int HTumbleImpulse = Animator.StringToHash("TumblingImpulse"); private bool _wasJumping; private bool _wasSprinting; private bool _wasSliding; private bool _wasTumbling; private float _prevYaw; private bool _yawInit; private const float TurnRateThreshold = 8f; private const float TumbleSpinThreshold = 0.015f; private void Update() { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected I4, but got Unknown if ((Object)(object)_source == (Object)null) { _source = ResolveAnimator(SourceVisuals); } if ((Object)(object)_target == (Object)null) { _target = ResolveAnimator(TargetVisuals); _params = null; } if ((Object)(object)_target == (Object)null) { return; } if (Override != MiniPoseOverride.None) { ApplyForcedPose(); } else { if ((Object)(object)_source == (Object)null) { return; } if (_params == null) { _params = _target.parameters; } if ((Object)(object)_targetMenu == (Object)null) { _targetMenu = (((Object)(object)TargetVisuals != (Object)null) ? TargetVisuals.playerAvatarMenu : null); } if ((Object)(object)_targetMenu != (Object)null) { _targetMenu.physGrabBeamActive = _source.GetBool(HGrabbing); } AnimatorControllerParameter[] array = _params; foreach (AnimatorControllerParameter val in array) { AnimatorControllerParameterType type = val.type; switch (type - 1) { case 3: _target.SetBool(val.nameHash, _source.GetBool(val.nameHash)); break; case 0: _target.SetFloat(val.nameHash, _source.GetFloat(val.nameHash)); break; case 2: _target.SetInteger(val.nameHash, _source.GetInteger(val.nameHash)); break; } } ForwardImpulses(); ApplyLegSpeed(); ApplyYawAssist(); } } private void ApplyYawAssist() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)SourceVisuals == (Object)null) { return; } if ((Object)(object)_source != (Object)null && _source.GetBool(HTumbling)) { float num = 0f; PlayerAvatar playerAvatar = SourceVisuals.playerAvatar; if ((Object)(object)playerAvatar != (Object)null && (Object)(object)playerAvatar.tumble != (Object)null && (Object)(object)playerAvatar.tumble.rb != (Object)null) { Vector3 angularVelocity = playerAvatar.tumble.rb.angularVelocity; num = ((Vector3)(ref angularVelocity)).magnitude; } _target.SetBool(HTumblingMove, num > 0.015f); return; } float y = ((Component)SourceVisuals).transform.eulerAngles.y; if (!_yawInit) { _prevYaw = y; _yawInit = true; return; } float num2 = Mathf.Abs(Mathf.DeltaAngle(_prevYaw, y)) / Mathf.Max(Time.deltaTime, 0.0001f); _prevYaw = y; bool flag = _source.GetBool(HMoving) || _source.GetBool(HSprinting) || _source.GetBool(HSliding); bool flag2 = _source.GetBool(HJumping); if (!flag && !flag2 && num2 > 8f) { _target.SetBool(HTurning, true); } } private void ForwardImpulses() { bool flag = _source.GetBool(HJumping); bool flag2 = _source.GetBool(HSprinting); bool flag3 = _source.GetBool(HSliding); bool flag4 = _source.GetBool(HTumbling); if (flag && !_wasJumping) { _target.SetTrigger(_source.GetBool(HFalling) ? HFallImpulse : HJumpImpulse); } if (flag2 && !_wasSprinting) { _target.SetTrigger(HSprintImpulse); } if (flag3 && !_wasSliding) { _target.SetTrigger(HSlideImpulse); } if (flag4 && !_wasTumbling) { _target.SetTrigger(HTumbleImpulse); } _wasJumping = flag; _wasSprinting = flag2; _wasSliding = flag3; _wasTumbling = flag4; } private void ApplyLegSpeed() { bool flag = _source.GetBool(HMoving) || _source.GetBool(HSprinting) || _source.GetBool(HSliding); float legSpeed = MiniSemibotSync.Resolve(((Object)(object)SourceVisuals != (Object)null) ? SourceVisuals.playerAvatar : null).LegSpeed; _target.speed = (flag ? Mathf.Max(1f, legSpeed) : 1f); } private void ApplyForcedPose() { _target.speed = 1f; if ((Object)(object)_targetMenu == (Object)null) { _targetMenu = (((Object)(object)TargetVisuals != (Object)null) ? TargetVisuals.playerAvatarMenu : null); } if ((Object)(object)_targetMenu != (Object)null) { _targetMenu.physGrabBeamActive = false; } bool flag = Override == MiniPoseOverride.CrouchIdle; bool flag2 = Override == MiniPoseOverride.TumbleIdle; _target.SetBool(HMoving, false); _target.SetBool(HSprinting, false); _target.SetBool(HSliding, false); _target.SetBool(HJumping, false); _target.SetBool(HFalling, false); _target.SetBool(HTurning, false); _target.SetBool(HGrabbing, false); _target.SetBool(HTumblingMove, false); _target.SetBool(HCrouching, flag); _target.SetBool(HCrawling, false); _target.SetBool(HTumbling, flag2); _wasJumping = (_wasSprinting = (_wasSliding = (_wasTumbling = false))); } private static Animator? ResolveAnimator(PlayerAvatarVisuals? visuals) { if ((Object)(object)visuals == (Object)null) { return null; } if (!((Object)(object)visuals.animator != (Object)null)) { return ((Component)visuals).GetComponent(); } return visuals.animator; } } internal static class MiniSemibotCosmetic { internal const string InternalName = "MHB_MiniMe"; internal const string DisplayName = "Mini-Semibot"; internal static readonly string AssetId = "morehead-bridge:" + "MHB_MiniMe".ToLowerInvariant(); private static bool _registered; private static GameObject? _prefab; internal static CosmeticAsset? Asset { get; private set; } internal static void Register() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (_registered || !Plugin.EnableMiniSemibot.Value) { return; } try { GameObject val = new GameObject("MHB_MiniMe"); val.SetActive(false); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); _prefab = val; Cosmetic val2 = val.AddComponent(); val2.type = (CosmeticType)0; PrefabRef val3 = NetworkPrefabs.RegisterNetworkPrefab("Cosmetics/" + ((Object)val).name, val); if (val3 == null) { BceConsole.LogError("Mini-Semibot: failed to register network prefab"); Object.Destroy((Object)(object)val); return; } CosmeticAsset val4 = ScriptableObject.CreateInstance(); ((Object)val4).name = "MHB_MiniMe"; val4.assetName = "Mini-Semibot"; val4.type = (CosmeticType)0; val4.prefab = val3; val4.assetId = AssetId; val4.rarity = Plugin.BridgeDefaultRarity.Value; val4.customTypeList = new List(); val4.tintable = false; val4.icon = (Sprite)(IconCapture.HasCache(val4) ? ((object)SemiFunc.LoadSpriteFromFile(IconCapture.CachePathFor(val4))) : ((object)MiniSemibotIcon.Create())); Asset = val4; Cosmetics.RegisterCosmetic(val4); HhhCosmeticLoader.RegisteredAssetIds.Add(AssetId); HhhCosmeticLoader.WorldAssetIds.Add(AssetId); _registered = true; BceConsole.LogInfo("Mini-Semibot world cosmetic registered", ConsoleColor.Cyan); } catch (Exception ex) { BceConsole.LogError("Mini-Semibot registration failed: " + ex.Message); } } } internal sealed class MiniSemibotFace : MonoBehaviour { internal PlayerAvatar? WearerAvatar; internal MiniSemibotFollow? Follow; internal Transform? MouthObject; internal float MouthMaxAngle = 45f; internal PlayerExpression? Expression; internal bool ExpressionPreview; internal int ForcedExpression = -1; private bool _exprFixed; private static FieldInfo? _isLocalField; private static FieldInfo? _stopExpressingField; private static FieldInfo? _timerField; private static FieldInfo? _isExpressingField; private int _registeredActor = -1; private AudioSource? _audio; private float _mimicTimer; private bool _wasInLevel; private const float MimicLevelWarmupMin = 10f; private const float MimicLevelWarmupMax = 20f; private float[]? _clipSamples; private int _clipChannels = 1; private float _clipInvPeak = 1f; private float _randTimer; private bool _randTalking; private float _randSeed; private void LateUpdate() { //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) if (ExpressionPreview) { if ((Object)(object)WearerAvatar == (Object)null) { WearerAvatar = PlayerAvatar.instance; } if ((Object)(object)Expression != (Object)null && (Object)(object)WearerAvatar != (Object)null) { Expression.playerAvatar = WearerAvatar; Expression.onlyVisualRepresentation = true; SetIsLocalFalse(Expression); } } else if (!_exprFixed && (Object)(object)Expression != (Object)null && (Object)(object)WearerAvatar != (Object)null) { _exprFixed = true; Expression.playerAvatar = WearerAvatar; Expression.onlyVisualRepresentation = true; SetIsLocalFalse(Expression); } EnsureRegistered(); MirrorStopExpressing(); if (ForcedExpression >= 0) { ForceExpression(ForcedExpression); } if ((Object)(object)MouthObject != (Object)null) { MiniSemibotConfig cfg = MiniSemibotSync.Resolve(WearerAvatar); bool flag = ((Object)(object)WearerAvatar != (Object)null && (WearerAvatar.isDisabled || WearerAvatar.deadSet)) || ((Object)(object)Follow != (Object)null && Follow.BodyHidden); if (flag && (Object)(object)_audio != (Object)null && _audio.isPlaying) { _audio.Stop(); } if (!flag && cfg.Mouth == MiniSemibotMouthMode.MimicClips && ((Object)(object)WearerAvatar == (Object)null || WearerAvatar.isLocal)) { TickOwnerMimic(in cfg); } float num = ((!flag) ? (cfg.Mouth switch { MiniSemibotMouthMode.Never => 0f, MiniSemibotMouthMode.Random => RandomLoudness(), MiniSemibotMouthMode.MimicClips => MimicLoudness(), _ => WearerVoiceLoudness(), }) : 0f); float num2 = num; float num3 = Mathf.Lerp(0f, 0f - MouthMaxAngle, Mathf.Clamp01(num2)); MouthObject.localRotation = Quaternion.Slerp(MouthObject.localRotation, Quaternion.Euler(num3, 0f, 0f), 100f * Time.deltaTime); } } private float WearerVoiceLoudness() { PlayerVoiceChat val = ((PlayerAvatar)((((Object)(object)WearerAvatar != (Object)null) ? ((object)WearerAvatar) : ((object)PlayerAvatar.instance))?)).voiceChat; if ((Object)(object)val == (Object)null || val.overrideNoTalkAnimationTimer > 0f || val.clipLoudness <= 0.005f) { return 0f; } return val.clipLoudness * 4f; } private void EnsureRegistered() { int num = MiniSemibotSync.ActorOf(WearerAvatar); if (num != _registeredActor) { if (_registeredActor >= 0) { MiniSemibotMimicAudio.UnregisterFace(_registeredActor, this); } _registeredActor = num; if (num >= 0) { MiniSemibotMimicAudio.RegisterFace(num, this); } } } private void TickOwnerMimic(in MiniSemibotConfig cfg) { if (!SemiFunc.RunIsLevel()) { _wasInLevel = false; return; } if (!_wasInLevel) { _wasInLevel = true; _mimicTimer = Random.Range(10f, 20f); } if ((Object)(object)_audio != (Object)null && _audio.isPlaying) { return; } _mimicTimer -= Time.deltaTime; if (!(_mimicTimer > 0f)) { byte[] array = MiniSemibotMimicAudio.PickRandomClipBytes(); if (array == null) { _mimicTimer = 2f; return; } PlayMimicClip(array); MiniSemibotMimicAudio.BroadcastClip(array); _mimicTimer = Random.Range(cfg.MimicMinDelay, cfg.MimicMaxDelay); } } internal void PlayMimicClip(byte[] wav) { if (!MiniSemibotMimicAudio.TryDecodeWav(wav, out float[] samples, out int channels, out int frequency)) { return; } EnsureAudio(); if ((Object)(object)_audio == (Object)null) { return; } int num = samples.Length / Mathf.Max(1, channels); if (num <= 0) { return; } MiniSemibotConfig miniSemibotConfig = MiniSemibotSync.Resolve(WearerAvatar); _audio.volume = miniSemibotConfig.MimicVol; _audio.maxDistance = miniSemibotConfig.MimicMaxDistance; _clipSamples = samples; _clipChannels = Mathf.Max(1, channels); float num2 = 0f; for (int i = 0; i < samples.Length; i++) { float num3 = ((samples[i] < 0f) ? (0f - samples[i]) : samples[i]); if (num3 > num2) { num2 = num3; } } _clipInvPeak = 1f / Mathf.Max(num2, 0.08f); AudioClip val = AudioClip.Create("MHB_MimicClip", num, channels, frequency, false); val.SetData(samples, 0); _audio.clip = val; _audio.Play(); } private void EnsureAudio() { if (!((Object)(object)_audio != (Object)null)) { _audio = ((Component)this).gameObject.AddComponent(); _audio.playOnAwake = false; _audio.loop = false; _audio.spatialBlend = 1f; _audio.dopplerLevel = 0f; _audio.minDistance = 1f; _audio.maxDistance = 20f; _audio.volume = 1f; } } private float MimicLoudness() { if ((Object)(object)_audio == (Object)null || !_audio.isPlaying || _clipSamples == null) { return 0f; } int clipChannels = _clipChannels; int num = _audio.timeSamples * clipChannels; int num2 = 256 * clipChannels; float num3 = 0f; int num4 = 0; for (int i = num; i < num + num2 && i < _clipSamples.Length; i++) { num3 += _clipSamples[i] * _clipSamples[i]; num4++; } if (num4 == 0) { return 0f; } float num5 = Mathf.Sqrt(num3 / (float)num4); return Mathf.Clamp01(num5 * _clipInvPeak * 1.6f); } private void OnDestroy() { if (_registeredActor >= 0) { MiniSemibotMimicAudio.UnregisterFace(_registeredActor, this); } } private float RandomLoudness() { _randTimer -= Time.deltaTime; if (_randTimer <= 0f) { _randTalking = !_randTalking; _randTimer = (_randTalking ? Random.Range(0.4f, 1.6f) : Random.Range(1.5f, 5f)); _randSeed = Random.value * 100f; } if (!_randTalking) { return 0f; } float num = Mathf.PerlinNoise(Time.time * 9f, _randSeed); return Mathf.Clamp01(0.15f + num * 0.85f); } private void MirrorStopExpressing() { if ((Object)(object)Expression == (Object)null || (Object)(object)WearerAvatar == (Object)null) { return; } PlayerExpression playerExpression = WearerAvatar.playerExpression; if ((Object)(object)playerExpression == (Object)null || (Object)(object)playerExpression == (Object)(object)Expression) { return; } List expressions = playerExpression.expressions; List expressions2 = Expression.expressions; if (expressions == null || expressions2 == null) { return; } try { if ((object)_stopExpressingField == null) { _stopExpressingField = typeof(ExpressionSettings).GetField("stopExpressing", BindingFlags.Instance | BindingFlags.NonPublic); } if (_stopExpressingField == null) { return; } int num = Math.Min(expressions.Count, expressions2.Count); for (int i = 0; i < num; i++) { if (expressions[i] != null && expressions2[i] != null) { _stopExpressingField.SetValue(expressions2[i], _stopExpressingField.GetValue(expressions[i])); } } } catch { } } private void ForceExpression(int index) { List list = (((Object)(object)Expression != (Object)null) ? Expression.expressions : null); if (list == null || index < 0 || index >= list.Count) { return; } ExpressionSettings val = list[index]; if (val == null) { return; } val.weight = 100f; try { if ((object)_timerField == null) { _timerField = typeof(ExpressionSettings).GetField("timer", BindingFlags.Instance | BindingFlags.NonPublic); } if ((object)_isExpressingField == null) { _isExpressingField = typeof(ExpressionSettings).GetField("isExpressing", BindingFlags.Instance | BindingFlags.NonPublic); } _timerField?.SetValue(val, 0.25f); _isExpressingField?.SetValue(val, true); } catch { } } private static void SetIsLocalFalse(PlayerExpression pe) { try { if ((object)_isLocalField == null) { _isLocalField = typeof(PlayerExpression).GetField("isLocal", BindingFlags.Instance | BindingFlags.NonPublic); } _isLocalField?.SetValue(pe, false); } catch { } } } internal sealed class MiniSemibotFollow : MonoBehaviour { internal PlayerAvatarVisuals? WearerVisuals; internal PlayerAvatar? WearerAvatar; internal MiniSemibotAnimSync? AnimSync; internal GameObject? Body; internal PlayerAvatarVisuals? MiniVisuals; internal Vector3 Scale = Vector3.one; internal bool ExpressionPreview; private MiniSemibotConfig _cfg; private FollowSpring _followSpring; private bool _hadVisuals; private bool _bodyHidden; private float _tumbleRecover; private bool _arenaExploded; private MiniDeathHead? _deathHead; private Vector3 _deathHeadSmoothPos; private bool _deathHeadPosInit; private MiniSemibotFace? _face; private const float TumbleRecoverTime = 0.5f; private const float TumbleYLift = 0.01f; private const float StateSmoothingRate = 12f; internal static readonly LayerMask PlacementMask = LayerMask.op_Implicit(LayerMask.GetMask(new string[2] { "Default", "StaticGrabObject" })); private static readonly LayerMask WallObstacleMask = LayerMask.op_Implicit(LayerMask.GetMask(new string[5] { "Default", "StaticGrabObject", "PhysGrabObject", "PhysGrabObjectCart", "PhysGrabObjectHinge" })); private static readonly RaycastHit[] _wallHits = (RaycastHit[])(object)new RaycastHit[8]; private const float WallProbeRadius = 0.15f; private const float WallProbeHeight = 0.5f; private const float GroundProbeRadius = 0.15f; private const float StepProbeUp = 0.75f; private const float StepSnapRange = 0.6f; private const int LedgePullSteps = 3; private bool _deathSmoked; private MiniMapHold? _mapHold; private Vector2 _sway; private SpringFloat? _swayUpSpring; private float _swaySteer; private float _swayPrevYaw; private bool _swayYawInit; private float _glanceYaw; private float _glancePitch; private float _glanceYawTarget; private float _glancePitchTarget; private float _glanceTimer; internal bool BodyHidden => _bodyHidden; private void LateUpdate() { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)WearerVisuals == (Object)null) { if (_hadVisuals) { Object.Destroy((Object)(object)((Component)this).gameObject); } return; } _hadVisuals = true; if (ExpressionPreview) { PlaceExpressionPreview(); return; } SetForcedExpression(-1); bool flag = (Object)(object)WearerAvatar != (Object)null && (Object)(object)ItemVehicle.GetVehicleForPlayer(WearerAvatar) != (Object)null; if (!MiniSemibotSpawner.IsMenuOrPreviewWearer(WearerVisuals) && MiniSemibotVisualPrefs.HideInArena && (RunIsKartArena() || flag)) { SetBodyHidden(hidden: true); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.None; } HideDeathHead(); return; } _cfg = MiniSemibotSync.Resolve(WearerAvatar); Scale = Vector3.one * _cfg.Scale; ApplyMenuGaze(); ApplyInGameGaze(); PlayerAvatar wearerAvatar = WearerAvatar; bool flag2 = MiniSemibotSpawner.IsMenuOrPreviewWearer(WearerVisuals); bool flag3 = !flag2 && (Object)(object)wearerAvatar != (Object)null && (wearerAvatar.isDisabled || wearerAvatar.deadSet); bool flag4 = !flag2 && (Object)(object)wearerAvatar != (Object)null && wearerAvatar.isTumbling; if (flag3) { if (SemiFunc.RunIsArena()) { if (!_arenaExploded) { _arenaExploded = true; ExplodeLikeWearer(); } SetBodyHidden(hidden: true); HideDeathHead(); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.None; } return; } switch (_cfg.Death) { case MiniSemibotDeathBehavior.Hide: SetBodyHidden(hidden: true); HideDeathHead(); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.None; } break; case MiniSemibotDeathBehavior.DeathHead: if (ShowDeathHead(wearerAvatar)) { SetBodyHidden(hidden: true); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.None; } if (!_deathSmoked) { _deathSmoked = true; PuffDeathSmoke(DeathHeadPosition(wearerAvatar)); } } else { SetBodyHidden(hidden: false); PlaceAtGround(DeathHeadPosition(wearerAvatar)); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.TumbleIdle; } } break; default: SetBodyHidden(hidden: false); HideDeathHead(); PlaceCrouchWaitByDeathHead(wearerAvatar); SetForcedExpression(2); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.CrouchIdle; } break; } return; } HideDeathHead(); SetBodyHidden(hidden: false); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.None; } _arenaExploded = false; _deathSmoked = false; if (flag4) { _tumbleRecover = 0.5f; } else if (_tumbleRecover > 0f) { _tumbleRecover -= Time.deltaTime; } if ((flag4 || _tumbleRecover > 0f) && (Object)(object)wearerAvatar != (Object)null) { PlaceRelativeUprightSmooth(((Component)wearerAvatar).transform.position + Vector3.up * 0.01f, ((Component)wearerAvatar).transform.eulerAngles.y); return; } Transform transform = ((Component)this).transform; Transform transform2 = ((Component)WearerVisuals).transform; Vector3 target = transform2.TransformPoint(ResolveOffset()); if (!flag2 && _cfg.AvoidWalls) { target = ClampToLevel(transform2.position, target); } Quaternion rotation = transform2.rotation; FollowSpringMode followSpring = MiniSemibotVisualPrefs.FollowSpring; transform.position = _followSpring.StepPosition(transform.position, target, Time.deltaTime, followSpring); transform.rotation = FollowSpring.StepRotation(transform.rotation, rotation, Time.deltaTime, followSpring); if (transform.localScale != Scale) { transform.localScale = Scale; } } private Vector3 ResolveOffset() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) MiniSemibotPosition miniSemibotPosition = ((!((Object)(object)WearerVisuals != (Object)null) || !WearerVisuals.isMenuAvatar) ? _cfg.Position : MiniSemibotPosition.Behind); Vector3 val = ((miniSemibotPosition == MiniSemibotPosition.Front) ? MiniSemibotSpawner.OffsetFront : MiniSemibotSpawner.OffsetBehind); float num = _cfg.Scale / 0.33f; return new Vector3(val.x, val.y * num, val.z); } private void PlaceExpressionPreview() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) SetBodyHidden(hidden: false); if ((Object)(object)AnimSync != (Object)null) { AnimSync.Override = MiniPoseOverride.None; } float num = MiniSemibotSettings.Scale / 0.33f; float num2 = 0.4f * num; MiniSemibotSize size = MiniSemibotVisualPrefs.Size; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(MiniSemibotSpawner.ExprPreviewXForSize(size), MiniSemibotSpawner.ExprPreviewYForSize(size), MiniSemibotSpawner.ExprPreviewZForSize(size)); Transform transform = ((Component)WearerVisuals).transform; Transform transform2 = ((Component)this).transform; transform2.position = transform.TransformPoint(val); transform2.rotation = transform.rotation * Quaternion.Euler(0f, 0f, 0f); Vector3 val2 = Vector3.one * num2; if (transform2.localScale != val2) { transform2.localScale = val2; } } private bool ShowDeathHead(PlayerAvatar avatar) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MiniVisuals == (Object)null) { return false; } if (_deathHead == null) { _deathHead = new MiniDeathHead(); } float y = ((Component)avatar).transform.eulerAngles.y; Quaternion rot = Quaternion.Euler(0f, y, 0f); Vector3 val = DeathHeadPosition(avatar); Vector3 val2 = (_deathHeadPosInit ? _deathHeadSmoothPos : ((Component)this).transform.position); Vector3 val3 = val2 - val; val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = -((Component)avatar).transform.forward; } Vector3 val4 = val + ((Vector3)(ref val3)).normalized * 0.7f + Vector3.up * MiniSemibotSpawner.DeathHeadLiftForSize(_cfg.Size); if (!_deathHeadPosInit) { _deathHeadSmoothPos = val4; _deathHeadPosInit = true; } else { float num = 1f - Mathf.Exp(-12f * Time.deltaTime); _deathHeadSmoothPos = Vector3.Lerp(_deathHeadSmoothPos, val4, num); } PlayerCosmetics val5 = (((Object)(object)WearerVisuals != (Object)null) ? WearerVisuals.playerCosmetics : null); bool crown = (Object)(object)val5 != (Object)null && (Object)(object)val5.playerCrown != (Object)null && (Object)(object)val5.playerCrown.crownMesh != (Object)null && ((Component)val5.playerCrown.crownMesh).gameObject.activeInHierarchy; return _deathHead.ShowAt(MiniVisuals, _deathHeadSmoothPos, rot, _cfg.Scale, crown); } private void HideDeathHead() { _deathHead?.Destroy(); _deathHeadPosInit = false; } internal void InvalidateDeathHead() { _deathHead?.Destroy(); } private void SetForcedExpression(int index) { if (_face == null) { _face = ((Component)this).GetComponent(); } if ((Object)(object)_face != (Object)null) { _face.ForcedExpression = index; } } private void OnDestroy() { HideDeathHead(); } private void PlaceCrouchWaitByDeathHead(PlayerAvatar avatar) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) Vector3 val = DeathHeadPosition(avatar); Transform transform = ((Component)this).transform; Vector3 val2 = transform.position - val; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = ((Component)avatar).transform.forward; } Vector3 val3 = val + ((Vector3)(ref val2)).normalized * 0.65f + Vector3.up * MiniSemibotSpawner.CrouchWaitLiftForSize(_cfg.Size); float num = 1f - Mathf.Exp(-12f * Time.deltaTime); transform.position = Vector3.Lerp(transform.position, val3, num); Vector3 val4 = val - transform.position; val4.y = 0f; if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f) { transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(val4), num); } if (transform.localScale != Scale) { transform.localScale = Scale; } } private void PlaceAtGround(Vector3 worldPos) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_009e: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)this).transform; float num = (((Object)(object)WearerAvatar != (Object)null) ? ((Component)WearerAvatar).transform.eulerAngles.y : (((Object)(object)WearerVisuals != (Object)null) ? ((Component)WearerVisuals).transform.eulerAngles.y : 0f)); transform.rotation = Quaternion.Euler(0f, num, 0f); transform.position = worldPos + transform.right * 0.4f; if (transform.localScale != Scale) { transform.localScale = Scale; } } private void PlaceRelativeUprightSmooth(Vector3 anchorPos, float yaw) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Quaternion val = Quaternion.Euler(0f, yaw, 0f); Vector3 val2 = anchorPos + val * ResolveOffset(); float num = 1f - Mathf.Exp(-12f * Time.deltaTime); Transform transform = ((Component)this).transform; transform.position = Vector3.Lerp(transform.position, val2, num); transform.rotation = Quaternion.Slerp(transform.rotation, val, num); if (transform.localScale != Scale) { transform.localScale = Scale; } } private Vector3 DeathHeadPosition(PlayerAvatar avatar) { //IL_0030: 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) PlayerDeathHead playerDeathHead = avatar.playerDeathHead; if ((Object)(object)playerDeathHead != (Object)null && (Object)(object)((Component)playerDeathHead).transform != (Object)null) { return ((Component)playerDeathHead).transform.position; } return ((Component)avatar).transform.position; } private void SetBodyHidden(bool hidden) { if (!((Object)(object)Body == (Object)null) && _bodyHidden != hidden) { _bodyHidden = hidden; Body.SetActive(!hidden); } } private static bool WallProbe(Vector3 origin, Vector3 dir, float dist, out RaycastHit best) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) best = default(RaycastHit); float num = float.MaxValue; int num2 = Physics.SphereCastNonAlloc(origin, 0.15f, dir, _wallHits, dist, LayerMask.op_Implicit(WallObstacleMask), (QueryTriggerInteraction)1); for (int i = 0; i < num2; i++) { RaycastHit val = _wallHits[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent() != (Object)null)) { PhysGrabObject componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent(); if ((!((Object)(object)componentInParent != (Object)null) || !componentInParent.grabbed) && ((RaycastHit)(ref val)).distance < num) { num = ((RaycastHit)(ref val)).distance; best = val; } } } return num < float.MaxValue; } private Vector3 ClampToLevel(Vector3 anchorPos, Vector3 target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) float num = target.y - anchorPos.y; float num2 = anchorPos.y + 0.5f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(anchorPos.x, num2, anchorPos.z); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(target.x, num2, target.z); Vector3 val3 = val2 - val; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude > 0.05f && WallProbe(val, val3 / magnitude, magnitude, out var best)) { Vector3 val4 = ((RaycastHit)(ref best)).point + ((RaycastHit)(ref best)).normal * 0.15f; ((Vector3)(ref target))..ctor(val4.x, target.y, val4.z); } Vector3 val5 = target; RaycastHit val6 = default(RaycastHit); for (int i = 0; i <= 3; i++) { float num3 = val5.y - num; if (Physics.SphereCast(new Vector3(val5.x, num3 + 0.75f, val5.z), 0.15f, Vector3.down, ref val6, 1.35f, LayerMask.op_Implicit(PlacementMask), (QueryTriggerInteraction)1) && Mathf.Abs(((RaycastHit)(ref val6)).point.y - num3) <= 0.6f) { return new Vector3(val5.x, ((RaycastHit)(ref val6)).point.y + num, val5.z); } val5 = Vector3.Lerp(val5, anchorPos + Vector3.up * num, 0.5f); } return target; } private void PuffDeathSmoke(Vector3 position) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) try { PlayerDeathEffects val = (((Object)(object)WearerAvatar != (Object)null) ? WearerAvatar.playerDeathEffects : null); ParticleSystem val2 = (((Object)(object)val != (Object)null) ? val.smokeParticles : null); if (!((Object)(object)val2 == (Object)null)) { GameObject val3 = Object.Instantiate(((Component)val2).gameObject, position + Vector3.up * 0.1f, Quaternion.identity); ((Object)val3).name = "MHB_MiniDeathSmoke"; val3.transform.localScale = Vector3.one * Mathf.Max(0.2f, Scale.x); ParticleSystem component = val3.GetComponent(); if ((Object)(object)component != (Object)null) { component.Clear(); component.Play(); } Object.Destroy((Object)(object)val3, 10f); } } catch (Exception ex) { BridgeLog.Debug("Mini-Semibot death smoke failed: " + ex.Message); } } private void ExplodeLikeWearer() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) try { PlayerDeathEffects val = (((Object)(object)WearerAvatar != (Object)null) ? WearerAvatar.playerDeathEffects : null); if ((Object)(object)val == (Object)null || (Object)(object)Body == (Object)null || (Object)(object)MiniVisuals == (Object)null) { return; } GameObject val2 = new GameObject("MHB_MiniDeathExplosion"); val2.transform.position = Body.transform.position + Vector3.up * 0.1f; GameObject val3 = Object.Instantiate(((Component)val).gameObject, val2.transform.position, ((Component)this).transform.rotation); val3.transform.localScale = Vector3.one * Mathf.Max(0.2f, Scale.x); PlayerDeathEffects component = val3.GetComponent(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val3); Object.Destroy((Object)(object)val2); return; } component.followTransform = val2.transform; component.playerAvatarVisuals = MiniVisuals; val3.SetActive(true); component.Trigger(); if ((Object)(object)component.hurtCollider != (Object)null) { ((Component)component.hurtCollider).gameObject.SetActive(false); } Object.Destroy((Object)(object)val3, 10f); Object.Destroy((Object)(object)val2, 10f); } catch (Exception ex) { BridgeLog.Debug("Mini-Semibot arena explosion failed: " + ex.Message); } } internal static bool RunIsKartArena() { Level val = (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelCurrent : null); if ((Object)(object)val != (Object)null) { return ((Object)val).name == "Level - Arena Race"; } return false; } private void ApplyMenuGaze() { //IL_0036: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MiniVisuals == (Object)null || (Object)(object)WearerVisuals == (Object)null || !WearerVisuals.isMenuAvatar) { return; } MiniSemibotLookAt lookAt = MiniSemibotSettings.LookAt; if (lookAt == MiniSemibotLookAt.Still) { return; } _sway = WearerHeadSway(); PlayerEyes playerEyes = WearerVisuals.playerEyes; PlayerEyes playerEyes2 = MiniVisuals.playerEyes; if (lookAt == MiniSemibotLookAt.Mouse) { Transform val = (((Object)(object)playerEyes != (Object)null) ? playerEyes.menuAvatarPointer : null); if ((Object)(object)playerEyes2 != (Object)null && (Object)(object)val != (Object)null) { playerEyes2.OverrideForce(val.position, 0.3f, ((Component)this).gameObject); if (AimHeadAtPoint(val.position)) { DeriveSecondaryGazeBones(); } } } else { CopyWearerGaze(); } } private void ApplyInGameGaze() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MiniVisuals == (Object)null || (Object)(object)WearerVisuals == (Object)null || WearerVisuals.isMenuAvatar) { return; } _sway = WearerHeadSway(); if (_mapHold == null) { _mapHold = ((Component)this).GetComponent(); } Transform val = (((Object)(object)_mapHold != (Object)null) ? _mapHold.ActiveCloneTransform : null); if ((Object)(object)val != (Object)null && AimHeadAtPoint(val.position)) { PlayerEyes playerEyes = MiniVisuals.playerEyes; if ((Object)(object)playerEyes != (Object)null) { playerEyes.OverrideForce(val.position, 0.3f, ((Component)this).gameObject); } DeriveSecondaryGazeBones(); } else { if (MiniSemibotVisualPrefs.IdleGlance && ApplyIdleGlance()) { return; } if (_cfg.Gaze == MiniSemibotGaze.SameTarget && AimHeadAtWearerTarget()) { AimEyesAtWearerTarget(); DeriveSecondaryGazeBones(); return; } if (WearerIsDriven()) { CopyWearerGaze(); return; } Transform headLookAtTransform = MiniVisuals.headLookAtTransform; if ((Object)(object)headLookAtTransform != (Object)null) { headLookAtTransform.localRotation = Quaternion.Slerp(headLookAtTransform.localRotation, Quaternion.identity, Time.deltaTime * 15f); } DeriveSecondaryGazeBones(); CopyWearerEyes(); } } private bool WearerIsDriven() { PlayerAvatarVisuals wearerVisuals = WearerVisuals; PlayerAvatar val = (((Object)(object)wearerVisuals != (Object)null) ? wearerVisuals.playerAvatar : null); if ((Object)(object)wearerVisuals != (Object)null) { if (!wearerVisuals.isMenuAvatar) { if (GameManager.Multiplayer() && (Object)(object)val != (Object)null && (Object)(object)val.photonView != (Object)null) { return !val.photonView.IsMine; } return false; } return true; } return false; } private Vector2 WearerHeadSway() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Expected O, but got Unknown PlayerAvatarVisuals wearerVisuals = WearerVisuals; if ((Object)(object)wearerVisuals == (Object)null) { return Vector2.zero; } if (WearerIsDriven()) { float num = (((Object)(object)wearerVisuals.headUpTransform != (Object)null) ? NormalizeAngle(wearerVisuals.headUpTransform.localEulerAngles.x) : 0f); float num2 = (((Object)(object)wearerVisuals.headSideTransform != (Object)null) ? NormalizeAngle(wearerVisuals.headSideTransform.localEulerAngles.y) : 0f); float num3 = (((Object)(object)wearerVisuals.headLookAtTransform != (Object)null) ? NormalizeAngle(wearerVisuals.headLookAtTransform.localEulerAngles.x) : 0f); float num4 = (((Object)(object)wearerVisuals.headLookAtTransform != (Object)null) ? NormalizeAngle(wearerVisuals.headLookAtTransform.localEulerAngles.y) : 0f); return new Vector2(num * 2f - num3, num2 * 2f - num4); } PlayerAvatar playerAvatar = wearerVisuals.playerAvatar; if ((Object)(object)playerAvatar == (Object)null) { return Vector2.zero; } float deltaTime = Time.deltaTime; if (deltaTime <= 0f) { return _sway; } float num5 = 0f; if (!playerAvatar.isTumbling && !playerAvatar.rotationDisabled && !playerAvatar.rotationOverrideActive && (Object)(object)playerAvatar.localCamera != (Object)null) { num5 = playerAvatar.localCamera.GetOverrideTransform().eulerAngles.x; } if (num5 > 90f) { num5 -= 360f; } if (playerAvatar.isCrawling) { num5 *= 0.4f; } else if (playerAvatar.isCrouching) { num5 *= 0.75f; } num5 = (playerAvatar.isCrouching ? Mathf.Clamp(num5, -40f, 40f) : Mathf.Clamp(num5, -75f, 85f)); if (_swayUpSpring == null) { _swayUpSpring = new SpringFloat { damping = (((Object)(object)MiniVisuals != (Object)null && MiniVisuals.lookUpSpring != null) ? MiniVisuals.lookUpSpring.damping : 0.5f), speed = (((Object)(object)MiniVisuals != (Object)null && MiniVisuals.lookUpSpring != null) ? MiniVisuals.lookUpSpring.speed : 10f) }; } float num6 = SemiFunc.SpringFloatGet(_swayUpSpring, num5, deltaTime); float y = ((Component)playerAvatar).transform.eulerAngles.y; if (!_swayYawInit) { _swayPrevYaw = y; _swayYawInit = true; } float num7 = Mathf.DeltaAngle(_swayPrevYaw, y); _swayPrevYaw = y; float num8 = Mathf.Clamp((0f - num7) * 5f, -100f, 100f); _swaySteer = Mathf.Lerp(_swaySteer, num8, 20f * deltaTime); return new Vector2(num6, _swaySteer); } private bool ApplyIdleGlance() { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) PlayerEyes val = (((Object)(object)WearerVisuals != (Object)null) ? WearerVisuals.playerEyes : null); if ((Object)(object)val == (Object)null || val.lookAtActive) { return false; } Transform val2 = (((Object)(object)MiniVisuals != (Object)null) ? MiniVisuals.headLookAtTransform : null); if ((Object)(object)val2 == (Object)null) { return false; } _glanceTimer -= Time.deltaTime; if (_glanceTimer <= 0f) { _glanceYawTarget = Random.Range(-28f, 28f); _glancePitchTarget = Random.Range(-8f, 10f); _glanceTimer = Random.Range(4f, 15f); } float num = 1f - Mathf.Exp(-3.5f * Time.deltaTime); _glanceYaw = Mathf.Lerp(_glanceYaw, _glanceYawTarget, num); _glancePitch = Mathf.Lerp(_glancePitch, _glancePitchTarget, num); Vector3 val3 = ((Component)MiniVisuals).transform.rotation * Quaternion.Euler(_glancePitch, _glanceYaw, 0f) * Vector3.forward; Vector3 val4 = val2.position + val3 * 3f; if (!AimHeadAtPoint(val4)) { return false; } DeriveSecondaryGazeBones(); PlayerEyes playerEyes = MiniVisuals.playerEyes; if ((Object)(object)playerEyes != (Object)null) { playerEyes.OverrideForce(val4, 0.3f, ((Component)this).gameObject); } return true; } private bool AimHeadAtWearerTarget() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) PlayerEyes playerEyes = WearerVisuals.playerEyes; if ((Object)(object)playerEyes == (Object)null || (Object)(object)playerEyes.lookAt == (Object)null) { return false; } return AimHeadAtPoint(playerEyes.lookAt.position); } private bool AimHeadAtPoint(Vector3 point) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) //IL_006a: Unknown result type (might be due to invalid IL or missing references) Transform headLookAtTransform = MiniVisuals.headLookAtTransform; if ((Object)(object)headLookAtTransform == (Object)null) { return false; } Vector3 val = point - headLookAtTransform.position; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { return false; } Vector3 forward = ((Component)MiniVisuals).transform.forward; val = SemiFunc.ClampDirection(val, forward, 40f); headLookAtTransform.rotation = Quaternion.Slerp(headLookAtTransform.rotation, Quaternion.LookRotation(val), Time.deltaTime * 15f); return true; } private void DeriveSecondaryGazeBones() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) PlayerAvatarVisuals miniVisuals = MiniVisuals; Transform val = (((Object)(object)miniVisuals != (Object)null) ? miniVisuals.headLookAtTransform : null); if (!((Object)(object)miniVisuals == (Object)null) && !((Object)(object)val == (Object)null)) { float num = NormalizeAngle(val.localEulerAngles.x) + _sway.x; float num2 = NormalizeAngle(val.localEulerAngles.y) + _sway.y; SetLocalRot(miniVisuals.headUpTransform, Quaternion.Euler(num * 0.5f, 0f, 0f)); SetLocalRot(miniVisuals.bodyTopUpTransform, Quaternion.Euler(num * 0.25f, 0f, 0f)); SetLocalRot(miniVisuals.headSideTransform, Quaternion.Euler(0f, num2 * 0.5f, 0f)); SetLocalRot(miniVisuals.bodyTopSideTransform, Quaternion.Euler(0f, num2 * 0.25f, 0f)); } } private static float NormalizeAngle(float a) { if (!(a > 180f)) { return a; } return a - 360f; } private static void SetLocalRot(Transform? t, Quaternion r) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t != (Object)null) { t.localRotation = r; } } private void AimEyesAtWearerTarget() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) PlayerEyes playerEyes = WearerVisuals.playerEyes; PlayerEyes playerEyes2 = MiniVisuals.playerEyes; if (!((Object)(object)playerEyes == (Object)null) && !((Object)(object)playerEyes.lookAt == (Object)null) && !((Object)(object)playerEyes2 == (Object)null)) { playerEyes2.OverrideForce(playerEyes.lookAt.position, 0.3f, ((Component)this).gameObject); } } private void CopyWearerGaze() { if (!((Object)(object)WearerVisuals == (Object)null) && !((Object)(object)MiniVisuals == (Object)null)) { CopyLocalRot(WearerVisuals.headLookAtTransform, MiniVisuals.headLookAtTransform); CopyLocalRot(WearerVisuals.headUpTransform, MiniVisuals.headUpTransform); CopyLocalRot(WearerVisuals.headSideTransform, MiniVisuals.headSideTransform); CopyLocalRot(WearerVisuals.bodyTopUpTransform, MiniVisuals.bodyTopUpTransform); CopyLocalRot(WearerVisuals.bodyTopSideTransform, MiniVisuals.bodyTopSideTransform); CopyWearerEyes(); } } private void CopyWearerEyes() { PlayerEyes val = (((Object)(object)WearerVisuals != (Object)null) ? WearerVisuals.playerEyes : null); PlayerEyes val2 = (((Object)(object)MiniVisuals != (Object)null) ? MiniVisuals.playerEyes : null); if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { CopyLocalRot(val.eyeLeft, val2.eyeLeft); CopyLocalRot(val.eyeRight, val2.eyeRight); CopyLocalRot(val.pupilLeft, val2.pupilLeft); CopyLocalRot(val.pupilRight, val2.pupilRight); } } private static void CopyLocalRot(Transform? from, Transform? to) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)from != (Object)null && (Object)(object)to != (Object)null) { to.localRotation = from.localRotation; } } } internal static class MiniSemibotIcon { private static Sprite? _cached; internal static Sprite Create() { //IL_001f: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cached != (Object)null) { return _cached; } Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false) { filterMode = (FilterMode)1, hideFlags = (HideFlags)61 }; Color[] array = (Color[])(object)new Color[16384]; for (int i = 0; i < array.Length; i++) { array[i] = new Color(0f, 0f, 0f, 0f); } val.SetPixels(array); FillRoundedRect(val, 12, 12, 116, 116, 22, new Color(0.1f, 0.12f, 0.16f, 0.85f)); Color c = default(Color); ((Color)(ref c))..ctor(0.85f, 0.93f, 1f, 1f); FillDisc(val, 64, 46, 30, c); FillDisc(val, 64, 90, 20, c); val.Apply(); _cached = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f); ((Object)_cached).name = "MHB_MiniSemibotIcon"; return _cached; } private static void FillDisc(Texture2D tex, int cx, int cy, int r, Color c) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) int num = r * r; for (int i = cy - r; i <= cy + r; i++) { if (i < 0 || i >= ((Texture)tex).height) { continue; } for (int j = cx - r; j <= cx + r; j++) { if (j >= 0 && j < ((Texture)tex).width) { int num2 = j - cx; int num3 = i - cy; if (num2 * num2 + num3 * num3 <= num) { tex.SetPixel(j, i, c); } } } } } private static void FillRoundedRect(Texture2D tex, int x0, int y0, int x1, int y1, int radius, Color c) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) int num = radius * radius; for (int i = y0; i < y1; i++) { if (i < 0 || i >= ((Texture)tex).height) { continue; } for (int j = x0; j < x1; j++) { if (j >= 0 && j < ((Texture)tex).width) { int num2 = ((j < x0 + radius) ? (x0 + radius) : ((j >= x1 - radius) ? (x1 - radius - 1) : j)); int num3 = ((i < y0 + radius) ? (y0 + radius) : ((i >= y1 - radius) ? (y1 - radius - 1) : i)); int num4 = j - num2; int num5 = i - num3; if (num4 * num4 + num5 * num5 <= num) { tex.SetPixel(j, i, c); } } } } } } internal static class MiniSemibotIconCapture { private static bool _attempted; internal static void TryStart(MonoBehaviour host) { if ((Object)(object)host == (Object)null || !Plugin.EnableMiniSemibot.Value) { return; } CosmeticAsset asset = MiniSemibotCosmetic.Asset; if ((Object)(object)asset == (Object)null) { return; } if (IconCapture.HasCache(asset)) { Sprite val = SemiFunc.LoadSpriteFromFile(IconCapture.CachePathFor(asset)); if ((Object)(object)val != (Object)null) { asset.icon = val; } } else if (!_attempted) { _attempted = true; host.StartCoroutine(Run(asset, useWearerColors: false)); } } internal static void ForceRecapture(MonoBehaviour host) { CosmeticAsset asset = MiniSemibotCosmetic.Asset; if (!((Object)(object)asset == (Object)null) && !((Object)(object)host == (Object)null)) { IconCapture.DeleteCache(asset); asset.icon = MiniSemibotIcon.Create(); _attempted = true; host.StartCoroutine(Run(asset, useWearerColors: true)); } } private static IEnumerator Run(CosmeticAsset asset, bool useWearerColors) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { yield break; } GameObject val = FindIconAvatarPrefab(); if ((Object)(object)val == (Object)null) { BceConsole.LogWarning("Mini-Semibot: preset icon-maker prefab not found — keeping the drawn icon"); yield break; } GameObject spawned = Object.Instantiate(val, new Vector3(-1000f, -1000f, -1000f), Quaternion.identity); PlayerCosmetics componentInChildren = spawned.GetComponentInChildren(); PlayerAvatarMenu componentInChildren2 = spawned.GetComponentInChildren(); object obj; if (componentInChildren2 == null) { obj = null; } else { Transform cameraAndStuff = componentInChildren2.cameraAndStuff; obj = ((cameraAndStuff != null) ? ((Component)cameraAndStuff).GetComponentInChildren(true) : null); } SemiIconMaker iconMaker = (SemiIconMaker)obj; if ((Object)(object)componentInChildren == (Object)null || (Object)(object)iconMaker == (Object)null) { Object.Destroy((Object)(object)spawned); BceConsole.LogWarning("Mini-Semibot: icon-maker avatar incomplete — keeping the drawn icon"); yield break; } SemiIconMaker[] componentsInChildren = spawned.GetComponentsInChildren(); foreach (SemiIconMaker val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)(object)iconMaker) { ((Component)val2).gameObject.SetActive(false); } } if (!((Component)iconMaker).gameObject.activeSelf) { ((Component)iconMaker).gameObject.SetActive(true); } int[] colorsEquipped = instance.colorsEquipped; int num = ((colorsEquipped != null) ? colorsEquipped.Length : 0); int[] array = ((useWearerColors && instance.colorsEquipped != null) ? ((int[])instance.colorsEquipped.Clone()) : new int[num]); componentInChildren.SetupCosmeticsLogic(Array.Empty(), false); componentInChildren.SetupColorsLogic(array); yield return null; Texture2D val3; try { val3 = RenderIconTexture(iconMaker); } finally { Object.Destroy((Object)(object)spawned); } Sprite val4 = null; if ((Object)(object)val3 != (Object)null) { val4 = IconCapture.SaveSquareContent(val3, IconCapture.CachePathFor(asset)); Object.Destroy((Object)(object)val3); } if ((Object)(object)val4 != (Object)null) { asset.icon = val4; MenuPageCosmetics? activePage = CosmeticsMenuState.ActivePage; if (activePage != null) { activePage.RefreshScrollContent(); } BceConsole.LogInfo("Mini-Semibot: captured preset-style icon", ConsoleColor.Cyan); } else { BceConsole.LogWarning("Mini-Semibot: icon capture failed — keeping the drawn icon"); } } private static Texture2D? RenderIconTexture(SemiIconMaker iconMaker) { //IL_0070: 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_004b: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) object? obj = AccessTools.Field(typeof(SemiIconMaker), "renderTextureInstance")?.GetValue(iconMaker); RenderTexture val = (RenderTexture)((obj is RenderTexture) ? obj : null); if ((Object)(object)val == (Object)null || (Object)(object)iconMaker.iconCamera == (Object)null) { return null; } bool fog = RenderSettings.fog; Color ambientLight = RenderSettings.ambientLight; try { RenderSettings.fog = false; RenderSettings.ambientLight = iconMaker.ambientLight; iconMaker.iconCamera.Render(); } finally { RenderSettings.fog = fog; RenderSettings.ambientLight = ambientLight; } RenderTexture active = RenderTexture.active; try { RenderTexture.active = val; Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, false); val2.ReadPixels(new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), 0, 0); val2.Apply(false, false); return val2; } finally { RenderTexture.active = active; } } private static GameObject? FindIconAvatarPrefab() { MenuPageCosmetics val = CosmeticsMenuState.ActivePage ?? Object.FindObjectOfType(true); GameObject val2 = (((Object)(object)val != (Object)null) ? val.presetButtonPrefab : null); MenuElementCosmeticPreset val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent() : null); if (!((Object)(object)val3 != (Object)null)) { return null; } return val3.playerAvatarIconPrefab; } } internal static class MiniSemibotMimicAudio { private sealed class Incoming { public byte[]?[] Chunks = Array.Empty(); public int Received; public int Total; } private const int ChunkSize = 8192; private const int MaxChunks = 128; private const int MaxClipBytes = 1048576; private static readonly Dictionary _faces = new Dictionary(); private static readonly Dictionary _incoming = new Dictionary(); internal static string AudioFolder => Path.Combine(Application.dataPath, "AudioFiles"); internal static void RegisterFace(int actor, MiniSemibotFace face) { if (actor >= 0) { _faces[actor] = face; } } internal static void UnregisterFace(int actor, MiniSemibotFace face) { if (actor >= 0 && _faces.TryGetValue(actor, out MiniSemibotFace value) && (Object)(object)value == (Object)(object)face) { _faces.Remove(actor); _incoming.Remove(actor); } } internal static byte[]? PickRandomClipBytes() { try { if (!Directory.Exists(AudioFolder)) { return null; } string[] files = Directory.GetFiles(AudioFolder, "*.wav"); if (files.Length == 0) { return null; } string path = files[Random.Range(0, files.Length)]; byte[] array = File.ReadAllBytes(path); int num = array.Length; return (num > 44 && num <= 1048576) ? array : null; } catch (Exception ex) { BridgeLog.Debug("MiniSemibotMimicAudio: could not read a recorded clip — " + ex.Message); return null; } } internal static void BroadcastClip(byte[] wav) { if (!SemiFunc.IsMultiplayer() || wav == null || wav.Length <= 44) { return; } int num = (wav.Length + 8192 - 1) / 8192; if (num <= 128) { for (int i = 0; i < num; i++) { int num2 = i * 8192; int num3 = Mathf.Min(8192, wav.Length - num2); byte[] array = new byte[num3]; Array.Copy(wav, num2, array, 0, num3); BridgeNetMux.SendTransient("MimicAudio", new object[3] { num, i, array }); } } } internal static void OnChunk(int actor, object data) { if (!(data is object[] array) || array.Length != 3) { return; } int num; int num2; byte[] array2; try { num = (int)array[0]; num2 = (int)array[1]; array2 = (byte[])array[2]; } catch { return; } if (num <= 0 || num > 128 || num2 < 0 || num2 >= num || array2 == null) { return; } if (!_incoming.TryGetValue(actor, out Incoming value) || value.Total != num || num2 == 0) { Incoming incoming = new Incoming(); incoming.Chunks = new byte[num][]; incoming.Received = 0; incoming.Total = num; value = incoming; _incoming[actor] = value; } if (value.Chunks[num2] == null) { value.Chunks[num2] = array2; value.Received++; } if (value.Received >= value.Total) { _incoming.Remove(actor); byte[] array3 = Concat(value.Chunks); if (array3.Length <= 1048576 && _faces.TryGetValue(actor, out MiniSemibotFace value2) && (Object)(object)value2 != (Object)null) { value2.PlayMimicClip(array3); } } } private static byte[] Concat(byte[]?[] chunks) { int num = 0; foreach (byte[] array in chunks) { num += ((array != null) ? array.Length : 0); } byte[] array2 = new byte[num]; int num2 = 0; foreach (byte[] array3 in chunks) { if (array3 != null) { Array.Copy(array3, 0, array2, num2, array3.Length); num2 += array3.Length; } } return array2; } internal static bool TryDecodeWav(byte[] wav, out float[] samples, out int channels, out int frequency) { samples = Array.Empty(); channels = 1; frequency = 16000; try { if (wav.Length < 44) { return false; } if (wav[0] != 82 || wav[1] != 73 || wav[2] != 70 || wav[3] != 70) { return false; } if (wav[8] != 87 || wav[9] != 65 || wav[10] != 86 || wav[11] != 69) { return false; } int num = 16; int num2 = -1; int num3 = 0; int num4 = 12; while (num4 + 8 <= wav.Length) { int num5 = BitConverter.ToInt32(wav, num4 + 4); int num6 = num4 + 8; if (num5 < 0 || num6 + num5 > wav.Length + 1) { break; } if (IsId(wav, num4, 'f', 'm', 't', ' ')) { channels = BitConverter.ToInt16(wav, num6 + 2); frequency = BitConverter.ToInt32(wav, num6 + 4); num = BitConverter.ToInt16(wav, num6 + 14); } else if (IsId(wav, num4, 'd', 'a', 't', 'a')) { num2 = num6; num3 = Mathf.Min(num5, wav.Length - num6); break; } num4 = num6 + num5 + (num5 & 1); } if (num2 < 0 || num3 <= 0 || num != 16) { return false; } if (channels < 1) { channels = 1; } if (frequency < 8000 || frequency > 48000) { frequency = 16000; } int num7 = num3 / 2; samples = new float[num7]; for (int i = 0; i < num7; i++) { short num8 = (short)(wav[num2 + i * 2] | (wav[num2 + i * 2 + 1] << 8)); samples[i] = (float)num8 / 32768f; } return num7 > 0; } catch { return false; } } private static bool IsId(byte[] b, int off, char a, char c, char d, char e) { if (b[off] == a && b[off + 1] == c && b[off + 2] == d) { return b[off + 3] == e; } return false; } } internal static class MiniSemibotModCompat { private const string CustomGrabColorGuid = "games.enchanted.CustomGrabColour"; private const string MimicGuid = "Mimics"; private static bool? _hasCgc; private static bool? _hasMimic; internal static bool HasCustomGrabColor { get { bool valueOrDefault = _hasCgc == true; if (!_hasCgc.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("games.enchanted.CustomGrabColour"); _hasCgc = valueOrDefault; return valueOrDefault; } return valueOrDefault; } } internal static bool HasMimic { get { bool valueOrDefault = _hasMimic == true; if (!_hasMimic.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("Mimics"); _hasMimic = valueOrDefault; return valueOrDefault; } return valueOrDefault; } } } internal static class MiniSemibotOutfitCache { private static readonly Dictionary _cosmetics = new Dictionary(); private static readonly Dictionary _colors = new Dictionary(); internal static void RecordCosmetics(PlayerCosmetics pc, int[]? indices) { if (!((Object)(object)pc == (Object)null) && indices != null) { Prune(); _cosmetics[pc] = (int[])indices.Clone(); } } internal static void RecordColors(PlayerCosmetics pc, int[]? colors) { if (!((Object)(object)pc == (Object)null) && colors != null) { Prune(); _colors[pc] = (int[])colors.Clone(); } } internal static int[]? GetCosmetics(PlayerCosmetics pc) { if (!((Object)(object)pc != (Object)null) || !_cosmetics.TryGetValue(pc, out int[] value)) { return null; } return value; } internal static int[]? GetColors(PlayerCosmetics pc) { if (!((Object)(object)pc != (Object)null) || !_colors.TryGetValue(pc, out int[] value)) { return null; } return value; } private static void Prune() { PruneDict(_cosmetics); PruneDict(_colors); } private static void PruneDict(Dictionary dict) { if (dict.Count == 0) { return; } List list = null; foreach (PlayerCosmetics key in dict.Keys) { if ((Object)(object)key == (Object)null) { (list ?? (list = new List())).Add(key); } } if (list == null) { return; } foreach (PlayerCosmetics item in list) { dict.Remove(item); } } } internal static class MiniSemibotOverridePopup { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Action <>9__17_21; public static ScrollViewBuilderDelegate <>9__17_0; public static Action <>9__17_22; public static ScrollViewBuilderDelegate <>9__17_1; public static Action <>9__17_23; public static ScrollViewBuilderDelegate <>9__17_2; public static Action <>9__17_24; public static ScrollViewBuilderDelegate <>9__17_3; public static Action <>9__17_25; public static ScrollViewBuilderDelegate <>9__17_4; public static Action <>9__17_26; public static ScrollViewBuilderDelegate <>9__17_5; public static Action <>9__17_27; public static ScrollViewBuilderDelegate <>9__17_6; public static Action <>9__17_28; public static ScrollViewBuilderDelegate <>9__17_7; public static Action <>9__17_29; public static ScrollViewBuilderDelegate <>9__17_8; public static Action <>9__17_30; public static ScrollViewBuilderDelegate <>9__17_9; public static Action <>9__17_31; public static ScrollViewBuilderDelegate <>9__17_10; public static Action <>9__17_36; public static Action <>9__17_37; public static Action <>9__17_38; public static Action <>9__17_39; public static ScrollViewBuilderDelegate <>9__17_13; public static Action <>9__17_40; public static ScrollViewBuilderDelegate <>9__17_14; public static Action <>9__17_41; public static ScrollViewBuilderDelegate <>9__17_15; public static Action <>9__17_42; public static ScrollViewBuilderDelegate <>9__17_16; public static Action <>9__17_43; public static ScrollViewBuilderDelegate <>9__17_17; public static Action <>9__17_44; public static ScrollViewBuilderDelegate <>9__17_18; internal RectTransform b__17_0(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Position", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.Position = ((opt == "Front") ? MiniSemibotPosition.Front : MiniSemibotPosition.Behind); Apply(); }, scrollView, PositionOptions, (MiniSemibotVisualPrefs.Position == MiniSemibotPosition.Front) ? "Front" : "Behind", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_21(string opt) { MiniSemibotVisualPrefs.Position = ((opt == "Front") ? MiniSemibotPosition.Front : MiniSemibotPosition.Behind); Apply(); } internal RectTransform b__17_1(Transform scrollView) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotVisualPrefs.Size = opt switch { "Baby" => MiniSemibotSize.Baby, "Teen" => MiniSemibotSize.Teen, "Junior" => MiniSemibotSize.Junior, _ => MiniSemibotSize.Child, }; MiniSemibotSpawner.ApplyLiveSettings(); }; string text = MiniSemibotVisualPrefs.Size switch { MiniSemibotSize.Baby => "Baby", MiniSemibotSize.Teen => "Teen", MiniSemibotSize.Junior => "Junior", _ => "Child", }; REPOSlider val = MenuAPI.CreateREPOSlider("Size", "", action, scrollView, SizeOptions, text, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_22(string opt) { MiniSemibotVisualPrefs.Size = opt switch { "Baby" => MiniSemibotSize.Baby, "Teen" => MiniSemibotSize.Teen, "Junior" => MiniSemibotSize.Junior, _ => MiniSemibotSize.Child, }; MiniSemibotSpawner.ApplyLiveSettings(); } internal RectTransform b__17_2(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Outfit", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.OutfitMode = ((opt == "Random Preset") ? MiniSemibotOutfitMode.RandomPreset : MiniSemibotOutfitMode.SameAsPlayer); MiniSemibotSpawner.ClearLocalRoll(); Apply(); }, scrollView, OutfitOptions, (MiniSemibotVisualPrefs.OutfitMode == MiniSemibotOutfitMode.RandomPreset) ? "Random Preset" : "Same As You", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_23(string opt) { MiniSemibotVisualPrefs.OutfitMode = ((opt == "Random Preset") ? MiniSemibotOutfitMode.RandomPreset : MiniSemibotOutfitMode.SameAsPlayer); MiniSemibotSpawner.ClearLocalRoll(); Apply(); } internal RectTransform b__17_3(Transform scrollView) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotLookAt lookAt2 = ((opt == "Copy Avatar") ? MiniSemibotLookAt.Copy : ((!(opt == "Still")) ? MiniSemibotLookAt.Mouse : MiniSemibotLookAt.Still)); MiniSemibotVisualPrefs.LookAt = lookAt2; }; MiniSemibotLookAt lookAt = MiniSemibotVisualPrefs.LookAt; REPOSlider val = MenuAPI.CreateREPOSlider("Look At", "", action, scrollView, LookAtOptions, lookAt switch { MiniSemibotLookAt.Copy => "Copy Avatar", MiniSemibotLookAt.Still => "Still", _ => "At Mouse", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_24(string opt) { MiniSemibotLookAt lookAt = ((opt == "Copy Avatar") ? MiniSemibotLookAt.Copy : ((!(opt == "Still")) ? MiniSemibotLookAt.Mouse : MiniSemibotLookAt.Still)); MiniSemibotVisualPrefs.LookAt = lookAt; } internal RectTransform b__17_4(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Look At", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.Gaze = ((opt == "Copy Head") ? MiniSemibotGaze.CopyHead : MiniSemibotGaze.SameTarget); MiniSemibotSpawner.ApplyLiveSettings(); }, scrollView, GazeOptions, (MiniSemibotVisualPrefs.Gaze == MiniSemibotGaze.CopyHead) ? "Copy Head" : "Same Target", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_25(string opt) { MiniSemibotVisualPrefs.Gaze = ((opt == "Copy Head") ? MiniSemibotGaze.CopyHead : MiniSemibotGaze.SameTarget); MiniSemibotSpawner.ApplyLiveSettings(); } internal RectTransform b__17_5(Transform scrollView) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown Action action = delegate(string opt) { FollowSpringMode followSpring2 = ((opt == "Soft") ? FollowSpringMode.Soft : ((opt == "Bouncy") ? FollowSpringMode.Springy : FollowSpringMode.Off)); MiniSemibotVisualPrefs.FollowSpring = followSpring2; }; FollowSpringMode followSpring = MiniSemibotVisualPrefs.FollowSpring; REPOSlider val = MenuAPI.CreateREPOSlider("Follow Smoothing", "", action, scrollView, SpringOptions, followSpring switch { FollowSpringMode.Soft => "Soft", FollowSpringMode.Springy => "Bouncy", _ => "Off", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_26(string opt) { FollowSpringMode followSpring = ((opt == "Soft") ? FollowSpringMode.Soft : ((opt == "Bouncy") ? FollowSpringMode.Springy : FollowSpringMode.Off)); MiniSemibotVisualPrefs.FollowSpring = followSpring; } internal RectTransform b__17_6(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Avoid Walls", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.AvoidWalls = opt == "On"; MiniSemibotSync.BroadcastLocal(); }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.AvoidWalls ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_27(string opt) { MiniSemibotVisualPrefs.AvoidWalls = opt == "On"; MiniSemibotSync.BroadcastLocal(); } internal RectTransform b__17_7(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Idle Glance", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.IdleGlance = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.IdleGlance ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_28(string opt) { MiniSemibotVisualPrefs.IdleGlance = opt == "On"; } internal RectTransform b__17_8(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("State Effects", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.StateEffects = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.StateEffects ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_29(string opt) { MiniSemibotVisualPrefs.StateEffects = opt == "On"; } internal RectTransform b__17_9(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Footstep Sounds", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.FootstepSounds = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.FootstepSounds ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_30(string opt) { MiniSemibotVisualPrefs.FootstepSounds = opt == "On"; } internal RectTransform b__17_10(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Flashlight", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.MiniFlashlight = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.MiniFlashlight ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_31(string opt) { MiniSemibotVisualPrefs.MiniFlashlight = opt == "On"; } internal void b__17_36(string opt) { MiniSemibotMimicChatter mimicChatter = ((!(opt == "Talks Little")) ? ((!(opt == "Talks Lots")) ? MiniSemibotMimicChatter.Moderate : MiniSemibotMimicChatter.Lots) : MiniSemibotMimicChatter.Little); MiniSemibotVisualPrefs.MimicChatter = mimicChatter; MiniSemibotSpawner.ApplyLiveSettings(); } internal void b__17_37(string opt) { MiniSemibotMimicVolume mimicVolume = ((!(opt == "Low")) ? ((!(opt == "High")) ? MiniSemibotMimicVolume.Medium : MiniSemibotMimicVolume.High) : MiniSemibotMimicVolume.Low); MiniSemibotVisualPrefs.MimicVolume = mimicVolume; MiniSemibotSpawner.ApplyLiveSettings(); } internal void b__17_38(string opt) { MiniSemibotMimicRange mimicRange = ((!(opt == "Near")) ? ((!(opt == "Far")) ? MiniSemibotMimicRange.Medium : MiniSemibotMimicRange.Far) : MiniSemibotMimicRange.Near); MiniSemibotVisualPrefs.MimicRange = mimicRange; MiniSemibotSpawner.ApplyLiveSettings(); } internal RectTransform b__17_13(Transform scrollView) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotGrabberVisual grabber2 = ((opt == "Orb") ? MiniSemibotGrabberVisual.Orb : ((opt == "Orb + Light") ? MiniSemibotGrabberVisual.OrbLight : MiniSemibotGrabberVisual.CleanArm)); MiniSemibotVisualPrefs.Grabber = grabber2; MiniSemibotSpawner.ApplyLiveSettings(); }; MiniSemibotGrabberVisual grabber = MiniSemibotVisualPrefs.Grabber; REPOSlider val = MenuAPI.CreateREPOSlider("Holding", "", action, scrollView, HandsOptions, grabber switch { MiniSemibotGrabberVisual.Orb => "Orb", MiniSemibotGrabberVisual.OrbLight => "Orb + Light", _ => "Clean Arm", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_39(string opt) { MiniSemibotGrabberVisual grabber = ((opt == "Orb") ? MiniSemibotGrabberVisual.Orb : ((opt == "Orb + Light") ? MiniSemibotGrabberVisual.OrbLight : MiniSemibotGrabberVisual.CleanArm)); MiniSemibotVisualPrefs.Grabber = grabber; MiniSemibotSpawner.ApplyLiveSettings(); } internal RectTransform b__17_14(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Beam Color", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.BeamColor = ((opt == "Mini-Semibot Grabber") ? MiniSemibotBeamColor.MiniGrabber : MiniSemibotBeamColor.SameAsPlayer); MiniSemibotSpawner.ApplyLiveSettings(); }, scrollView, BeamOptions, (MiniSemibotVisualPrefs.BeamColor == MiniSemibotBeamColor.MiniGrabber) ? "Mini-Semibot Grabber" : "Same As You", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_40(string opt) { MiniSemibotVisualPrefs.BeamColor = ((opt == "Mini-Semibot Grabber") ? MiniSemibotBeamColor.MiniGrabber : MiniSemibotBeamColor.SameAsPlayer); MiniSemibotSpawner.ApplyLiveSettings(); } internal RectTransform b__17_15(Transform scrollView) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Leg Speed", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.LegSpeed = LegSpeedFromOption(opt); Apply(); }, scrollView, LegSpeedOptions, LegSpeedToOption(MiniSemibotVisualPrefs.LegSpeed), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_41(string opt) { MiniSemibotVisualPrefs.LegSpeed = LegSpeedFromOption(opt); Apply(); } internal RectTransform b__17_16(Transform scrollView) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotDeathBehavior deathBehavior2 = ((!(opt == "Death Head")) ? ((!(opt == "Hide")) ? MiniSemibotDeathBehavior.CrouchWait : MiniSemibotDeathBehavior.Hide) : MiniSemibotDeathBehavior.DeathHead); MiniSemibotVisualPrefs.DeathBehavior = deathBehavior2; Apply(); }; MiniSemibotDeathBehavior deathBehavior = MiniSemibotVisualPrefs.DeathBehavior; REPOSlider val = MenuAPI.CreateREPOSlider("When You Die", "", action, scrollView, DeathOptions, deathBehavior switch { MiniSemibotDeathBehavior.DeathHead => "Death Head", MiniSemibotDeathBehavior.Hide => "Hide", _ => "Crouch & Wait", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_42(string opt) { MiniSemibotDeathBehavior deathBehavior = ((!(opt == "Death Head")) ? ((!(opt == "Hide")) ? MiniSemibotDeathBehavior.CrouchWait : MiniSemibotDeathBehavior.Hide) : MiniSemibotDeathBehavior.DeathHead); MiniSemibotVisualPrefs.DeathBehavior = deathBehavior; Apply(); } internal RectTransform b__17_17(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Hide on Kart", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.HideInArena = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.HideInArena ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_43(string opt) { MiniSemibotVisualPrefs.HideInArena = opt == "On"; } internal RectTransform b__17_18(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val = MenuAPI.CreateREPOSlider("Show Mini", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.ShowInExpressionPreview = opt == "On"; MiniSemibotSpawner.RefreshExpressionPreview(); }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.ShowInExpressionPreview ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val).transform; } internal void b__17_44(string opt) { MiniSemibotVisualPrefs.ShowInExpressionPreview = opt == "On"; MiniSemibotSpawner.RefreshExpressionPreview(); } } private const float PopupX = -120f; private const float TitleGap = 15f; private static readonly string[] PositionOptions = new string[2] { "Behind", "Front" }; private static readonly string[] DeathOptions = new string[3] { "Death Head", "Crouch & Wait", "Hide" }; private static readonly string[] OutfitOptions = new string[2] { "Same As You", "Random Preset" }; private static readonly string[] LegSpeedOptions = new string[8] { "1.0x", "1.2x", "1.4x", "1.6x", "1.8x", "2.0x", "2.5x", "3.0x" }; private static readonly string[] LookAtOptions = new string[3] { "At Mouse", "Copy Avatar", "Still" }; private static readonly string[] HandsOptions = new string[3] { "Clean Arm", "Orb", "Orb + Light" }; private static readonly string[] SizeOptions = new string[4] { "Baby", "Child", "Teen", "Junior" }; private static readonly string[] GazeOptions = new string[2] { "Same Target", "Copy Head" }; private static readonly string[] BeamOptions = new string[2] { "Same As You", "Mini-Semibot Grabber" }; private static readonly string[] ChatterOptions = new string[3] { "Talks Little", "Moderate", "Talks Lots" }; private static readonly string[] VolumeOptions = new string[3] { "Low", "Medium", "High" }; private static readonly string[] RangeOptions = new string[3] { "Near", "Medium", "Far" }; private static readonly string[] OnOffOptions = new string[2] { "Off", "On" }; private static readonly string[] SpringOptions = new string[3] { "Off", "Soft", "Bouncy" }; internal static void Show(CosmeticAsset asset) { PopupUI.AfterMouseRelease((MonoBehaviour)(object)Plugin.Instance, delegate { ShowNow(asset); }); } private static void ShowNow(CosmeticAsset asset) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Expected O, but got Unknown //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Expected O, but got Unknown //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Expected O, but got Unknown //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Expected O, but got Unknown //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Expected O, but got Unknown //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Expected O, but got Unknown //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03f4: Expected O, but got Unknown //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Expected O, but got Unknown //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Expected O, but got Unknown //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_0540: Expected O, but got Unknown //IL_04ec: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Expected O, but got Unknown //IL_0569: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0574: Expected O, but got Unknown //IL_059d: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_05a8: Expected O, but got Unknown //IL_0622: Unknown result type (might be due to invalid IL or missing references) //IL_0636: Expected O, but got Unknown //IL_0643: Unknown result type (might be due to invalid IL or missing references) //IL_0657: Expected O, but got Unknown //IL_05e6: Unknown result type (might be due to invalid IL or missing references) //IL_05eb: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Expected O, but got Unknown string text = asset.assetName ?? ((Object)asset).name ?? "Mini-Semibot"; REPOPopupPage popup = MenuAPI.CreateREPOPopupPage(text, false, true, 5f, (Vector2?)new Vector2(-120f, 0f)); PopupUI.AttachGuards(popup); AddSectionLabel(popup, "Placement", 15f); REPOPopupPage obj = popup; object obj2 = <>c.<>9__17_0; if (obj2 == null) { ScrollViewBuilderDelegate val = delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Position", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.Position = ((opt == "Front") ? MiniSemibotPosition.Front : MiniSemibotPosition.Behind); Apply(); }, scrollView, PositionOptions, (MiniSemibotVisualPrefs.Position == MiniSemibotPosition.Front) ? "Front" : "Behind", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_0 = val; obj2 = (object)val; } obj.AddElementToScrollView((ScrollViewBuilderDelegate)obj2, 10f, 0f); REPOPopupPage obj3 = popup; object obj4 = <>c.<>9__17_1; if (obj4 == null) { ScrollViewBuilderDelegate val2 = delegate(Transform scrollView) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotVisualPrefs.Size = opt switch { "Baby" => MiniSemibotSize.Baby, "Teen" => MiniSemibotSize.Teen, "Junior" => MiniSemibotSize.Junior, _ => MiniSemibotSize.Child, }; MiniSemibotSpawner.ApplyLiveSettings(); }; string text2 = MiniSemibotVisualPrefs.Size switch { MiniSemibotSize.Baby => "Baby", MiniSemibotSize.Teen => "Teen", MiniSemibotSize.Junior => "Junior", _ => "Child", }; REPOSlider val20 = MenuAPI.CreateREPOSlider("Size", "", action, scrollView, SizeOptions, text2, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_1 = val2; obj4 = (object)val2; } obj3.AddElementToScrollView((ScrollViewBuilderDelegate)obj4, 10f, 0f); AddSectionLabel(popup, "Outfit", 10f); REPOPopupPage obj5 = popup; object obj6 = <>c.<>9__17_2; if (obj6 == null) { ScrollViewBuilderDelegate val3 = delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Outfit", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.OutfitMode = ((opt == "Random Preset") ? MiniSemibotOutfitMode.RandomPreset : MiniSemibotOutfitMode.SameAsPlayer); MiniSemibotSpawner.ClearLocalRoll(); Apply(); }, scrollView, OutfitOptions, (MiniSemibotVisualPrefs.OutfitMode == MiniSemibotOutfitMode.RandomPreset) ? "Random Preset" : "Same As You", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_2 = val3; obj6 = (object)val3; } obj5.AddElementToScrollView((ScrollViewBuilderDelegate)obj6, 10f, 0f); AddSectionLabel(popup, "Menu Gaze", 10f); REPOPopupPage obj7 = popup; object obj8 = <>c.<>9__17_3; if (obj8 == null) { ScrollViewBuilderDelegate val4 = delegate(Transform scrollView) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotLookAt lookAt2 = ((opt == "Copy Avatar") ? MiniSemibotLookAt.Copy : ((!(opt == "Still")) ? MiniSemibotLookAt.Mouse : MiniSemibotLookAt.Still)); MiniSemibotVisualPrefs.LookAt = lookAt2; }; MiniSemibotLookAt lookAt = MiniSemibotVisualPrefs.LookAt; REPOSlider val20 = MenuAPI.CreateREPOSlider("Look At", "", action, scrollView, LookAtOptions, lookAt switch { MiniSemibotLookAt.Copy => "Copy Avatar", MiniSemibotLookAt.Still => "Still", _ => "At Mouse", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_3 = val4; obj8 = (object)val4; } obj7.AddElementToScrollView((ScrollViewBuilderDelegate)obj8, 10f, 0f); AddSectionLabel(popup, "In-Game Gaze", 10f); REPOPopupPage obj9 = popup; object obj10 = <>c.<>9__17_4; if (obj10 == null) { ScrollViewBuilderDelegate val5 = delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Look At", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.Gaze = ((opt == "Copy Head") ? MiniSemibotGaze.CopyHead : MiniSemibotGaze.SameTarget); MiniSemibotSpawner.ApplyLiveSettings(); }, scrollView, GazeOptions, (MiniSemibotVisualPrefs.Gaze == MiniSemibotGaze.CopyHead) ? "Copy Head" : "Same Target", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_4 = val5; obj10 = (object)val5; } obj9.AddElementToScrollView((ScrollViewBuilderDelegate)obj10, 10f, 0f); AddSectionLabel(popup, "Movement", 10f); REPOPopupPage obj11 = popup; object obj12 = <>c.<>9__17_5; if (obj12 == null) { ScrollViewBuilderDelegate val6 = delegate(Transform scrollView) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown Action action = delegate(string opt) { FollowSpringMode followSpring2 = ((opt == "Soft") ? FollowSpringMode.Soft : ((opt == "Bouncy") ? FollowSpringMode.Springy : FollowSpringMode.Off)); MiniSemibotVisualPrefs.FollowSpring = followSpring2; }; FollowSpringMode followSpring = MiniSemibotVisualPrefs.FollowSpring; REPOSlider val20 = MenuAPI.CreateREPOSlider("Follow Smoothing", "", action, scrollView, SpringOptions, followSpring switch { FollowSpringMode.Soft => "Soft", FollowSpringMode.Springy => "Bouncy", _ => "Off", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_5 = val6; obj12 = (object)val6; } obj11.AddElementToScrollView((ScrollViewBuilderDelegate)obj12, 10f, 0f); REPOPopupPage obj13 = popup; object obj14 = <>c.<>9__17_6; if (obj14 == null) { ScrollViewBuilderDelegate val7 = delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Avoid Walls", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.AvoidWalls = opt == "On"; MiniSemibotSync.BroadcastLocal(); }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.AvoidWalls ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_6 = val7; obj14 = (object)val7; } obj13.AddElementToScrollView((ScrollViewBuilderDelegate)obj14, 10f, 0f); REPOPopupPage obj15 = popup; object obj16 = <>c.<>9__17_7; if (obj16 == null) { ScrollViewBuilderDelegate val8 = delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Idle Glance", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.IdleGlance = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.IdleGlance ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_7 = val8; obj16 = (object)val8; } obj15.AddElementToScrollView((ScrollViewBuilderDelegate)obj16, 10f, 0f); REPOPopupPage obj17 = popup; object obj18 = <>c.<>9__17_8; if (obj18 == null) { ScrollViewBuilderDelegate val9 = delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("State Effects", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.StateEffects = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.StateEffects ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_8 = val9; obj18 = (object)val9; } obj17.AddElementToScrollView((ScrollViewBuilderDelegate)obj18, 10f, 0f); REPOPopupPage obj19 = popup; object obj20 = <>c.<>9__17_9; if (obj20 == null) { ScrollViewBuilderDelegate val10 = delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Footstep Sounds", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.FootstepSounds = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.FootstepSounds ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_9 = val10; obj20 = (object)val10; } obj19.AddElementToScrollView((ScrollViewBuilderDelegate)obj20, 10f, 0f); REPOPopupPage obj21 = popup; object obj22 = <>c.<>9__17_10; if (obj22 == null) { ScrollViewBuilderDelegate val11 = delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Flashlight", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.MiniFlashlight = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.MiniFlashlight ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_10 = val11; obj22 = (object)val11; } obj21.AddElementToScrollView((ScrollViewBuilderDelegate)obj22, 10f, 0f); AddSectionLabel(popup, "Face", 10f); string[] mouthOptions = ((!MiniSemibotModCompat.HasMimic) ? new string[3] { "Never", "Random", "When I Talk" } : new string[4] { "Never", "Random", "When I Talk", "Mimic Clips" }); List mimicRows = new List(); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotVisualPrefs.MouthMode = opt switch { "Never" => MiniSemibotMouthMode.Never, "Random" => MiniSemibotMouthMode.Random, "Mimic Clips" => MiniSemibotMouthMode.MimicClips, _ => MiniSemibotMouthMode.WhenITalk, }; UpdateMimicRows(); MiniSemibotSpawner.ApplyLiveSettings(); }; string[] array2 = mouthOptions; REPOSlider val20 = MenuAPI.CreateREPOSlider("Mouth", "", action, scrollView, array2, MiniSemibotVisualPrefs.MouthMode switch { MiniSemibotMouthMode.Never => "Never", MiniSemibotMouthMode.Random => "Random", MiniSemibotMouthMode.MimicClips => "Mimic Clips", _ => "When I Talk", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }, 10f, 0f); if (MiniSemibotModCompat.HasMimic) { RectTransform chatterTr = null; RectTransform volumeTr = null; RectTransform rangeTr = null; popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_008b: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotMimicChatter mimicChatter2 = ((!(opt == "Talks Little")) ? ((!(opt == "Talks Lots")) ? MiniSemibotMimicChatter.Moderate : MiniSemibotMimicChatter.Lots) : MiniSemibotMimicChatter.Little); MiniSemibotVisualPrefs.MimicChatter = mimicChatter2; MiniSemibotSpawner.ApplyLiveSettings(); }; MiniSemibotMimicChatter mimicChatter = MiniSemibotVisualPrefs.MimicChatter; REPOSlider val20 = MenuAPI.CreateREPOSlider("Chatter - Mimic", "", action, scrollView, ChatterOptions, mimicChatter switch { MiniSemibotMimicChatter.Little => "Talks Little", MiniSemibotMimicChatter.Lots => "Talks Lots", _ => "Moderate", }, default(Vector2), "", "", (BarBehavior)0); RectTransform val21 = (RectTransform)((Component)val20).transform; RectTransform result = val21; chatterTr = val21; return result; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_008b: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotMimicVolume mimicVolume2 = ((!(opt == "Low")) ? ((!(opt == "High")) ? MiniSemibotMimicVolume.Medium : MiniSemibotMimicVolume.High) : MiniSemibotMimicVolume.Low); MiniSemibotVisualPrefs.MimicVolume = mimicVolume2; MiniSemibotSpawner.ApplyLiveSettings(); }; MiniSemibotMimicVolume mimicVolume = MiniSemibotVisualPrefs.MimicVolume; REPOSlider val20 = MenuAPI.CreateREPOSlider("Voice Volume - Mimic", "", action, scrollView, VolumeOptions, mimicVolume switch { MiniSemibotMimicVolume.Low => "Low", MiniSemibotMimicVolume.High => "High", _ => "Medium", }, default(Vector2), "", "", (BarBehavior)0); RectTransform val21 = (RectTransform)((Component)val20).transform; RectTransform result = val21; volumeTr = val21; return result; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_008b: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotMimicRange mimicRange2 = ((!(opt == "Near")) ? ((!(opt == "Far")) ? MiniSemibotMimicRange.Medium : MiniSemibotMimicRange.Far) : MiniSemibotMimicRange.Near); MiniSemibotVisualPrefs.MimicRange = mimicRange2; MiniSemibotSpawner.ApplyLiveSettings(); }; MiniSemibotMimicRange mimicRange = MiniSemibotVisualPrefs.MimicRange; REPOSlider val20 = MenuAPI.CreateREPOSlider("Voice Range - Mimic", "", action, scrollView, RangeOptions, mimicRange switch { MiniSemibotMimicRange.Near => "Near", MiniSemibotMimicRange.Far => "Far", _ => "Medium", }, default(Vector2), "", "", (BarBehavior)0); RectTransform val21 = (RectTransform)((Component)val20).transform; RectTransform result = val21; rangeTr = val21; return result; }, 10f, 0f); RectTransform[] array = (RectTransform[])(object)new RectTransform[3] { chatterTr, volumeTr, rangeTr }; foreach (RectTransform val12 in array) { REPOScrollViewElement val13 = (((Object)(object)val12 != (Object)null) ? ((Component)val12).GetComponent() : null); if ((Object)(object)val13 != (Object)null) { mimicRows.Add(val13); } } UpdateMimicRows(); } AddSectionLabel(popup, "Hands", 10f); REPOPopupPage obj23 = popup; object obj24 = <>c.<>9__17_13; if (obj24 == null) { ScrollViewBuilderDelegate val14 = delegate(Transform scrollView) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotGrabberVisual grabber2 = ((opt == "Orb") ? MiniSemibotGrabberVisual.Orb : ((opt == "Orb + Light") ? MiniSemibotGrabberVisual.OrbLight : MiniSemibotGrabberVisual.CleanArm)); MiniSemibotVisualPrefs.Grabber = grabber2; MiniSemibotSpawner.ApplyLiveSettings(); }; MiniSemibotGrabberVisual grabber = MiniSemibotVisualPrefs.Grabber; REPOSlider val20 = MenuAPI.CreateREPOSlider("Holding", "", action, scrollView, HandsOptions, grabber switch { MiniSemibotGrabberVisual.Orb => "Orb", MiniSemibotGrabberVisual.OrbLight => "Orb + Light", _ => "Clean Arm", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_13 = val14; obj24 = (object)val14; } obj23.AddElementToScrollView((ScrollViewBuilderDelegate)obj24, 10f, 0f); if (MiniSemibotModCompat.HasCustomGrabColor) { REPOPopupPage obj25 = popup; object obj26 = <>c.<>9__17_14; if (obj26 == null) { ScrollViewBuilderDelegate val15 = delegate(Transform scrollView) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Beam Color", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.BeamColor = ((opt == "Mini-Semibot Grabber") ? MiniSemibotBeamColor.MiniGrabber : MiniSemibotBeamColor.SameAsPlayer); MiniSemibotSpawner.ApplyLiveSettings(); }, scrollView, BeamOptions, (MiniSemibotVisualPrefs.BeamColor == MiniSemibotBeamColor.MiniGrabber) ? "Mini-Semibot Grabber" : "Same As You", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_14 = val15; obj26 = (object)val15; } obj25.AddElementToScrollView((ScrollViewBuilderDelegate)obj26, 10f, 0f); } AddSectionLabel(popup, "Behaviour", 10f); REPOPopupPage obj27 = popup; object obj28 = <>c.<>9__17_15; if (obj28 == null) { ScrollViewBuilderDelegate val16 = delegate(Transform scrollView) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Leg Speed", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.LegSpeed = LegSpeedFromOption(opt); Apply(); }, scrollView, LegSpeedOptions, LegSpeedToOption(MiniSemibotVisualPrefs.LegSpeed), default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_15 = val16; obj28 = (object)val16; } obj27.AddElementToScrollView((ScrollViewBuilderDelegate)obj28, 10f, 0f); REPOPopupPage obj29 = popup; object obj30 = <>c.<>9__17_16; if (obj30 == null) { ScrollViewBuilderDelegate val17 = delegate(Transform scrollView) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown Action action = delegate(string opt) { MiniSemibotDeathBehavior deathBehavior2 = ((!(opt == "Death Head")) ? ((!(opt == "Hide")) ? MiniSemibotDeathBehavior.CrouchWait : MiniSemibotDeathBehavior.Hide) : MiniSemibotDeathBehavior.DeathHead); MiniSemibotVisualPrefs.DeathBehavior = deathBehavior2; Apply(); }; MiniSemibotDeathBehavior deathBehavior = MiniSemibotVisualPrefs.DeathBehavior; REPOSlider val20 = MenuAPI.CreateREPOSlider("When You Die", "", action, scrollView, DeathOptions, deathBehavior switch { MiniSemibotDeathBehavior.DeathHead => "Death Head", MiniSemibotDeathBehavior.Hide => "Hide", _ => "Crouch & Wait", }, default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_16 = val17; obj30 = (object)val17; } obj29.AddElementToScrollView((ScrollViewBuilderDelegate)obj30, 10f, 0f); REPOPopupPage obj31 = popup; object obj32 = <>c.<>9__17_17; if (obj32 == null) { ScrollViewBuilderDelegate val18 = delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Hide on Kart", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.HideInArena = opt == "On"; }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.HideInArena ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_17 = val18; obj32 = (object)val18; } obj31.AddElementToScrollView((ScrollViewBuilderDelegate)obj32, 10f, 0f); AddSectionLabel(popup, "Expression Preview", 10f); REPOPopupPage obj33 = popup; object obj34 = <>c.<>9__17_18; if (obj34 == null) { ScrollViewBuilderDelegate val19 = delegate(Transform scrollView) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown REPOSlider val20 = MenuAPI.CreateREPOSlider("Show Mini", "", (Action)delegate(string opt) { MiniSemibotVisualPrefs.ShowInExpressionPreview = opt == "On"; MiniSemibotSpawner.RefreshExpressionPreview(); }, scrollView, OnOffOptions, MiniSemibotVisualPrefs.ShowInExpressionPreview ? "On" : "Off", default(Vector2), "", "", (BarBehavior)0); return (RectTransform)((Component)val20).transform; }; <>c.<>9__17_18 = val19; obj34 = (object)val19; } obj33.AddElementToScrollView((ScrollViewBuilderDelegate)obj34, 10f, 0f); AddSectionLabel(popup, "Actions", 10f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val20 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Recapture Icon", (Action)delegate { MonoBehaviour host = (MonoBehaviour)(object)popup; if ((Object)(object)CosmeticsMenuState.ActivePage != (Object)null) { host = (MonoBehaviour)(object)CosmeticsMenuState.ActivePage; } MiniSemibotIconCapture.ForceRecapture(host); popup.ClosePage(false); }, (Transform)(object)val20, new Vector2(-137f, 0f)); return val20; }, 10f, 0f); popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RectTransform val20 = PopupUI.MakeRow(scrollView); MenuAPI.CreateREPOButton("Back", (Action)delegate { popup.ClosePage(false); }, (Transform)(object)val20, new Vector2(-137f, 0f)); return val20; }, 10f, 0f); popup.OpenPage(false); void UpdateMimicRows() { bool visibility = MiniSemibotVisualPrefs.MouthMode == MiniSemibotMouthMode.MimicClips; foreach (REPOScrollViewElement item in mimicRows) { if ((Object)(object)item != (Object)null) { item.visibility = visibility; } } } } private static void Apply() { MiniSemibotSpawner.ApplyLiveSettings(); } private static float LegSpeedFromOption(string opt) { if (!float.TryParse(opt.TrimEnd('x'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return 1.4f; } return result; } private static string LegSpeedToOption(float v) { string result = LegSpeedOptions[0]; float num = float.MaxValue; string[] legSpeedOptions = LegSpeedOptions; foreach (string text in legSpeedOptions) { float num2 = LegSpeedFromOption(text); float num3 = Mathf.Abs(num2 - v); if (num3 < num) { num = num3; result = text; } } return result; } private static void AddSectionLabel(REPOPopupPage popup, string text, float topPadding) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown REPOLabel val = MenuAPI.CreateREPOLabel(text, scrollView, default(Vector2)); ((TMP_Text)val.labelTMP).fontSize = 18f; ((TMP_Text)val.labelTMP).alpha = 0.85f; ((TMP_Text)val.labelTMP).alignment = (TextAlignmentOptions)513; ((REPOElement)val).rectTransform.sizeDelta = new Vector2(200f, 24f); return (RectTransform)((Component)val).transform; }, topPadding, 0f); } } internal static class MiniSemibotSettings { internal const float BaseScale = 0.33f; internal static MiniSemibotPosition Position => MiniSemibotVisualPrefs.Position; internal static MiniSemibotDeathBehavior DeathBehavior => MiniSemibotVisualPrefs.DeathBehavior; internal static MiniSemibotOutfitMode OutfitMode => MiniSemibotVisualPrefs.OutfitMode; internal static float LegSpeedMultiplier => MiniSemibotVisualPrefs.LegSpeed; internal static MiniSemibotLookAt LookAt => MiniSemibotVisualPrefs.LookAt; internal static MiniSemibotGrabberVisual GrabberVisual => MiniSemibotVisualPrefs.Grabber; internal static MiniSemibotGaze Gaze => MiniSemibotVisualPrefs.Gaze; internal static MiniSemibotMouthMode MouthMode => MiniSemibotVisualPrefs.MouthMode; internal static MiniSemibotBeamColor BeamColor => MiniSemibotVisualPrefs.BeamColor; internal static (float min, float max) MimicChatterDelay => ChatterToDelay(MiniSemibotVisualPrefs.MimicChatter); internal static float MimicVolume => VolumeToValue(MiniSemibotVisualPrefs.MimicVolume); internal static float MimicRange => RangeToValue(MiniSemibotVisualPrefs.MimicRange); internal static float Scale => ScaleForSize(MiniSemibotVisualPrefs.Size); internal static (float min, float max) ChatterToDelay(MiniSemibotMimicChatter c) { return c switch { MiniSemibotMimicChatter.Little => (min: 60f, max: 150f), MiniSemibotMimicChatter.Lots => (min: 12f, max: 35f), _ => (min: 30f, max: 120f), }; } internal static float VolumeToValue(MiniSemibotMimicVolume v) { return v switch { MiniSemibotMimicVolume.Low => 0.4f, MiniSemibotMimicVolume.High => 1f, _ => 0.7f, }; } internal static float RangeToValue(MiniSemibotMimicRange r) { return r switch { MiniSemibotMimicRange.Near => 10f, MiniSemibotMimicRange.Far => 40f, _ => 20f, }; } internal static float ScaleForSize(MiniSemibotSize size) { return size switch { MiniSemibotSize.Baby => 0.22f, MiniSemibotSize.Teen => 0.45f, MiniSemibotSize.Junior => 0.65f, _ => 0.33f, }; } } public enum MiniSemibotSize { Baby, Child, Teen, Junior } public enum MiniSemibotLookAt { Still, Copy, Mouse } public enum MiniSemibotGaze { SameTarget, CopyHead } public enum MiniSemibotMouthMode { Never, Random, WhenITalk, MimicClips } public enum MiniSemibotBeamColor { SameAsPlayer, MiniGrabber } public enum MiniSemibotMimicChatter { Little, Moderate, Lots } public enum MiniSemibotMimicVolume { Low, Medium, High } public enum MiniSemibotMimicRange { Near, Medium, Far } public enum MiniSemibotGrabberVisual { CleanArm, Orb, OrbLight } public enum MiniSemibotPosition { Behind, Front } public enum MiniSemibotDeathBehavior { DeathHead, CrouchWait, Hide } public enum MiniSemibotOutfitMode { SameAsPlayer, RandomPreset } internal static class MiniSemibotSpawner { internal struct LocalMiniState { public int[]? Cosmetics; public int[]? Colors; public string? ColorData; public string? AnimData; public string? CustomData; public string? SlotAnimData; } private static bool _warnedNoPresets; private static readonly Dictionary _active = new Dictionary(); private static int[]? _pendingBroadcastCosmetics; private static int[]? _pendingBroadcastColors; internal static LocalMiniState LocalState; internal static readonly Vector3 OffsetBehind = new Vector3(0.3f, 0.2f, -0.5f); internal static readonly Vector3 OffsetFront = new Vector3(0.3f, 0.2f, 0.9f); internal const float DeathHeadDistance = 0.7f; internal const float DeathHeadLiftBaby = -0.2f; internal const float DeathHeadLiftChild = -0.29f; internal const float DeathHeadLiftTeen = -0.38f; internal const float DeathHeadLiftJunior = -0.55f; internal const float CrouchWaitDistance = 0.65f; internal const float CrouchWaitLiftBaby = 0.13f; internal const float CrouchWaitLiftChild = 0.2f; internal const float CrouchWaitLiftTeen = 0.28f; internal const float CrouchWaitLiftJunior = 0.4f; internal const int CrouchWaitExpression = 2; internal const float ExprPreviewScale = 0.4f; internal const float ExprPreviewYaw = 0f; internal const float ExprPreviewXBaby = 0.45f; internal const float ExprPreviewXChild = 0.45f; internal const float ExprPreviewXTeen = 0.42f; internal const float ExprPreviewXJunior = 0.36f; internal const float ExprPreviewYBaby = 0.82f; internal const float ExprPreviewYChild = 0.77f; internal const float ExprPreviewYTeen = 0.72f; internal const float ExprPreviewYJunior = 0.64f; internal const float ExprPreviewZBaby = -0.2f; internal const float ExprPreviewZChild = -0.2f; internal const float ExprPreviewZTeen = -0.2f; internal const float ExprPreviewZJunior = -0.2f; private static bool _semibotWasEquipped; internal static GameObject? Spawn(PlayerCosmetics wearer, CosmeticAsset asset) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0175: 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_0184: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)wearer == (Object)null || (Object)(object)wearer.playerAvatarVisuals == (Object)null) { return null; } bool flag = IsExpressionAvatar(wearer.playerAvatarVisuals); PlayerAvatar val = (flag ? PlayerAvatar.instance : wearer.playerAvatarVisuals.playerAvatar); PlayerAvatarMenu val2 = FindAvatarPrefab(); if ((Object)(object)val2 == (Object)null) { BceConsole.LogWarning("[MiniSemibot] No PlayerAvatarMenu prefab source found."); return null; } GameObject val3 = new GameObject("MHB_MiniHolder"); val3.SetActive(false); GameObject val4 = Object.Instantiate(((Component)val2).gameObject, val3.transform); ((Object)val4).name = "MHB_MiniSemibot"; PlayerAvatarMenu component = val4.GetComponent(); if ((Object)(object)component != (Object)null) { component.worldAvatar = true; component.iconMakerAvatar = false; component.expressionAvatar = false; } StripRenderRig(val4, component); val4.transform.SetParent((Transform)null, false); Object.Destroy((Object)(object)val3); PlayerAvatarVisuals componentInChildren = val4.GetComponentInChildren(); PlayerCosmetics componentInChildren2 = val4.GetComponentInChildren(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.previewCosmetics = false; componentInChildren2.previewColors = false; } MiniSemibotAnimSync miniSemibotAnimSync = null; if ((Object)(object)componentInChildren != (Object)null) { miniSemibotAnimSync = val4.AddComponent(); miniSemibotAnimSync.SourceVisuals = wearer.playerAvatarVisuals; miniSemibotAnimSync.TargetVisuals = componentInChildren; } MiniSemibotFollow miniSemibotFollow = val4.AddComponent(); miniSemibotFollow.WearerVisuals = wearer.playerAvatarVisuals; miniSemibotFollow.WearerAvatar = val; miniSemibotFollow.AnimSync = miniSemibotAnimSync; miniSemibotFollow.Body = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).gameObject : null); miniSemibotFollow.MiniVisuals = componentInChildren; miniSemibotFollow.Scale = Vector3.one * MiniSemibotSettings.Scale; miniSemibotFollow.ExpressionPreview = flag; MiniSemibotTag miniSemibotTag = val4.AddComponent(); miniSemibotTag.Asset = asset; Animator[] componentsInChildren = val4.GetComponentsInChildren(true); foreach (Animator val5 in componentsInChildren) { if (!((Object)(object)val5 == (Object)null)) { ((Behaviour)val5).enabled = true; val5.cullingMode = (AnimatorCullingMode)0; val5.speed = 1f; } } ApplyGrabberVisual(val4); PlayerAvatarRightArm componentInChildren3 = val4.GetComponentInChildren(); MiniMapHold miniMapHold = val4.AddComponent(); miniMapHold.WearerAvatar = wearer.playerAvatarVisuals.playerAvatar; miniMapHold.MiniArm = componentInChildren3; miniMapHold.Follow = miniSemibotFollow; MiniFlashlightHold miniFlashlightHold = val4.AddComponent(); miniFlashlightHold.WearerAvatar = wearer.playerAvatarVisuals.playerAvatar; miniFlashlightHold.Follow = miniSemibotFollow; MiniStateEffects miniStateEffects = val4.AddComponent(); miniStateEffects.WearerAvatar = wearer.playerAvatarVisuals.playerAvatar; miniStateEffects.Follow = miniSemibotFollow; miniStateEffects.MiniCosmetics = val4.GetComponentInChildren(true); MiniWingsHold miniWingsHold = val4.AddComponent(); miniWingsHold.WearerAvatar = wearer.playerAvatarVisuals.playerAvatar; miniWingsHold.Follow = miniSemibotFollow; MiniGrabBeam miniGrabBeam = val4.AddComponent(); miniGrabBeam.WearerAvatar = wearer.playerAvatarVisuals.playerAvatar; miniGrabBeam.MiniArm = componentInChildren3; miniGrabBeam.Follow = miniSemibotFollow; MiniCrownDriver miniCrownDriver = val4.AddComponent(); miniCrownDriver.WearerAvatar = val; miniCrownDriver.Follow = miniSemibotFollow; PlayerAvatar val6 = val; PlayerAvatarTalkAnimation componentInChildren4 = val4.GetComponentInChildren(true); PlayerExpression componentInChildren5 = val4.GetComponentInChildren(true); if ((Object)(object)componentInChildren5 != (Object)null && (Object)(object)val6 != (Object)null) { componentInChildren5.playerAvatar = val6; componentInChildren5.onlyVisualRepresentation = true; } MiniSemibotFace miniSemibotFace = val4.AddComponent(); miniSemibotFace.WearerAvatar = val6; miniSemibotFace.ExpressionPreview = flag; miniSemibotFace.Expression = componentInChildren5; miniSemibotFace.Follow = miniSemibotFollow; if ((Object)(object)componentInChildren4 != (Object)null && (Object)(object)componentInChildren4.objectToRotate != (Object)null) { miniSemibotFace.MouthObject = componentInChildren4.objectToRotate.transform; miniSemibotFace.MouthMaxAngle = componentInChildren4.rotationMaxAngle; } RollOutfitForTag(wearer, miniSemibotTag); _active[wearer] = val4; RefreshOutfit(wearer); return val4; } internal static void RefreshOutfit(PlayerCosmetics wearer) { if ((Object)(object)wearer == (Object)null) { return; } PruneActive(); if (!_active.TryGetValue(wearer, out GameObject value) || (Object)(object)value == (Object)null) { return; } MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } MiniSemibotTag component = value.GetComponent(); if ((Object)(object)component != (Object)null) { RollOutfitForTag(wearer, component); } bool flag = IsLocalWearer(wearer.playerAvatarVisuals); int num = -1; int[] cosmetics; int[] colors; if (flag && (Object)(object)component != (Object)null && component.PresetCosmetics != null) { cosmetics = FilterIndices(component.PresetCosmetics, instance, excludeWorldOverride: true); colors = component.PresetColors; } else if (flag) { cosmetics = FilterIndices(instance.cosmeticEquipped, instance, excludeWorldOverride: true); colors = instance.colorsEquipped; } else { num = MiniSemibotSync.ActorOf(wearer.playerAvatarVisuals.playerAvatar); if (MiniSemibotSync.TryGetRemoteOutfit(num, out int[] cosmetics2, out int[] colors2)) { cosmetics = FilterIndices(cosmetics2, instance, excludeWorldOverride: false, num); colors = colors2; } else { int[] cosmetics3 = MiniSemibotOutfitCache.GetCosmetics(wearer); if (cosmetics3 == null) { return; } cosmetics = FilterIndices(cosmetics3, instance, excludeWorldOverride: false, num); colors = MiniSemibotOutfitCache.GetColors(wearer); } } if (flag) { if (PerCosmeticColorNetworkSync.BrowseGateOpen) { _pendingBroadcastCosmetics = cosmetics; _pendingBroadcastColors = (int[])colors?.Clone(); } else { LocalState.Cosmetics = cosmetics; LocalState.Colors = (int[])colors?.Clone(); } } string text = Signature(cosmetics, colors); if ((Object)(object)component != (Object)null && component.OutfitSig == text) { return; } PlayerCosmetics pc = value.GetComponentInChildren(true); if (!((Object)(object)pc == (Object)null)) { if ((Object)(object)component != (Object)null && component.PresetSlot >= 0) { PerCosmeticColors.RunWithPresetContext(component.PresetSlot, Dress); } else { Dress(); } if ((Object)(object)component != (Object)null) { component.OutfitSig = text; } value.GetComponent()?.InvalidateDeathHead(); if (flag) { CaptureLocalMiniColorData(((Object)(object)component != (Object)null) ? component.PresetSlot : (-1)); MiniSemibotSync.BroadcastLocal(); } else { MiniSemibotSync.ApplyRemoteMiniColors(num, pc); } } void Dress() { pc.SetupCosmeticsLogic(cosmetics, true); if (colors != null) { pc.SetupColorsLogic(colors); } DisableCosmeticLights(pc); } } internal static void CommitPendingBroadcast() { if (_pendingBroadcastCosmetics != null) { LocalState.Cosmetics = _pendingBroadcastCosmetics; _pendingBroadcastCosmetics = null; } if (_pendingBroadcastColors != null) { LocalState.Colors = _pendingBroadcastColors; _pendingBroadcastColors = null; } } private static void CaptureLocalMiniColorData(int presetSlot) { if (presetSlot >= 0) { ref string colorData = ref LocalState.ColorData; ref string animData = ref LocalState.AnimData; ref string customData = ref LocalState.CustomData; ref string? slotAnimData = ref LocalState.SlotAnimData; (colorData, animData, customData, slotAnimData) = PerCosmeticColors.SerializePresetForBroadcast(presetSlot); } else { LocalState.ColorData = (LocalState.AnimData = (LocalState.CustomData = (LocalState.SlotAnimData = null))); } } internal static bool IsRemoteMiniCosmetics(PlayerCosmetics? pc) { return (Object)(object)RemoteMiniWearerOf(pc) != (Object)null; } internal static (PlayerCosmetics pc, float scale)? ActiveMiniOf(PlayerCosmetics? wearer) { if ((Object)(object)wearer == (Object)null) { return null; } PruneActive(); if (!_active.TryGetValue(wearer, out GameObject value) || (Object)(object)value == (Object)null) { return null; } PlayerCosmetics componentInChildren = value.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return null; } MiniSemibotFollow component = value.GetComponent(); return (componentInChildren, ((Object)(object)component != (Object)null) ? component.Scale.x : 1f); } internal static bool TryRedressMini(PlayerCosmetics? pc) { if ((Object)(object)pc == (Object)null) { return false; } PruneActive(); foreach (KeyValuePair item in _active) { GameObject value = item.Value; if (!((Object)(object)value == (Object)null) && !((Object)(object)value.GetComponentInChildren(true) != (Object)(object)pc)) { MiniSemibotTag component = value.GetComponent(); if ((Object)(object)component != (Object)null) { component.OutfitSig = null; } RefreshOutfit(item.Key); return true; } } return false; } internal static PlayerAvatar? RemoteMiniWearerOf(PlayerCosmetics? pc) { if ((Object)(object)pc == (Object)null) { return null; } MiniSemibotFollow miniSemibotFollow = null; Transform val = ((Component)pc).transform; while ((Object)(object)val != (Object)null && (Object)(object)miniSemibotFollow == (Object)null) { miniSemibotFollow = ((Component)val).GetComponent(); val = val.parent; } PlayerAvatar val2 = (((Object)(object)miniSemibotFollow != (Object)null) ? miniSemibotFollow.WearerAvatar : null); if (!((Object)(object)val2 != (Object)null) || val2.isLocal) { return null; } return val2; } internal static int RemoteMiniActorOf(PlayerCosmetics? pc) { return MiniSemibotSync.ActorOf(RemoteMiniWearerOf(pc)); } internal static void InvalidateLocalDeathHeads() { PruneActive(); foreach (KeyValuePair item in _active) { PlayerAvatar val = ((!((Object)(object)item.Key != (Object)null)) ? null : item.Key.playerAvatarVisuals?.playerAvatar); if ((Object)(object)val != (Object)null && val.isLocal && (Object)(object)item.Value != (Object)null) { item.Value.GetComponent()?.InvalidateDeathHead(); } } } internal static void InvalidateRemoteMiniDeathHeads() { PruneActive(); foreach (KeyValuePair item in _active) { PlayerAvatar val = ((!((Object)(object)item.Key != (Object)null)) ? null : item.Key.playerAvatarVisuals?.playerAvatar); if ((Object)(object)val != (Object)null && !val.isLocal && (Object)(object)item.Value != (Object)null) { item.Value.GetComponent()?.InvalidateDeathHead(); } } } internal static void OnLocalColorsChanged() { PruneActive(); if (_active.Count != 0) { InvalidateLocalDeathHeads(); int presetSlot = ((MiniSemibotSettings.OutfitMode == MiniSemibotOutfitMode.RandomPreset) ? MiniSemibotVisualPrefs.RolledPreset : (-1)); CaptureLocalMiniColorData(presetSlot); MiniSemibotSync.BroadcastLocal(); } } internal static void OnRemoteSyncChanged(int actor) { PruneActive(); foreach (KeyValuePair item in _active) { PlayerCosmetics key = item.Key; GameObject value = item.Value; if (!((Object)(object)key == (Object)null) && !((Object)(object)value == (Object)null) && !((Object)(object)key.playerAvatarVisuals == (Object)null) && MiniSemibotSync.ActorOf(key.playerAvatarVisuals.playerAvatar) == actor) { MiniSemibotTag component = value.GetComponent(); if ((Object)(object)component != (Object)null) { component.OutfitSig = null; } ApplyGrabberVisual(value); RefreshOutfit(key); } } } internal static void RefreshRemoteMiniColors(int actor) { if (actor < 0) { return; } PruneActive(); foreach (KeyValuePair item in _active) { PlayerCosmetics key = item.Key; GameObject value = item.Value; if (!((Object)(object)key == (Object)null) && !((Object)(object)value == (Object)null) && !((Object)(object)key.playerAvatarVisuals == (Object)null) && MiniSemibotSync.ActorOf(key.playerAvatarVisuals.playerAvatar) == actor) { PlayerCosmetics componentInChildren = value.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { MiniSemibotSync.ApplyRemoteMiniColors(actor, componentInChildren); } value.GetComponent()?.InvalidateDeathHead(); } } } internal static void ApplyLiveSettings() { PruneActive(); foreach (KeyValuePair item in _active) { PlayerCosmetics key = item.Key; GameObject value = item.Value; if (!((Object)(object)key == (Object)null) && !((Object)(object)value == (Object)null)) { MiniSemibotTag component = value.GetComponent(); if ((Object)(object)component != (Object)null) { RollOutfitForTag(key, component); component.OutfitSig = null; } ApplyGrabberVisual(value); RefreshOutfit(key); } } MiniSemibotSync.BroadcastLocal(); } internal static void ApplyGrabberVisual(GameObject go) { PlayerAvatar wearer = go.GetComponent()?.WearerAvatar; MiniSemibotGrabberVisual grabber = MiniSemibotSync.Resolve(wearer).Grabber; bool flag = grabber != MiniSemibotGrabberVisual.CleanArm; bool enabled = grabber == MiniSemibotGrabberVisual.OrbLight; PlayerAvatarRightArm[] componentsInChildren = go.GetComponentsInChildren(true); foreach (PlayerAvatarRightArm val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { if ((Object)(object)val.grabberTransform != (Object)null) { ((Component)val.grabberTransform).gameObject.SetActive(flag); } SetRenderersUnder(val.grabberClawParent, flag); SetRenderersUnder(val.grabberOrb, flag); if ((Object)(object)val.grabberLight != (Object)null) { ((Behaviour)val.grabberLight).enabled = enabled; } } } } private static void SetRenderersUnder(Transform? root, bool enabled) { if (!((Object)(object)root == (Object)null)) { Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { val.enabled = enabled; } } } private static bool IsLocalWearer(PlayerAvatarVisuals? v) { if ((Object)(object)v != (Object)null) { if (!IsMenuOrPreviewWearer(v)) { if ((Object)(object)v.playerAvatar != (Object)null) { return v.playerAvatar.isLocal; } return false; } return true; } return false; } internal static bool IsExpressionAvatar(PlayerAvatarVisuals? v) { if ((Object)(object)v == (Object)null) { return false; } PlayerAvatarMenu val = (((Object)(object)v.playerAvatarMenu != (Object)null) ? v.playerAvatarMenu : ((Component)v).GetComponentInParent()); if ((Object)(object)val != (Object)null) { return val.expressionAvatar; } return false; } internal static bool IsMenuOrPreviewWearer(PlayerAvatarVisuals? v) { if ((Object)(object)v == (Object)null) { return false; } if (v.isMenuAvatar) { return true; } return (Object)(object)(((Object)(object)v.playerAvatarMenu != (Object)null) ? v.playerAvatarMenu : ((Component)v).GetComponentInParent()) != (Object)null; } internal static void RefreshExpressionPreview() { PlayerCosmetics val = PlayerExpressionsUI.instance?.playerAvatarVisuals?.playerCosmetics; if ((Object)(object)val == (Object)null) { return; } try { val.SetupCosmetics(false, true, (List)null); val.SetupColors(false, (int[])null); } catch (Exception ex) { BceConsole.LogWarning("Mini-Semibot expression-preview refresh failed: " + ex.Message); } } private static void PruneActive() { if (_active.Count == 0) { return; } List list = null; foreach (KeyValuePair item in _active) { if ((Object)(object)item.Key == (Object)null || (Object)(object)item.Value == (Object)null) { (list ?? (list = new List())).Add(item.Key); } } if (list == null) { return; } foreach (PlayerCosmetics item2 in list) { _active.Remove(item2); } } private static void DisableCosmeticLights(PlayerCosmetics pc) { if (pc.cosmeticEquipped == null) { return; } foreach (Cosmetic item in pc.cosmeticEquipped) { if ((Object)(object)item != (Object)null) { Light[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); foreach (Light val in componentsInChildren) { ((Behaviour)val).enabled = false; } } } } private static void StripRenderRig(GameObject go, PlayerAvatarMenu? menu) { if ((Object)(object)menu != (Object)null && (Object)(object)menu.cameraAndStuff != (Object)null) { ((Component)menu.cameraAndStuff).gameObject.SetActive(false); } Light[] componentsInChildren = go.GetComponentsInChildren(true); foreach (Light val in componentsInChildren) { ((Behaviour)val).enabled = false; } Camera[] componentsInChildren2 = go.GetComponentsInChildren(true); foreach (Camera val2 in componentsInChildren2) { ((Behaviour)val2).enabled = false; } AudioListener[] componentsInChildren3 = go.GetComponentsInChildren(true); foreach (AudioListener val3 in componentsInChildren3) { ((Behaviour)val3).enabled = false; } Collider[] componentsInChildren4 = go.GetComponentsInChildren(true); foreach (Collider val4 in componentsInChildren4) { val4.enabled = false; } } internal static PlayerAvatarMenu? FindAvatarPrefab() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) PlayerAvatarMenu result = null; int num = int.MinValue; PlayerAvatarMenu[] array = Resources.FindObjectsOfTypeAll(); foreach (PlayerAvatarMenu val in array) { if (!((Object)(object)val == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; bool flag = !((Scene)(ref scene)).IsValid(); int num2 = 0; if (flag) { num2 += 100; } if (!val.iconMakerAvatar && !val.expressionAvatar && !val.worldAvatar) { num2 += 50; } else if (val.worldAvatar) { num2 += 20; } else if (val.iconMakerAvatar) { num2 += 10; } else if (val.expressionAvatar) { num2++; } if (num2 > num) { num = num2; result = val; } } } return result; } private static int[] FilterIndices(IList raw, MetaManager meta, bool excludeWorldOverride = false, int remoteActor = -1) { bool flag = remoteActor > 0; List list = new List(raw.Count); foreach (int item in raw) { if (item < 0 || item >= meta.cosmeticAssets.Count) { continue; } CosmeticAsset val = meta.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && !(val.assetId == MiniSemibotCosmetic.AssetId)) { bool flag2; if (flag) { CustomizerSync.TryGetRemote(remoteActor, val.assetId, out BridgeSyncPayload data); flag2 = MoreHeadCosmeticMountPatch.GetRemoteEffectiveType(val, data).isWorld; } else { flag2 = HhhCosmeticLoader.IsWorldAsset(val) || (excludeWorldOverride && CustomizerStore.TryGet(val.assetId, out CosmeticOverrideData data2) && data2.Type == OverrideCosmeticType.World); } if (!flag2) { list.Add(item); } } } return list.ToArray(); } private static string Signature(int[] cosmetics, int[]? colors) { StringBuilder stringBuilder = new StringBuilder(); foreach (int value in cosmetics) { stringBuilder.Append(value).Append(','); } stringBuilder.Append('|'); if (colors != null) { foreach (int value2 in colors) { stringBuilder.Append(value2).Append(','); } } return stringBuilder.ToString(); } internal static float DeathHeadLiftForSize(MiniSemibotSize size) { return size switch { MiniSemibotSize.Baby => -0.2f, MiniSemibotSize.Teen => -0.38f, MiniSemibotSize.Junior => -0.55f, _ => -0.29f, }; } internal static float CrouchWaitLiftForSize(MiniSemibotSize size) { return size switch { MiniSemibotSize.Baby => 0.13f, MiniSemibotSize.Teen => 0.28f, MiniSemibotSize.Junior => 0.4f, _ => 0.2f, }; } internal static float ExprPreviewXForSize(MiniSemibotSize size) { return size switch { MiniSemibotSize.Baby => 0.45f, MiniSemibotSize.Teen => 0.42f, MiniSemibotSize.Junior => 0.36f, _ => 0.45f, }; } internal static float ExprPreviewYForSize(MiniSemibotSize size) { return size switch { MiniSemibotSize.Baby => 0.82f, MiniSemibotSize.Teen => 0.72f, MiniSemibotSize.Junior => 0.64f, _ => 0.77f, }; } internal static float ExprPreviewZForSize(MiniSemibotSize size) { return size switch { MiniSemibotSize.Baby => -0.2f, MiniSemibotSize.Teen => -0.2f, MiniSemibotSize.Junior => -0.2f, _ => -0.2f, }; } internal static void ClearLocalRoll() { MiniSemibotVisualPrefs.RolledPreset = -1; } internal static void UpdateEquipState() { MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null) { return; } bool flag = false; foreach (int item in instance.cosmeticEquipped) { if (item >= 0 && item < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[item]; if ((Object)(object)val != (Object)null && val.assetId == MiniSemibotCosmetic.AssetId) { flag = true; break; } } } if (_semibotWasEquipped && !flag) { MiniSemibotVisualPrefs.RolledPreset = -1; } _semibotWasEquipped = flag; } private static void RollOutfitForTag(PlayerCosmetics wearer, MiniSemibotTag tag) { tag.PresetCosmetics = null; tag.PresetColors = null; tag.PresetSlot = -1; if (!IsLocalWearer(wearer.playerAvatarVisuals) || MiniSemibotSettings.OutfitMode != MiniSemibotOutfitMode.RandomPreset) { return; } MetaManager instance = MetaManager.instance; if (instance?.cosmeticPresets == null) { return; } int rolledPreset = MiniSemibotVisualPrefs.RolledPreset; if (rolledPreset >= 0 && IsPresetNonEmpty(instance, rolledPreset)) { ApplyPresetToTag(instance, rolledPreset, tag); return; } List list = new List(); for (int i = 0; i < instance.cosmeticPresets.Count; i++) { if (IsPresetNonEmpty(instance, i)) { list.Add(i); } } if (list.Count == 0) { if (!_warnedNoPresets) { _warnedNoPresets = true; BceConsole.LogWarning("[MiniSemibot] RandomPreset: no saved presets found in meta.cosmeticPresets — falling back to your live outfit. (Save an outfit in the Presets tab first.)"); } } else { _warnedNoPresets = false; int slot = (MiniSemibotVisualPrefs.RolledPreset = list[Random.Range(0, list.Count)]); ApplyPresetToTag(instance, slot, tag); } } private static bool IsPresetNonEmpty(MetaManager meta, int slot) { if (slot < 0 || slot >= meta.cosmeticPresets.Count) { return false; } bool flag = meta.cosmeticPresets[slot] != null && meta.cosmeticPresets[slot].Count > 0; bool flag2 = meta.colorPresets != null && slot < meta.colorPresets.Count && meta.colorPresets[slot] != null && meta.colorPresets[slot].Count > 0; return flag || flag2; } private static void ApplyPresetToTag(MetaManager meta, int slot, MiniSemibotTag tag) { tag.PresetCosmetics = meta.cosmeticPresets[slot].ToArray(); if (meta.colorPresets != null && slot < meta.colorPresets.Count && meta.colorPresets[slot] != null) { tag.PresetColors = meta.colorPresets[slot].ToArray(); } tag.PresetSlot = slot; } internal static bool IsPresetMini(PlayerCosmetics? pc) { return PresetSlotOf(pc) >= 0; } internal static bool IsPresetMiniComponent(Component? c) { if ((Object)(object)c == (Object)null) { return false; } MiniSemibotTag componentInParent = c.GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent.PresetSlot >= 0; } return false; } internal static int PresetSlotOf(PlayerCosmetics? pc) { if ((Object)(object)pc == (Object)null) { return -1; } MiniSemibotTag componentInParent = ((Component)pc).GetComponentInParent(); if (!((Object)(object)componentInParent != (Object)null)) { return -1; } return componentInParent.PresetSlot; } } internal struct MiniSemibotConfig { public MiniSemibotPosition Position; public float Scale; public MiniSemibotSize Size; public float LegSpeed; public MiniSemibotGrabberVisual Grabber; public MiniSemibotDeathBehavior Death; public MiniSemibotGaze Gaze; public MiniSemibotMouthMode Mouth; public MiniSemibotBeamColor Beam; public bool AvoidWalls; public float MimicMinDelay; public float MimicMaxDelay; public float MimicVol; public float MimicMaxDistance; public static MiniSemibotConfig Local() { var (mimicMinDelay, mimicMaxDelay) = MiniSemibotSettings.MimicChatterDelay; return new MiniSemibotConfig { Position = MiniSemibotSettings.Position, Scale = MiniSemibotSettings.Scale, Size = MiniSemibotVisualPrefs.Size, LegSpeed = MiniSemibotSettings.LegSpeedMultiplier, Grabber = MiniSemibotSettings.GrabberVisual, Death = MiniSemibotSettings.DeathBehavior, Gaze = MiniSemibotSettings.Gaze, Mouth = MiniSemibotSettings.MouthMode, Beam = MiniSemibotSettings.BeamColor, AvoidWalls = MiniSemibotVisualPrefs.AvoidWalls, MimicMinDelay = mimicMinDelay, MimicMaxDelay = mimicMaxDelay, MimicVol = MiniSemibotSettings.MimicVolume, MimicMaxDistance = MiniSemibotSettings.MimicRange }; } } internal sealed class MiniSemibotSyncPayload { [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotPosition Position { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotSize Size { get; set; } public float LegSpeed { get; set; } = 1.4f; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotGrabberVisual Grabber { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotDeathBehavior Death { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotGaze Gaze { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMouthMode Mouth { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotBeamColor Beam { get; set; } public bool AvoidWalls { get; set; } = true; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMimicChatter MimicChatter { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMimicVolume MimicVolume { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMimicRange MimicRange { get; set; } public string[]? Cosmetics { get; set; } public int[]? Colors { get; set; } public string? ColorData { get; set; } public string? AnimData { get; set; } public string? CustomData { get; set; } public string? SlotAnimData { get; set; } internal void ClampValues() { LegSpeed = Mathf.Clamp(LegSpeed, 1f, 3f); Position = DefinedOrDefault(Position); Size = DefinedOrDefault(Size); Grabber = DefinedOrDefault(Grabber); Death = DefinedOrDefault(Death); Gaze = DefinedOrDefault(Gaze); Mouth = DefinedOrDefault(Mouth); Beam = DefinedOrDefault(Beam); MimicChatter = DefinedOrDefault(MimicChatter); MimicVolume = DefinedOrDefault(MimicVolume); MimicRange = DefinedOrDefault(MimicRange); if (Cosmetics != null && Cosmetics.Length > 64) { string[] array = new string[64]; Array.Copy(Cosmetics, array, 64); Cosmetics = array; } if (Colors != null && Colors.Length > 64) { int[] array2 = new int[64]; Array.Copy(Colors, array2, 64); Colors = array2; } } private static T DefinedOrDefault(T value) where T : struct, Enum { if (!Enum.IsDefined(typeof(T), value)) { return default(T); } return value; } public MiniSemibotConfig ToConfig() { var (mimicMinDelay, mimicMaxDelay) = MiniSemibotSettings.ChatterToDelay(MimicChatter); return new MiniSemibotConfig { Position = Position, Scale = MiniSemibotSettings.ScaleForSize(Size), Size = Size, LegSpeed = ((LegSpeed <= 0f) ? 1f : LegSpeed), Grabber = Grabber, Death = Death, Gaze = Gaze, Mouth = Mouth, Beam = Beam, AvoidWalls = AvoidWalls, MimicMinDelay = mimicMinDelay, MimicMaxDelay = mimicMaxDelay, MimicVol = MiniSemibotSettings.VolumeToValue(MimicVolume), MimicMaxDistance = MiniSemibotSettings.RangeToValue(MimicRange) }; } } internal static class MiniSemibotSync { private static readonly Dictionary _remote = new Dictionary(); internal static void PurgeActor(int actorNumber) { _remote.Remove(actorNumber); } internal static void PurgeAll() { _remote.Clear(); } internal static MiniSemibotConfig Resolve(PlayerAvatar? wearer) { if ((Object)(object)wearer == (Object)null || wearer.isLocal || !SemiFunc.IsMultiplayer()) { return MiniSemibotConfig.Local(); } int num = ActorOf(wearer); if (num >= 0 && _remote.TryGetValue(num, out MiniSemibotSyncPayload value) && value != null) { return value.ToConfig(); } return MiniSemibotConfig.Local(); } internal static bool TryGetRemoteOutfit(int actor, out int[] cosmetics, out int[]? colors) { cosmetics = Array.Empty(); colors = null; if (actor < 0 || !_remote.TryGetValue(actor, out MiniSemibotSyncPayload value) || value == null || value.Cosmetics == null) { return false; } cosmetics = AssetIdsToIndices(value.Cosmetics); colors = value.Colors; return true; } internal static int ActorOf(PlayerAvatar? wearer) { if (!((Object)(object)wearer != (Object)null) || !((Object)(object)wearer.photonView != (Object)null) || wearer.photonView.Owner == null) { return -1; } return wearer.photonView.Owner.ActorNumber; } internal static bool RemoteMiniHasOwnColors(int actor) { if (_remote.TryGetValue(actor, out MiniSemibotSyncPayload value) && value != null) { if (string.IsNullOrEmpty(value.ColorData) && string.IsNullOrEmpty(value.CustomData) && string.IsNullOrEmpty(value.AnimData)) { return !string.IsNullOrEmpty(value.SlotAnimData); } return true; } return false; } internal static void ApplyRemoteMiniColors(int actor, PlayerCosmetics miniPc) { if ((Object)(object)miniPc == (Object)null || actor < 0) { return; } PerCosmeticColorSyncComponent component = ((Component)miniPc).GetComponent(); if (!((Object)(object)component == (Object)null)) { bool flag = false; if (RemoteMiniHasOwnColors(actor) && _remote.TryGetValue(actor, out MiniSemibotSyncPayload value) && value != null) { PerCosmeticColorSerializer.DeserializeWithSlots(value.ColorData ?? "", out Dictionary colors, out Dictionary> slotColors); PerCosmeticColorSerializer.DeserializeCustomColors(value.CustomData ?? "", out Dictionary whole, out Dictionary> perSlot); Dictionary remoteAnimations = PerCosmeticColorSerializer.DeserializeAnimations(value.AnimData ?? ""); Dictionary> remoteSlotAnimations = PerCosmeticColorSerializer.DeserializeSlotAnimations(value.SlotAnimData ?? ""); component.SetRemoteColors(colors, slotColors); component.SetRemoteCustomColors(whole, perSlot); component.SetRemoteAnimations(remoteAnimations); component.SetRemoteSlotAnimations(remoteSlotAnimations); flag = true; } else { flag = PerCosmeticColorNetworkSync.PopulateFromCachedActor(actor, component); } if (flag) { component.ApplyToCosmetics(miniPc); component.RefreshAnimators(miniPc); } } } internal static void BroadcastLocal() { BridgeNetMux.BroadcastSnapshot(); } internal static string BuildSection() { MiniSemibotSyncPayload miniSemibotSyncPayload = new MiniSemibotSyncPayload { Position = MiniSemibotSettings.Position, Size = MiniSemibotVisualPrefs.Size, LegSpeed = MiniSemibotSettings.LegSpeedMultiplier, Grabber = MiniSemibotSettings.GrabberVisual, Death = MiniSemibotSettings.DeathBehavior, Gaze = MiniSemibotSettings.Gaze, Mouth = MiniSemibotSettings.MouthMode, Beam = MiniSemibotSettings.BeamColor, AvoidWalls = MiniSemibotVisualPrefs.AvoidWalls, MimicChatter = MiniSemibotVisualPrefs.MimicChatter, MimicVolume = MiniSemibotVisualPrefs.MimicVolume, MimicRange = MiniSemibotVisualPrefs.MimicRange, Cosmetics = IndicesToAssetIds(MiniSemibotSpawner.LocalState.Cosmetics), Colors = MiniSemibotSpawner.LocalState.Colors, ColorData = MiniSemibotSpawner.LocalState.ColorData, AnimData = MiniSemibotSpawner.LocalState.AnimData, CustomData = MiniSemibotSpawner.LocalState.CustomData, SlotAnimData = MiniSemibotSpawner.LocalState.SlotAnimData }; return JsonConvert.SerializeObject((object)miniSemibotSyncPayload); } internal static void OnRemoteSection(int actor, string json) { if (!string.IsNullOrEmpty(json) && json.Length <= 32768) { MiniSemibotSyncPayload miniSemibotSyncPayload = JsonConvert.DeserializeObject(json); if (miniSemibotSyncPayload != null) { miniSemibotSyncPayload.ClampValues(); _remote[actor] = miniSemibotSyncPayload; MiniSemibotSpawner.OnRemoteSyncChanged(actor); } } } private static string[]? IndicesToAssetIds(int[]? indices) { MetaManager instance = MetaManager.instance; if (indices == null || (Object)(object)instance == (Object)null) { return null; } List list = new List(indices.Length); foreach (int num in indices) { if (num >= 0 && num < instance.cosmeticAssets.Count) { CosmeticAsset val = instance.cosmeticAssets[num]; if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(val.assetId)) { list.Add(val.assetId); } } } return list.ToArray(); } private static int[] AssetIdsToIndices(string[] assetIds) { MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return Array.Empty(); } Dictionary dictionary = new Dictionary(instance.cosmeticAssets.Count); for (int i = 0; i < instance.cosmeticAssets.Count; i++) { CosmeticAsset val = instance.cosmeticAssets[i]; if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(val.assetId)) { dictionary[val.assetId] = i; } } List list = new List(assetIds.Length); foreach (string text in assetIds) { if (text != null && dictionary.TryGetValue(text, out var value)) { list.Add(value); } } return list.ToArray(); } } internal sealed class MiniSemibotTag : MonoBehaviour { internal CosmeticAsset? Asset; internal string? OutfitSig; internal int[]? PresetCosmetics; internal int[]? PresetColors; internal int PresetSlot = -1; } internal enum MiniPoseOverride { None, CrouchIdle, TumbleIdle } internal static class MiniSemibotVisualPrefs { private sealed class Data { [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotLookAt LookAt { get; set; } = MiniSemibotLookAt.Mouse; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotGrabberVisual Grabber { get; set; } public int RolledPreset { get; set; } = -1; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotSize Size { get; set; } = MiniSemibotSize.Child; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotGaze Gaze { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMouthMode MouthMode { get; set; } = MiniSemibotMouthMode.WhenITalk; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotBeamColor BeamColor { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMimicChatter MimicChatter { get; set; } = MiniSemibotMimicChatter.Moderate; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMimicVolume MimicVolume { get; set; } = MiniSemibotMimicVolume.Medium; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotMimicRange MimicRange { get; set; } = MiniSemibotMimicRange.Medium; public bool ShowInExpressionPreview { get; set; } = true; public bool HideInArena { get; set; } = true; [JsonConverter(typeof(StringEnumConverter))] public FollowSpringMode FollowSpring { get; set; } public bool IdleGlance { get; set; } = true; public bool StateEffects { get; set; } = true; public bool FootstepSounds { get; set; } public bool MiniFlashlight { get; set; } = true; public bool AvoidWalls { get; set; } = true; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotPosition Position { get; set; } [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotDeathBehavior DeathBehavior { get; set; } = MiniSemibotDeathBehavior.CrouchWait; [JsonConverter(typeof(StringEnumConverter))] public MiniSemibotOutfitMode OutfitMode { get; set; } public float LegSpeed { get; set; } = 1.4f; public bool IconFromAvatar { get; set; } = true; } private static readonly string SavePath = BridgePaths.Of("MiniSemibot.json"); private static Data _data = new Data(); private static bool _loaded; internal static MiniSemibotLookAt LookAt { get { EnsureLoaded(); return _data.LookAt; } set { EnsureLoaded(); _data.LookAt = value; Save(); } } internal static MiniSemibotGrabberVisual Grabber { get { EnsureLoaded(); return _data.Grabber; } set { EnsureLoaded(); _data.Grabber = value; Save(); } } internal static int RolledPreset { get { EnsureLoaded(); return _data.RolledPreset; } set { EnsureLoaded(); if (_data.RolledPreset != value) { _data.RolledPreset = value; Save(); } } } internal static MiniSemibotSize Size { get { EnsureLoaded(); return _data.Size; } set { EnsureLoaded(); if (_data.Size != value) { _data.Size = value; Save(); } } } internal static MiniSemibotGaze Gaze { get { EnsureLoaded(); return _data.Gaze; } set { EnsureLoaded(); if (_data.Gaze != value) { _data.Gaze = value; Save(); } } } internal static MiniSemibotMouthMode MouthMode { get { EnsureLoaded(); return _data.MouthMode; } set { EnsureLoaded(); if (_data.MouthMode != value) { _data.MouthMode = value; Save(); } } } internal static MiniSemibotBeamColor BeamColor { get { EnsureLoaded(); return _data.BeamColor; } set { EnsureLoaded(); if (_data.BeamColor != value) { _data.BeamColor = value; Save(); } } } internal static MiniSemibotMimicChatter MimicChatter { get { EnsureLoaded(); return _data.MimicChatter; } set { EnsureLoaded(); if (_data.MimicChatter != value) { _data.MimicChatter = value; Save(); } } } internal static MiniSemibotMimicVolume MimicVolume { get { EnsureLoaded(); return _data.MimicVolume; } set { EnsureLoaded(); if (_data.MimicVolume != value) { _data.MimicVolume = value; Save(); } } } internal static MiniSemibotMimicRange MimicRange { get { EnsureLoaded(); return _data.MimicRange; } set { EnsureLoaded(); if (_data.MimicRange != value) { _data.MimicRange = value; Save(); } } } internal static bool ShowInExpressionPreview { get { EnsureLoaded(); return _data.ShowInExpressionPreview; } set { EnsureLoaded(); if (_data.ShowInExpressionPreview != value) { _data.ShowInExpressionPreview = value; Save(); } } } internal static bool HideInArena { get { EnsureLoaded(); return _data.HideInArena; } set { EnsureLoaded(); if (_data.HideInArena != value) { _data.HideInArena = value; Save(); } } } internal static FollowSpringMode FollowSpring { get { EnsureLoaded(); return _data.FollowSpring; } set { EnsureLoaded(); if (_data.FollowSpring != value) { _data.FollowSpring = value; Save(); } } } internal static bool IdleGlance { get { EnsureLoaded(); return _data.IdleGlance; } set { EnsureLoaded(); if (_data.IdleGlance != value) { _data.IdleGlance = value; Save(); } } } internal static bool StateEffects { get { EnsureLoaded(); return _data.StateEffects; } set { EnsureLoaded(); if (_data.StateEffects != value) { _data.StateEffects = value; Save(); } } } internal static bool FootstepSounds { get { EnsureLoaded(); return _data.FootstepSounds; } set { EnsureLoaded(); if (_data.FootstepSounds != value) { _data.FootstepSounds = value; Save(); } } } internal static bool MiniFlashlight { get { EnsureLoaded(); return _data.MiniFlashlight; } set { EnsureLoaded(); if (_data.MiniFlashlight != value) { _data.MiniFlashlight = value; Save(); } } } internal static bool AvoidWalls { get { EnsureLoaded(); return _data.AvoidWalls; } set { EnsureLoaded(); if (_data.AvoidWalls != value) { _data.AvoidWalls = value; Save(); } } } internal static MiniSemibotPosition Position { get { EnsureLoaded(); return _data.Position; } set { EnsureLoaded(); if (_data.Position != value) { _data.Position = value; Save(); } } } internal static MiniSemibotDeathBehavior DeathBehavior { get { EnsureLoaded(); return _data.DeathBehavior; } set { EnsureLoaded(); if (_data.DeathBehavior != value) { _data.DeathBehavior = value; Save(); } } } internal static MiniSemibotOutfitMode OutfitMode { get { EnsureLoaded(); return _data.OutfitMode; } set { EnsureLoaded(); if (_data.OutfitMode != value) { _data.OutfitMode = value; Save(); } } } internal static float LegSpeed { get { EnsureLoaded(); return _data.LegSpeed; } set { EnsureLoaded(); if (_data.LegSpeed != value) { _data.LegSpeed = value; Save(); } } } internal static bool IconFromAvatar { get { EnsureLoaded(); return _data.IconFromAvatar; } set { EnsureLoaded(); if (_data.IconFromAvatar != value) { _data.IconFromAvatar = value; Save(); } } } private static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; try { if (File.Exists(SavePath)) { _data = JsonConvert.DeserializeObject(File.ReadAllText(SavePath)) ?? new Data(); } } catch (Exception ex) { BceConsole.LogWarning("Mini-Semibot prefs load failed: " + ex.Message); _data = new Data(); } } private static void Save() { try { AtomicJson.Write(SavePath, JsonConvert.SerializeObject((object)_data, (Formatting)1)); } catch (Exception ex) { BceConsole.LogWarning("Mini-Semibot prefs save failed: " + ex.Message); } } } internal sealed class MiniStateEffects : MonoBehaviour { private static readonly int OverlayColorId = Shader.PropertyToID("_ColorOverlay"); private static readonly int OverlayAmountId = Shader.PropertyToID("_ColorOverlayAmount"); private static readonly FieldInfo? PupilMultField = AccessTools.Field(typeof(PlayerEyes), "pupilSizeMultiplier"); internal PlayerAvatar? WearerAvatar; internal MiniSemibotFollow? Follow; internal PlayerCosmetics? MiniCosmetics; private float _appliedAmount = -1f; private Color _appliedColor; private Material? _wearerEyeMat; private Material? _wearerPupilMat; private Material? _miniEyeMat; private Material? _miniPupilMat; private bool _eyeMatsResolved; private float _appliedEyeAmount = -1f; private float _appliedPupilAmount = -1f; private Color _appliedEyeColor; private Color _appliedPupilColor; private float _appliedPupilMult = 1f; private void LateUpdate() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MiniCosmetics == (Object)null) { return; } bool flag = (Object)(object)WearerAvatar != (Object)null && (WearerAvatar.deadSet || WearerAvatar.isDisabled); bool flag2 = (Object)(object)Follow != (Object)null && Follow.ExpressionPreview; if (!MiniSemibotVisualPrefs.StateEffects || flag || flag2 || ((Object)(object)Follow != (Object)null && Follow.BodyHidden)) { if (_appliedAmount > 0f) { ApplyBody(0f, _appliedColor); } ClearEyes(); } else { MirrorBody(); MirrorEyesAndPupil(); } } private void MirrorBody() { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) PlayerCosmetics val = (((Object)(object)WearerAvatar != (Object)null) ? WearerAvatar.playerCosmetics : null); Material val2 = null; if ((Object)(object)val != (Object)null) { foreach (PlayerMaterial playerMaterial in val.playerMaterials) { if ((Object)(object)playerMaterial != (Object)null && (Object)(object)playerMaterial.material != (Object)null) { val2 = playerMaterial.material; break; } } } if (!((Object)(object)val2 == (Object)null) && val2.HasProperty(OverlayAmountId)) { float num = val2.GetFloat(OverlayAmountId); Color color = val2.GetColor(OverlayColorId); if (!Mathf.Approximately(num, _appliedAmount) || !(color == _appliedColor)) { ApplyBody(num, color); } } } private void ApplyBody(float amount, Color color) { //IL_0008: 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_005d: Unknown result type (might be due to invalid IL or missing references) _appliedAmount = amount; _appliedColor = color; foreach (PlayerMaterial playerMaterial in MiniCosmetics.playerMaterials) { if (!((Object)(object)playerMaterial == (Object)null) && !((Object)(object)playerMaterial.material == (Object)null) && playerMaterial.material.HasProperty(OverlayAmountId)) { playerMaterial.material.SetColor(OverlayColorId, color); playerMaterial.material.SetFloat(OverlayAmountId, amount); } } } private void MirrorEyesAndPupil() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) ResolveEyeMats(); if ((Object)(object)_wearerEyeMat != (Object)null && (Object)(object)_miniEyeMat != (Object)null) { float num = _wearerEyeMat.GetFloat(OverlayAmountId); Color color = _wearerEyeMat.GetColor(OverlayColorId); if (!Mathf.Approximately(num, _appliedEyeAmount) || color != _appliedEyeColor) { _appliedEyeAmount = num; _appliedEyeColor = color; _miniEyeMat.SetFloat(OverlayAmountId, num); _miniEyeMat.SetColor(OverlayColorId, color); } } if ((Object)(object)_wearerPupilMat != (Object)null && (Object)(object)_miniPupilMat != (Object)null) { float num2 = _wearerPupilMat.GetFloat(OverlayAmountId); Color color2 = _wearerPupilMat.GetColor(OverlayColorId); if (!Mathf.Approximately(num2, _appliedPupilAmount) || color2 != _appliedPupilColor) { _appliedPupilAmount = num2; _appliedPupilColor = color2; _miniPupilMat.SetFloat(OverlayAmountId, num2); _miniPupilMat.SetColor(OverlayColorId, color2); } } if (!(PupilMultField != null)) { return; } PlayerEyes val = (((Object)(object)WearerAvatar != (Object)null && (Object)(object)WearerAvatar.playerAvatarVisuals != (Object)null) ? WearerAvatar.playerAvatarVisuals.playerEyes : null); PlayerEyes val2 = (((Object)(object)Follow != (Object)null && (Object)(object)Follow.MiniVisuals != (Object)null) ? Follow.MiniVisuals.playerEyes : null); if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { float num3 = (float)(PupilMultField.GetValue(val) ?? ((object)1f)); if (!Mathf.Approximately(num3, _appliedPupilMult)) { _appliedPupilMult = num3; PupilMultField.SetValue(val2, num3); } } } private void ClearEyes() { if ((Object)(object)_miniEyeMat != (Object)null && _appliedEyeAmount > 0f) { _appliedEyeAmount = 0f; _miniEyeMat.SetFloat(OverlayAmountId, 0f); } if ((Object)(object)_miniPupilMat != (Object)null && _appliedPupilAmount > 0f) { _appliedPupilAmount = 0f; _miniPupilMat.SetFloat(OverlayAmountId, 0f); } if (PupilMultField != null && !Mathf.Approximately(_appliedPupilMult, 1f)) { PlayerEyes val = (((Object)(object)Follow != (Object)null && (Object)(object)Follow.MiniVisuals != (Object)null) ? Follow.MiniVisuals.playerEyes : null); if ((Object)(object)val != (Object)null) { PupilMultField.SetValue(val, 1f); _appliedPupilMult = 1f; } } } private void ResolveEyeMats() { if (!_eyeMatsResolved || !((Object)(object)_wearerEyeMat != (Object)null) || !((Object)(object)_wearerPupilMat != (Object)null) || !((Object)(object)_miniEyeMat != (Object)null) || !((Object)(object)_miniPupilMat != (Object)null)) { PlayerAvatarVisuals val = (((Object)(object)WearerAvatar != (Object)null) ? WearerAvatar.playerAvatarVisuals : null); PlayerAvatarVisuals val2 = (((Object)(object)Follow != (Object)null) ? Follow.MiniVisuals : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null)) { _wearerEyeMat = FindMat(val, "Player Avatar - Eye"); _wearerPupilMat = FindMat(val, "Player Avatar - Pupil"); _miniEyeMat = FindMat(val2, "Player Avatar - Eye"); _miniPupilMat = FindMat(val2, "Player Avatar - Pupil"); _eyeMatsResolved = (Object)(object)_wearerEyeMat != (Object)null && (Object)(object)_wearerPupilMat != (Object)null && (Object)(object)_miniEyeMat != (Object)null && (Object)(object)_miniPupilMat != (Object)null; } } } private static Material? FindMat(PlayerAvatarVisuals v, string baseName) { Renderer[] componentsInChildren = ((Component)v).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material sharedMaterial = val.sharedMaterial; if (!((Object)(object)sharedMaterial == (Object)null)) { string text = ((Object)sharedMaterial).name.Replace(" (Instance)", ""); if (text == baseName) { return val.material; } } } return null; } } internal sealed class MiniWingsHold : MonoBehaviour { private static readonly FieldInfo? VisualsActiveField = AccessTools.Field(typeof(PlayerAvatar), "upgradeTumbleWingsVisualsActive"); private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor"); private static readonly int FresnelColorId = Shader.PropertyToID("_FresnelColor"); internal PlayerAvatar? WearerAvatar; internal MiniSemibotFollow? Follow; private GameObject? _clone; private bool _buildFailed; private Transform? _srcWings; private Transform? _srcWingL; private Transform? _srcWingR; private Transform? _cloneWingL; private Transform? _cloneWingR; private MeshRenderer? _srcMeshL; private MeshRenderer? _srcMeshR; private MeshRenderer? _cloneMeshL; private MeshRenderer? _cloneMeshR; private void LateUpdate() { //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) ItemUpgradePlayerTumbleWingsLogic val = (((Object)(object)WearerAvatar != (Object)null) ? WearerAvatar.upgradeTumbleWingsLogic : null); PlayerAvatarVisuals val2 = (((Object)(object)Follow != (Object)null) ? Follow.WearerVisuals : null); PlayerAvatarVisuals val3 = (((Object)(object)Follow != (Object)null) ? Follow.MiniVisuals : null); int num; if ((Object)(object)WearerAvatar != (Object)null && VisualsActiveField != null) { object value = VisualsActiveField.GetValue(WearerAvatar); num = ((value is bool && (bool)value) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; if (!(MiniSemibotVisualPrefs.StateEffects && ((Object)(object)Follow == (Object)null || !MiniSemibotSpawner.IsMenuOrPreviewWearer(Follow.WearerVisuals)) && ((Object)(object)Follow == (Object)null || !Follow.BodyHidden) && (Object)(object)val != (Object)null && (Object)(object)val.transformWings != (Object)null && flag) || !((Object)(object)val2 != (Object)null) || !((Object)(object)val3 != (Object)null)) { if ((Object)(object)_clone != (Object)null && _clone.activeSelf) { _clone.SetActive(false); } return; } if ((Object)(object)_clone == (Object)null && !_buildFailed) { BuildClone(val); } if (!((Object)(object)_clone == (Object)null)) { if (!_clone.activeSelf) { _clone.SetActive(true); } float scale = MiniSemibotSync.Resolve(WearerAvatar).Scale; Transform transform = _clone.transform; transform.position = ((Component)val3).transform.TransformPoint(((Component)val2).transform.InverseTransformPoint(_srcWings.position)); transform.rotation = ((Component)val3).transform.rotation * (Quaternion.Inverse(((Component)val2).transform.rotation) * _srcWings.rotation); transform.localScale = _srcWings.lossyScale * scale; if ((Object)(object)_cloneWingL != (Object)null && (Object)(object)_srcWingL != (Object)null) { _cloneWingL.localRotation = _srcWingL.localRotation; } if ((Object)(object)_cloneWingR != (Object)null && (Object)(object)_srcWingR != (Object)null) { _cloneWingR.localRotation = _srcWingR.localRotation; } CopyWingColor(_srcMeshL, _cloneMeshL); CopyWingColor(_srcMeshR, _cloneMeshR); } } private static void CopyWingColor(MeshRenderer? src, MeshRenderer? dst) { //IL_003a: 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) if (!((Object)(object)src == (Object)null) && !((Object)(object)dst == (Object)null)) { Material material = ((Renderer)src).material; Material material2 = ((Renderer)dst).material; if (material.HasProperty(BaseColorId)) { material2.SetColor(BaseColorId, material.GetColor(BaseColorId)); } if (material.HasProperty(FresnelColorId)) { material2.SetColor(FresnelColorId, material.GetColor(FresnelColorId)); } } } private void BuildClone(ItemUpgradePlayerTumbleWingsLogic logic) { try { _srcWings = logic.transformWings; _srcWingL = logic.transformWingLeft; _srcWingR = logic.transformWingRight; _srcMeshL = (((Object)(object)_srcWingL != (Object)null) ? ((Component)_srcWingL).GetComponentInChildren(true) : null); _srcMeshR = (((Object)(object)_srcWingR != (Object)null) ? ((Component)_srcWingR).GetComponentInChildren(true) : null); GameObject val = Object.Instantiate(((Component)_srcWings).gameObject); ((Object)val).name = "MHB_MiniWings"; MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren(true); foreach (MonoBehaviour val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null) { ((Behaviour)val2).enabled = false; } } AudioSource[] componentsInChildren2 = val.GetComponentsInChildren(true); foreach (AudioSource val3 in componentsInChildren2) { ((Behaviour)val3).enabled = false; } Light[] componentsInChildren3 = val.GetComponentsInChildren(true); foreach (Light val4 in componentsInChildren3) { ((Behaviour)val4).enabled = false; } int num = LayerMask.NameToLayer("Triggers"); if (num >= 0) { Transform[] componentsInChildren4 = val.GetComponentsInChildren(true); foreach (Transform val5 in componentsInChildren4) { ((Component)val5).gameObject.layer = num; } } _cloneWingL = (((Object)(object)_srcWingL != (Object)null) ? FindByName(val.transform, ((Object)_srcWingL).name) : null); _cloneWingR = (((Object)(object)_srcWingR != (Object)null) ? FindByName(val.transform, ((Object)_srcWingR).name) : null); _cloneMeshL = (((Object)(object)_cloneWingL != (Object)null) ? ((Component)_cloneWingL).GetComponentInChildren(true) : null); _cloneMeshR = (((Object)(object)_cloneWingR != (Object)null) ? ((Component)_cloneWingR).GetComponentInChildren(true) : null); _clone = val; } catch (Exception ex) { _buildFailed = true; BceConsole.LogWarning("Mini-Semibot wings clone failed: " + ex.Message); _clone = null; } } private static Transform? FindByName(Transform root, string name) { if (((Object)root).name == name) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindByName(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private void OnDestroy() { if ((Object)(object)_clone != (Object)null) { Object.Destroy((Object)(object)_clone); } } } internal static class MiniFootstepEmitter { internal static void Emit(PlayerAvatarVisuals visuals, SoundType soundType) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)visuals == (Object)null) && MiniSemibotVisualPrefs.FootstepSounds && !((Object)(object)Materials.Instance == (Object)null) && !((Object)(object)RecordingDirector.instance != (Object)null)) { MiniSemibotFollow componentInParent = ((Component)visuals).GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null) && componentInParent.MiniVisuals == visuals && !componentInParent.BodyHidden && !MiniSemibotSpawner.IsMenuOrPreviewWearer(componentInParent.WearerVisuals) && !((Object)(object)componentInParent.WearerAvatar == (Object)null)) { Materials.Instance.Impulse(((Component)visuals).transform.position, Vector3.down, (SoundType)0, true, false, componentInParent.WearerAvatar.MaterialTrigger, (HostType)1); } } } } [HarmonyPatch(typeof(PlayerAvatarVisuals), "FootstepLight")] internal static class MiniFootstepLightPatch { [HarmonyPostfix] private static void Postfix(PlayerAvatarVisuals __instance) { MiniFootstepEmitter.Emit(__instance, (SoundType)0); } } [HarmonyPatch(typeof(PlayerAvatarVisuals), "FootstepMedium")] internal static class MiniFootstepMediumPatch { [HarmonyPostfix] private static void Postfix(PlayerAvatarVisuals __instance) { MiniFootstepEmitter.Emit(__instance, (SoundType)1); } } [HarmonyPatch(typeof(PlayerAvatarVisuals), "FootstepHeavy")] internal static class MiniFootstepHeavyPatch { [HarmonyPostfix] private static void Postfix(PlayerAvatarVisuals __instance) { MiniFootstepEmitter.Emit(__instance, (SoundType)2); } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsLogic")] internal static class MiniSemibotColorsRefreshPatch { [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance, int[] _colors) { MiniSemibotOutfitCache.RecordColors(__instance, _colors); MiniSemibotSpawner.RefreshOutfit(__instance); } } [HarmonyPatch(typeof(MenuElementCosmeticButton), "ToggleCosmetic")] [HarmonyPriority(600)] internal static class WorldCosmeticsClearButtonPatch { private sealed class PatchState { public List? Backup; public bool UnequipAllWasActive; } private static readonly MethodInfo? _triggerClickAnimations = typeof(MenuElementCosmeticButton).GetMethod("TriggerClickAnimations", BindingFlags.Instance | BindingFlags.NonPublic); internal static bool IsUnequipAllRunning { get; private set; } [HarmonyPrefix] private static bool Prefix(MenuElementCosmeticButton __instance, ref PatchState __state) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 //IL_0068: Unknown result type (might be due to invalid IL or missing references) __state = new PatchState(); IsUnequipAllRunning = false; if (HhhCosmeticLoader.WorldAssetIds.Count == 0) { return true; } if ((Object)(object)__instance.cosmeticAsset != (Object)null) { return true; } if ((Object)(object)MetaManager.instance == (Object)null) { return true; } MenuElementCosmeticSection cosmeticSection = __instance.cosmeticSection; if ((Object)(object)cosmeticSection == (Object)null) { return true; } if ((int)cosmeticSection.subCategory == 2147483646) { PlayClickFeedback(__instance); UnequipWorldsOnly(__instance); return false; } if ((int)cosmeticSection.subCategory != 0) { return true; } if (WorldCosmeticsMenuState.IsWorldCategory(CosmeticsMenuState.ActivePage?.selectedCategory) || ((Object)((Component)cosmeticSection).gameObject).name == "MHB_WorldSection") { PlayClickFeedback(__instance); UnequipWorldsOnly(__instance); return false; } WorldCosmeticsMenuState.PartitionHatCosmetics(MetaManager.instance, out List _, out List worlds); if (worlds.Count > 0) { __state.Backup = worlds; IsUnequipAllRunning = true; __state.UnequipAllWasActive = true; } return true; } [HarmonyPostfix] private static void Postfix(PatchState __state) { IsUnequipAllRunning = false; if (__state == null) { return; } List backup = __state.Backup; bool unequipAllWasActive = __state.UnequipAllWasActive; if ((Object)(object)MetaManager.instance == (Object)null) { return; } bool flag = false; if (backup != null) { foreach (int item in backup) { if (!MetaManager.instance.cosmeticEquipped.Contains(item)) { MetaManager.instance.cosmeticEquipped.Add(item); flag = true; } } } if (flag) { MetaManager.instance.Save(); } if (flag || unequipAllWasActive) { MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); } } [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception) { IsUnequipAllRunning = false; return __exception; } private static void PlayClickFeedback(MenuElementCosmeticButton btn) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) btn.soundClick.Play(MenuManager.instance.soundPosition, 1f, 1f, 1f, 1f); _triggerClickAnimations?.Invoke(btn, null); } private static void UnequipWorldsOnly(MenuElementCosmeticButton btn) { WorldCosmeticsMenuState.PartitionHatCosmetics(MetaManager.instance, out List _, out List worlds); bool flag = false; foreach (int item in worlds) { MetaManager.instance.cosmeticEquipped.Remove(item); flag = true; } if (flag) { MetaManager.instance.Save(); MetaManager.instance.CosmeticPlayerUpdateLocal(false, false); } MenuElementCosmeticSection cosmeticSection = btn.cosmeticSection; if (cosmeticSection != null) { cosmeticSection.UpdateColorButton((CosmeticAsset)null, false); } } } [HarmonyPatch(typeof(MenuElementButtonCosmeticCategory), "UpdateHighlight")] internal static class WorldCosmeticsHighlightPatch { [HarmonyPostfix] private static void Postfix(MenuElementButtonCosmeticCategory __instance) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Invalid comparison between Unknown and I4 //IL_01c5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)MetaManager.instance == (Object)null || HhhCosmeticLoader.WorldAssetIds.Count == 0) { return; } if (CosmeticsMenuState.IsVirtual(__instance.category)) { if ((Object)(object)__instance.highlightObj?.text != (Object)null) { ((TMP_Text)__instance.highlightObj.text).text = "0"; } return; } int count; if ((int)__instance.buttonType == 0) { if ((Object)(object)__instance.category == (Object)null || (Object)(object)__instance.highlightObj == (Object)null) { return; } bool isWorldCategory = WorldCosmeticsMenuState.IsWorldCategory(__instance.category); bool flag = __instance.category.typeList != null && __instance.category.typeList.Contains((CosmeticType)0); if (!isWorldCategory && !flag) { return; } count = CountNewCosmetics((CosmeticAsset asset) => (!isWorldCategory) ? (MatchesCategory(asset, __instance.category) && !HhhCosmeticLoader.IsWorldAsset(asset)) : HhhCosmeticLoader.IsWorldAsset(asset)); } else { if ((int)__instance.buttonType != 1 || (Object)(object)__instance.highlightObj == (Object)null) { return; } if (CosmeticsMenuState.IsVirtual(((Component)__instance).GetComponentInParent()?.selectedCategory)) { if ((Object)(object)__instance.highlightObj.text != (Object)null) { ((TMP_Text)__instance.highlightObj.text).text = "0"; } return; } if ((int)__instance.subCategory != 0) { return; } count = CountNewCosmetics((CosmeticAsset asset) => asset.type == __instance.subCategory && !HhhCosmeticLoader.IsWorldAsset(asset)); } SetHighlightCount(__instance.highlightObj, count); } private static bool MatchesCategory(CosmeticAsset asset, CosmeticCategoryAsset category) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (category.typeList != null) { return category.typeList.Contains(asset.type); } return false; } private static int CountNewCosmetics(Func predicate) { MetaManager instance = MetaManager.instance; HashSet hashSet = new HashSet(instance.cosmeticHistory); int num = 0; foreach (int cosmeticUnlock in instance.cosmeticUnlocks) { if (cosmeticUnlock >= 0 && cosmeticUnlock < instance.cosmeticAssets.Count && !hashSet.Contains(cosmeticUnlock)) { CosmeticAsset val = instance.cosmeticAssets[cosmeticUnlock]; if ((Object)(object)val != (Object)null && predicate(val)) { num++; } } } return num; } private static void SetHighlightCount(MenuElementCosmeticHighlight highlight, int count) { if ((Object)(object)highlight.text != (Object)null) { ((TMP_Text)highlight.text).text = count.ToString(); } } } [HarmonyPatch(typeof(MenuElementCosmeticSection), "UpdateHighlight")] internal static class WorldCosmeticsSectionHighlightPatch { [HarmonyPostfix] private static void Postfix(MenuElementCosmeticSection __instance) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)MetaManager.instance == (Object)null || HhhCosmeticLoader.WorldAssetIds.Count == 0 || (int)__instance.subCategory != 0 || (Object)(object)__instance.highlightObj == (Object)null) { return; } if (CosmeticsMenuState.IsVirtual(__instance.menuPageCosmetics?.selectedCategory)) { if ((Object)(object)__instance.highlightObj.text != (Object)null) { ((TMP_Text)__instance.highlightObj.text).text = "0"; } if ((Object)(object)__instance.menuPageCosmetics != (Object)null && __instance.menuPageCosmetics.selectedSubCategory == __instance.subCategory && (Object)(object)__instance.menuPageCosmetics.stickyHeader?.highlightObj?.text != (Object)null) { ((TMP_Text)__instance.menuPageCosmetics.stickyHeader.highlightObj.text).text = "0"; } return; } bool flag = WorldCosmeticsMenuState.IsWorldCategory(__instance.menuPageCosmetics?.selectedCategory); HashSet hashSet = new HashSet(MetaManager.instance.cosmeticHistory); HashSet hashSet2 = new HashSet(MetaManager.instance.cosmeticUnlocks); int num = 0; for (int i = 0; i < MetaManager.instance.cosmeticAssets.Count; i++) { if (hashSet.Contains(i) || !hashSet2.Contains(i)) { continue; } CosmeticAsset val = MetaManager.instance.cosmeticAssets[i]; if (!((Object)(object)val == (Object)null) && (int)val.type == 0 && ((PrefabRef)(object)val.prefab).IsValid()) { bool flag2 = HhhCosmeticLoader.IsWorldAsset(val); if (flag ? flag2 : (!flag2)) { num++; } } } if ((Object)(object)__instance.highlightObj.text != (Object)null) { ((TMP_Text)__instance.highlightObj.text).text = num.ToString(); } if ((Object)(object)__instance.menuPageCosmetics != (Object)null && __instance.menuPageCosmetics.selectedSubCategory == __instance.subCategory && (Object)(object)__instance.menuPageCosmetics.stickyHeader?.highlightObj?.text != (Object)null) { ((TMP_Text)__instance.menuPageCosmetics.stickyHeader.highlightObj.text).text = num.ToString(); } } } [HarmonyPatch(typeof(MenuElementCosmeticButton), "IsEquipped")] internal static class WorldCosmeticsIsEquippedPatch { [HarmonyPostfix] private static void Postfix(MenuElementCosmeticButton __instance, ref bool __result) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.cosmeticAsset != (Object)null || (Object)(object)MetaManager.instance == (Object)null || HhhCosmeticLoader.WorldAssetIds.Count == 0) { return; } MenuElementCosmeticSection cosmeticSection = __instance.cosmeticSection; if ((Object)(object)cosmeticSection == (Object)null) { return; } if ((int)cosmeticSection.subCategory == 2147483646 || ((Object)((Component)cosmeticSection).gameObject).name == "MHB_WorldSection" || ((int)cosmeticSection.subCategory == 0 && WorldCosmeticsMenuState.IsWorldCategory(WorldCosmeticsMenuState.CurrentPage?.selectedCategory))) { __result = !MetaManager.instance.cosmeticEquipped.Any((int idx) => idx >= 0 && idx < MetaManager.instance.cosmeticAssets.Count && HhhCosmeticLoader.IsWorldAsset(MetaManager.instance.cosmeticAssets[idx])); } else if ((int)cosmeticSection.subCategory == 0) { __result = !MetaManager.instance.cosmeticEquipped.Any((int idx) => idx >= 0 && idx < MetaManager.instance.cosmeticAssets.Count && (int)MetaManager.instance.cosmeticAssets[idx].type == 0 && !HhhCosmeticLoader.IsWorldAsset(MetaManager.instance.cosmeticAssets[idx])); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "RefreshScrollContent")] internal static class WorldCosmeticsMenuFilterPatch { private const float SectionSpacing = 10f; private const float SectionHeader = 40f; [HarmonyPostfix] private static void Postfix(MenuPageCosmetics __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || HhhCosmeticLoader.WorldAssetIds.Count == 0 || (int)__instance.selectedTab != 0 || CosmeticsMenuState.IsPresetsCategory(__instance.selectedCategory) || CosmeticsMenuState.IsVirtual(__instance.selectedCategory) || WorldCosmeticsMenuState.IsWorldCategory(__instance.selectedCategory)) { return; } bool flag = false; BridgeFavoritesManager.EnsureLoaded(); float yPos = 0f; foreach (MenuElementCosmeticSection section in __instance.sections) { MenuElementCosmeticButton[] componentsInChildren = ((Component)section.cosmeticListTransform).GetComponentsInChildren(true); MenuElementCosmeticButton[] array = componentsInChildren.Where((MenuElementCosmeticButton b) => (Object)(object)b != (Object)null && (Object)(object)b.cosmeticAsset != (Object)null).ToArray(); int num = 0; MenuElementCosmeticButton[] array2 = array; foreach (MenuElementCosmeticButton val in array2) { bool flag2 = !HhhCosmeticLoader.IsWorldAsset(val.cosmeticAsset); if (flag2 && BridgeFavoritesManager.IsHidden(val.cosmeticAsset)) { flag2 = false; } if (((Component)val).gameObject.activeSelf != flag2) { ((Component)val).gameObject.SetActive(flag2); flag = true; } if (flag2) { num++; } } if (num == 0) { if (((Component)section).gameObject.activeSelf) { ((Component)section).gameObject.SetActive(false); flag = true; } } else { if (!((Component)section).gameObject.activeSelf) { ((Component)section).gameObject.SetActive(true); } ReflowSection(section, num, ref yPos); } } ShowAllSubCategoryButtons(__instance); if (flag) { RebuildScroll(__instance); } } private static void ReflowSection(MenuElementCosmeticSection section, int remaining, ref float yPos) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) GridLayoutGroup component = ((Component)section.cosmeticListTransform).GetComponent(); if (!((Object)(object)component == (Object)null)) { int num = Mathf.Max(1, component.constraintCount); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)(remaining + 1) / (float)num)); float num3 = component.cellSize.y * (float)num2 + component.spacing.y * (float)(num2 - 1) + (float)((LayoutGroup)component).padding.top + (float)((LayoutGroup)component).padding.bottom; float num4 = 40f + num3; RectTransform component2 = ((Component)section).GetComponent(); ((Transform)component2).localPosition = new Vector3(((Transform)component2).localPosition.x, yPos, ((Transform)component2).localPosition.z); component2.sizeDelta = new Vector2(component2.sizeDelta.x, num4); RectTransform component3 = ((Component)section.cosmeticListTransform).GetComponent(); component3.sizeDelta = new Vector2(component3.sizeDelta.x, num3); LayoutRebuilder.ForceRebuildLayoutImmediate(component3); LayoutRebuilder.ForceRebuildLayoutImmediate(component2); yPos -= num4 + 10f; } } private static void ShowAllSubCategoryButtons(MenuPageCosmetics page) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 foreach (Transform item in page.subCategoriesTransform) { Transform val = item; MenuElementButtonCosmeticCategory component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && (int)component.buttonType == 1) { ((Component)val).gameObject.SetActive(true); } } } private static void RebuildScroll(MenuPageCosmetics page) { ScrollRect componentInChildren = ((Component)page).GetComponentInChildren(true); if ((Object)(object)((componentInChildren != null) ? componentInChildren.content : null) != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(componentInChildren.content); } } } [HarmonyPatch(typeof(MenuPageCosmetics), "Start")] internal static class WorldCosmeticsMenuStartPatch { [HarmonyPostfix] private static void Postfix(MenuPageCosmetics __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || HhhCosmeticLoader.WorldAssetIds.Count == 0 || (int)__instance.selectedTab != 0 || BridgePatcher.MenuTakeoverBroken) { return; } WorldCosmeticsMenuState.CurrentPage = __instance; try { WorldCosmeticsMenuState.EnsureCategory(); InjectWorldCategoryButton(__instance); } catch (Exception ex) { BceConsole.LogWarning("WORLD menu injection failed: " + ex.Message); } } private static void InjectWorldCategoryButton(MenuPageCosmetics page) { if ((Object)(object)WorldCosmeticsMenuState.Category == (Object)null) { return; } MenuElementButtonCosmeticCategory val = ((IEnumerable)((Component)page.categoriesTransform).GetComponentsInChildren(true)).FirstOrDefault((Func)((MenuElementButtonCosmeticCategory b) => (Object)(object)b.category == (Object)(object)WorldCosmeticsMenuState.Category || HasLabel(b, "WORLD"))); if ((Object)(object)val != (Object)null) { val.category = WorldCosmeticsMenuState.Category; return; } GameObject val2 = Object.Instantiate(page.categoryButtonPrefab, page.categoriesTransform); MenuElementButtonCosmeticCategory component = val2.GetComponent(); component.category = WorldCosmeticsMenuState.Category; TextMeshProUGUI componentInChildren = val2.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).fontSize = 20f; ((TMP_Text)componentInChildren).text = "WORLD"; } MoveAfter(page, val2.transform, "LEGS"); page.categoriesHolder.UpdateButtons(); } private static bool HasLabel(MenuElementButtonCosmeticCategory btn, string label) { TextMeshProUGUI componentInChildren = ((Component)btn).GetComponentInChildren(); string text = btn.category?.categoryName ?? ((componentInChildren != null) ? ((TMP_Text)componentInChildren).text : null) ?? ""; return string.Equals(text.Trim(), label, StringComparison.OrdinalIgnoreCase); } private static void MoveAfter(MenuPageCosmetics page, Transform item, string label) { List source = ((Component)page.categoriesTransform).GetComponentsInChildren(true).ToList(); MenuElementButtonCosmeticCategory val = ((IEnumerable)source).FirstOrDefault((Func)((MenuElementButtonCosmeticCategory b) => HasLabel(b, label))); if ((Object)(object)val != (Object)null) { item.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1); } } } [HarmonyPatch(typeof(PlayerCosmetics), "SetupCosmeticsLogic")] internal static class WorldCosmeticsSetupPatch { private sealed class PatchState { public List? PendingWorldAssets; public List? PreviewIndicesRemoved; } private static readonly Dictionary> _worldInstances = new Dictionary>(); [HarmonyPriority(100)] [HarmonyPrefix] private static bool Prefix(PlayerCosmetics __instance, ref int[] _cosmeticEquipped, bool _forced, ref PatchState __state) { __state = new PatchState(); PruneDestroyedInstances(); MiniSemibotOutfitCache.RecordCosmetics(__instance, _cosmeticEquipped); if ((Object)(object)MetaManager.instance == (Object)null) { return true; } MiniSemibotSpawner.UpdateEquipState(); if (WorldCosmeticsClearButtonPatch.IsUnequipAllRunning) { return false; } if (IsNonSpawnMenuAvatar(__instance)) { int num = MiniSemibotSpawner.RemoteMiniActorOf(__instance); bool flag = num > 0; List list = new List(_cosmeticEquipped.Length); int[] array = _cosmeticEquipped; foreach (int num2 in array) { if (num2 >= 0 && num2 < MetaManager.instance.cosmeticAssets.Count) { CosmeticAsset val = MetaManager.instance.cosmeticAssets[num2]; if ((Object)(object)val == (Object)null) { list.Add(num2); continue; } if (MoreHeadCosmeticMountPatch.IsWorldFor(val, flag ? num : 0)) { continue; } } list.Add(num2); } _cosmeticEquipped = list.ToArray(); DestroyAllTracked(__instance); return true; } bool cosmeticPreviewEnabled = MetaManager.instance.cosmeticPreviewEnabled; bool flag2 = IsExpressionAvatar(__instance); int actorNumber; bool flag3 = AvatarIdentity.TryGetRemoteActor(__instance, out actorNumber); List list2 = null; List list3 = new List(_cosmeticEquipped.Length); int[] array2 = _cosmeticEquipped; foreach (int num3 in array2) { if (num3 < 0 || num3 >= MetaManager.instance.cosmeticAssets.Count) { list3.Add(num3); continue; } CosmeticAsset val2 = MetaManager.instance.cosmeticAssets[num3]; if ((Object)(object)val2 == (Object)null) { list3.Add(num3); } else if (MoreHeadCosmeticMountPatch.IsWorldFor(val2, flag3 ? actorNumber : 0)) { if (!cosmeticPreviewEnabled && (!flag2 || val2.assetId == MiniSemibotCosmetic.AssetId)) { if (list2 == null) { list2 = new List(); } list2.Add(val2); } } else { list3.Add(num3); } } _cosmeticEquipped = list3.ToArray(); if (list2 != null) { __state.PendingWorldAssets = list2; } if (cosmeticPreviewEnabled) { List cosmeticEquippedPreview = MetaManager.instance.cosmeticEquippedPreview; List list4 = null; for (int num4 = cosmeticEquippedPreview.Count - 1; num4 >= 0; num4--) { int num5 = cosmeticEquippedPreview[num4]; if (num5 >= 0 && num5 < MetaManager.instance.cosmeticAssets.Count) { CosmeticAsset val3 = MetaManager.instance.cosmeticAssets[num5]; if (HhhCosmeticLoader.IsWorldAsset(val3)) { if (list4 == null) { list4 = new List(); } list4.Add(num5); cosmeticEquippedPreview.RemoveAt(num4); if (!flag2 || !(val3.assetId != MiniSemibotCosmetic.AssetId)) { PatchState patchState = __state; if (patchState.PendingWorldAssets == null) { patchState.PendingWorldAssets = new List(); } if (!__state.PendingWorldAssets.Contains(val3)) { __state.PendingWorldAssets.Add(val3); } } } } } __state.PreviewIndicesRemoved = list4; } if (_forced) { DestroyAllTracked(__instance); } else { SelectiveDestroyTracked(__instance, __state.PendingWorldAssets); } return true; } [HarmonyPostfix] private static void Postfix(PlayerCosmetics __instance, PatchState __state) { if (__state == null) { return; } RestorePreviewIndices(__state); SpawnPendingWorldCosmetics(__instance, __state); try { MoreHeadCosmeticMountPatch.ReconcileMeshSwitchBaseMeshes(__instance); } catch (Exception ex) { BceConsole.LogWarning("Mesh-switch reconcile failed: " + ex.Message); } try { MiniSemibotSpawner.RefreshOutfit(__instance); } catch (Exception ex2) { BceConsole.LogWarning("Mini-Semibot RefreshOutfit failed: " + ex2.Message); } } [HarmonyFinalizer] private static Exception? Finalizer(PlayerCosmetics __instance, Exception? __exception, PatchState __state) { if (__state == null) { return __exception; } RestorePreviewIndices(__state); if (__exception != null) { SpawnPendingWorldCosmetics(__instance, __state); } return __exception; } private static void RestorePreviewIndices(PatchState state) { List previewIndicesRemoved = state.PreviewIndicesRemoved; state.PreviewIndicesRemoved = null; if (previewIndicesRemoved == null || (Object)(object)MetaManager.instance == (Object)null) { return; } List cosmeticEquippedPreview = MetaManager.instance.cosmeticEquippedPreview; foreach (int item in previewIndicesRemoved) { if (!cosmeticEquippedPreview.Contains(item)) { cosmeticEquippedPreview.Add(item); } } } private static void SpawnPendingWorldCosmetics(PlayerCosmetics instance, PatchState state) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected I4, but got Unknown List pendingWorldAssets = state.PendingWorldAssets; state.PendingWorldAssets = null; if (pendingWorldAssets == null || pendingWorldAssets.Count == 0 || (Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarVisuals == (Object)null) { return; } Transform transform = ((Component)instance.playerAvatarVisuals).transform; if (!_worldInstances.TryGetValue(instance, out List value)) { value = new List(); _worldInstances[instance] = value; } foreach (CosmeticAsset item in pendingWorldAssets) { if ((Object)(object)item != (Object)null && item.assetId == MiniSemibotCosmetic.AssetId) { try { GameObject val = MiniSemibotSpawner.Spawn(instance, item); if ((Object)(object)val != (Object)null) { value.Add(val); } } catch (Exception ex) { BceConsole.LogWarning("Mini-Semibot spawn failed: " + ex.Message); } } else { if ((Object)(object)item == (Object)null) { continue; } GameObject val2 = ((PrefabRef)(object)item.prefab)?.Prefab; if ((Object)(object)val2 == (Object)null) { continue; } try { GameObject val3 = Object.Instantiate(val2); Cosmetic val4 = val3.GetComponent() ?? val3.AddComponent(); val4.cosmeticAsset = item; val4.type = item.type; val4.rarity = item.rarity; val4.playerCosmetics = instance; val4.cosmeticParent = null; int num = (int)item.type; if ((Object)(object)MetaManager.instance != (Object)null && num >= 0 && num < MetaManager.instance.cosmeticTypeAssets.Count) { val4.cosmeticTypeAsset = MetaManager.instance.cosmeticTypeAssets[num]; } val4.Setup(); MoreHeadCosmeticMountPatch.MountWorldCosmetic(val3, transform, val2, item.assetId); int actorNumber; bool flag = AvatarIdentity.TryGetRemoteActor(instance, out actorNumber); BridgeSyncPayload data = null; if (flag) { CustomizerSync.TryGetRemote(actorNumber, item.assetId, out data); } CosmeticPrefabFixer.FixInstance(val3, item.assetId, (!flag) ? ((bool?)null) : data?.FixAnimation, flag); bool? flag2 = (flag ? new bool?(data?.Tintable ?? CustomizerStore.GetRemoteFallbackTintable(item)) : ((bool?)null)); if (flag2 != false) { BridgeTintHelper.InjectBridgeTintMaterials(val3, item, flag2); } if ((Object)(object)instance.playerAvatarVisuals != (Object)null) { PartShrinkerBridge.OnSpawn(val3, instance.playerAvatarVisuals); } ApplyOverridesToWorldCosmetic(val3, item, instance, flag, data); value.Add(val3); } catch (Exception ex2) { BceConsole.LogWarning("WorldCosmeticsSetupPatch: failed to spawn '" + item?.assetId + "': " + ex2.Message); } } } } private static void ApplyOverridesToWorldCosmetic(GameObject go, CosmeticAsset asset, PlayerCosmetics instance, bool isRemote, BridgeSyncPayload? remoteData) { List offsets; List customTypes; if (OverridePreviewContext.IsActiveFor(instance, asset.assetId)) { CosmeticOverrideData data = OverridePreviewContext.Data; if (data != null) { offsets = data.Offsets; customTypes = data.CustomTypes; } else { CustomizerStore.TryGet(asset.assetId, out CosmeticOverrideData data2); offsets = data2?.Offsets; customTypes = data2?.CustomTypes; } } else if (isRemote) { offsets = remoteData?.Offsets; customTypes = remoteData?.CustomTypes; } else { CustomizerStore.TryGet(asset.assetId, out CosmeticOverrideData data3); offsets = data3?.Offsets; customTypes = data3?.CustomTypes; } MoreHeadCosmeticMountPatch.InjectOffsetConditions(go, asset, instance, offsets, customTypes); if (CosmeticSwayHelper.IsSwayEnabled(instance, asset.assetId) && go.GetComponentsInChildren(true).Length == 0) { Cosmetic component = go.GetComponent(); if ((Object)(object)component != (Object)null) { BridgeSwaySpring bridgeSwaySpring = go.AddComponent(); bridgeSwaySpring.Init(component, CosmeticSwayHelper.GetIntensityFactor(instance, asset.assetId)); } } } internal static void SetAllWorldInstancesActive(bool active) { foreach (List value in _worldInstances.Values) { foreach (GameObject item in value) { if ((Object)(object)item != (Object)null) { item.SetActive(active); } } } } internal static void SetWorldAssetActive(CosmeticAsset asset, bool active) { foreach (List value in _worldInstances.Values) { foreach (GameObject item in value) { if (!((Object)(object)item == (Object)null)) { Cosmetic component = item.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.cosmeticAsset == (Object)(object)asset) { item.SetActive(active); } } } } } private static void DestroyAllTracked(PlayerCosmetics instance) { if (!_worldInstances.TryGetValue(instance, out List value)) { return; } PlayerAvatarVisuals playerAvatarVisuals = instance.playerAvatarVisuals; foreach (GameObject item in value) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)playerAvatarVisuals != (Object)null) { PartShrinkerBridge.OnRemove(item, playerAvatarVisuals); } Object.Destroy((Object)(object)item); } } value.Clear(); } private static void PruneDestroyedInstances() { List list = null; foreach (PlayerCosmetics key in _worldInstances.Keys) { if ((Object)(object)key == (Object)null) { if (list == null) { list = new List(); } list.Add(key); } } if (list == null) { return; } foreach (PlayerCosmetics item in list) { _worldInstances.Remove(item); } } private static bool IsNonSpawnMenuAvatar(PlayerCosmetics instance) { if ((Object)(object)((Component)instance).GetComponentInParent() != (Object)null) { return true; } PlayerAvatarVisuals playerAvatarVisuals = instance.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null || !playerAvatarVisuals.isMenuAvatar) { return false; } PlayerAvatarMenu val = (((Object)(object)playerAvatarVisuals.playerAvatarMenu != (Object)null) ? playerAvatarVisuals.playerAvatarMenu : ((Component)playerAvatarVisuals).GetComponentInParent()); if ((Object)(object)val == (Object)null) { return false; } if (val.expressionAvatar && MiniSemibotVisualPrefs.ShowInExpressionPreview) { return false; } if (!val.expressionAvatar) { return val.iconMakerAvatar; } return true; } private static bool IsExpressionAvatar(PlayerCosmetics instance) { PlayerAvatarVisuals playerAvatarVisuals = instance.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null || !playerAvatarVisuals.isMenuAvatar) { return false; } PlayerAvatarMenu val = (((Object)(object)playerAvatarVisuals.playerAvatarMenu != (Object)null) ? playerAvatarVisuals.playerAvatarMenu : ((Component)playerAvatarVisuals).GetComponentInParent()); if ((Object)(object)val != (Object)null) { return val.expressionAvatar; } return false; } private static void SelectiveDestroyTracked(PlayerCosmetics instance, List? pending) { if (!_worldInstances.TryGetValue(instance, out List value)) { return; } HashSet hashSet = ((pending != null) ? new HashSet(pending) : null); PlayerAvatarVisuals playerAvatarVisuals = instance.playerAvatarVisuals; for (int num = value.Count - 1; num >= 0; num--) { GameObject val = value[num]; if ((Object)(object)val == (Object)null) { value.RemoveAt(num); } else { CosmeticAsset val2 = val.GetComponent()?.cosmeticAsset ?? val.GetComponent()?.Asset; if ((Object)(object)val2 != (Object)null && hashSet != null && hashSet.Remove(val2)) { pending.Remove(val2); } else { if ((Object)(object)playerAvatarVisuals != (Object)null) { PartShrinkerBridge.OnRemove(val, playerAvatarVisuals); } Object.Destroy((Object)(object)val); value.RemoveAt(num); } } } } } [HarmonyPatch(typeof(MetaManager), "CosmeticPreviewSet")] internal static class WorldCosmeticsUnequipHoverPatch { [HarmonyPrefix] private static void Prefix(bool _state) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Invalid comparison between Unknown and I4 //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Invalid comparison between Unknown and I4 if (!_state || HhhCosmeticLoader.WorldAssetIds.Count == 0) { return; } MetaManager instance = MetaManager.instance; if ((Object)(object)instance == (Object)null) { return; } WorldCosmeticsMenuState.PartitionHatCosmetics(instance, out List realHats, out List worlds); if (realHats.Count == 0 && worlds.Count == 0) { return; } List cosmeticEquippedPreview = instance.cosmeticEquippedPreview; MenuElementCosmeticButton val = WorldCosmeticsMenuState.CurrentPage?.pendingHoveredCosmeticButton; MenuElementCosmeticSection val2 = val?.cosmeticSection; if ((Object)(object)val?.cosmeticAsset == (Object)null && (Object)(object)val2 != (Object)null && ((int)val2.subCategory == 2147483646 || ((Object)((Component)val2).gameObject).name == "MHB_WorldSection")) { foreach (int item in worlds) { cosmeticEquippedPreview.Remove(item); } { foreach (int item2 in realHats) { if (!cosmeticEquippedPreview.Contains(item2)) { cosmeticEquippedPreview.Add(item2); } } return; } } bool flag = false; foreach (int item3 in cosmeticEquippedPreview) { if (item3 >= 0 && item3 < instance.cosmeticAssets.Count) { CosmeticAsset val3 = instance.cosmeticAssets[item3]; if (val3 != null && (int)val3.type == 0) { flag = true; break; } } } if (flag) { return; } bool flag2 = WorldCosmeticsMenuState.IsWorldCategory(WorldCosmeticsMenuState.CurrentPage?.selectedCategory); bool flag3 = false; if (!flag2 && (Object)(object)val2 != (Object)null) { flag3 = (int)val2.subCategory == 2147483646 || ((Object)((Component)val2).gameObject).name == "MHB_WorldSection"; } List list = ((flag2 || flag3) ? realHats : worlds); foreach (int item4 in list) { if (!cosmeticEquippedPreview.Contains(item4)) { cosmeticEquippedPreview.Add(item4); } } } } [HarmonyPatch(typeof(MetaManager), "CosmeticUnequip")] internal static class WorldCosmeticsUnequipPatch { [HarmonyPrefix] private static void Prefix(MetaManager __instance, CosmeticAsset _cosmeticAsset, ref List? __state) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_007b: Unknown result type (might be due to invalid IL or missing references) __state = null; if (HhhCosmeticLoader.WorldAssetIds.Count == 0 || _cosmeticAsset == null || (int)_cosmeticAsset.type > 0) { return; } bool flag = HhhCosmeticLoader.IsWorldAsset(_cosmeticAsset); List list = new List(); foreach (int item in __instance.cosmeticEquipped) { if (item < 0 || item >= __instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = __instance.cosmeticAssets[item]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)_cosmeticAsset) && (int)val.type == 0) { bool flag2 = HhhCosmeticLoader.IsWorldAsset(val); bool flag3 = flag2 != flag; bool flag4 = Plugin.AllowMultipleCosmetics.Value && flag2 == flag; if (flag3 || flag4) { list.Add(item); } } } if (list.Count > 0) { __state = list; } } [HarmonyPostfix] private static void Postfix(MetaManager __instance, List? __state) { if (__state == null) { return; } foreach (int item in __state) { if (!__instance.cosmeticEquipped.Contains(item)) { __instance.cosmeticEquipped.Add(item); } } } } [HarmonyPatch(typeof(Cosmetic), "Setup")] internal static class WorldEquipAnimationScalePatch { private static readonly FieldInfo? MeshParentsScaleField = AccessTools.Field(typeof(Cosmetic), "meshParentsScale"); [HarmonyPostfix] private static void Postfix(Cosmetic __instance) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.cosmeticAsset == (Object)null || !BridgeIds.IsCustomizable(__instance.cosmeticAsset)) { return; } string assetId = __instance.cosmeticAsset.assetId; VanillaEquipAnimationMode vanillaEquipAnimationMode = ((!OverridePreviewContext.IsActiveFor(__instance.playerCosmetics, assetId) || OverridePreviewContext.Data == null || !OverridePreviewContext.Data.VanillaEquipAnimationMode.HasValue) ? CustomizerStore.GetEffectiveEquipAnimationMode(assetId) : OverridePreviewContext.Data.VanillaEquipAnimationMode.Value); if (vanillaEquipAnimationMode == VanillaEquipAnimationMode.Normal || !(MeshParentsScaleField?.GetValue(__instance) is List list)) { return; } List meshParents = __instance.meshParents; for (int i = 0; i < meshParents.Count && i < list.Count; i++) { if (!((Object)(object)meshParents[i] == (Object)null)) { if (vanillaEquipAnimationMode == VanillaEquipAnimationMode.Disabled) { __instance.iconCreationAvatar = true; meshParents[i].localScale = list[i]; } else { meshParents[i].localScale = list[i] * 0.05f; } } } } } internal sealed class WorldCosmeticsFollower : MonoBehaviour { private Transform? _avatar; private string _assetId = ""; private FollowSpring _spring; private Vector3 _easedPos; private Quaternion _easedRot; private bool _seeded; private GameObject? _cosmetic; private PlayerAvatarVisuals? _wearer; private bool _localWearer; private Renderer[]? _renderers; private bool _visApplied; private bool _visState; private bool _boundsCached; private Vector3 _boundsLocal; private float _probeRadius; private bool _groundSitter; private const float GroundSitMax = 0.3f; private const float WallProbeLiftMin = 0.3f; private const float GroundProbeRadius = 0.15f; private const float StepProbeUp = 0.75f; private const float StepSnapRange = 0.6f; private const int LedgePullSteps = 3; internal void Configure(Transform avatar, string? assetId, PlayerAvatarVisuals? wearer = null, GameObject? cosmetic = null) { _avatar = avatar; _assetId = assetId ?? ""; _cosmetic = cosmetic; _wearer = wearer; int localWearer; if ((Object)(object)wearer != (Object)null && !MiniSemibotSpawner.IsMenuOrPreviewWearer(wearer)) { if (SemiFunc.IsMultiplayer()) { PlayerAvatar playerAvatar = wearer.playerAvatar; if (playerAvatar == null) { localWearer = 0; } else { PhotonView photonView = playerAvatar.photonView; localWearer = ((((photonView != null) ? new bool?(photonView.IsMine) : ((bool?)null)) == true) ? 1 : 0); } } else { localWearer = 1; } } else { localWearer = 0; } _localWearer = (byte)localWearer != 0; } private void LateUpdate() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_avatar == (Object)null) { _avatar = ((Component)this).transform.parent; } if (!((Object)(object)_avatar == (Object)null)) { Vector3 val = _avatar.position; Quaternion val2 = Quaternion.Euler(0f, _avatar.eulerAngles.y, 0f); if (_boundsCached && AvoidWallsActive() && !MiniSemibotSpawner.IsMenuOrPreviewWearer(_wearer)) { val = ClampToLevel(val, val2); } if (!_seeded) { _easedPos = val; _easedRot = val2; _seeded = true; } FollowSpringMode mode = (Plugin.EnableWorldFollowSpring.Value ? WorldFollowPrefs.GetSpring(_assetId) : FollowSpringMode.Off); _easedPos = _spring.StepPosition(_easedPos, val, Time.deltaTime, mode); _easedRot = FollowSpring.StepRotation(_easedRot, val2, Time.deltaTime, mode); Transform transform = ((Component)this).transform; transform.position = _easedPos; transform.rotation = _easedRot; transform.localScale = Vector3.one; ApplyVisibility(); if (!_boundsCached) { CacheVisualBounds(); } } } private bool AvoidWallsActive() { PlayerAvatar val = (((Object)(object)_wearer != (Object)null) ? _wearer.playerAvatar : null); if ((Object)(object)val != (Object)null && !val.isLocal && SemiFunc.IsMultiplayer()) { if (CustomizerSync.TryGetRemote(MiniSemibotSync.ActorOf(val), _assetId, out BridgeSyncPayload data) && data != null) { return data.AvoidWalls == true; } return false; } return WorldFollowPrefs.GetAvoidWalls(_assetId); } private void CacheVisualBounds() { //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_0062: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) _boundsCached = true; if ((Object)(object)_cosmetic == (Object)null) { return; } Renderer[] componentsInChildren = _cosmetic.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return; } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } } Transform transform = ((Component)this).transform; _boundsLocal = Quaternion.Inverse(transform.rotation) * (((Bounds)(ref bounds)).center - transform.position); _probeRadius = Mathf.Clamp(Mathf.Max(((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.z), 0.05f, 0.3f); _groundSitter = ((Bounds)(ref bounds)).min.y - transform.position.y < 0.3f; } private Vector3 ClampToLevel(Vector3 targetPos, Quaternion targetRot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) Vector3 val = targetPos; Vector3 val2 = targetPos + targetRot * _boundsLocal; float num = Mathf.Max(val2.y, val.y + 0.3f); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(val.x, num, val.z); Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(val2.x, num, val2.z); Vector3 val5 = val4 - val3; float magnitude = ((Vector3)(ref val5)).magnitude; RaycastHit val6 = default(RaycastHit); if (magnitude > 0.05f && Physics.SphereCast(val3, _probeRadius, val5 / magnitude, ref val6, magnitude, LayerMask.op_Implicit(MiniSemibotFollow.PlacementMask), (QueryTriggerInteraction)1)) { Vector3 val7 = ((RaycastHit)(ref val6)).point + ((RaycastHit)(ref val6)).normal * _probeRadius; targetPos += new Vector3(val7.x - val2.x, 0f, val7.z - val2.z); } if (!_groundSitter) { return targetPos; } RaycastHit val9 = default(RaycastHit); for (int i = 0; i <= 3; i++) { Vector3 val8 = targetPos + targetRot * _boundsLocal; if (Physics.SphereCast(new Vector3(val8.x, val.y + 0.75f, val8.z), 0.15f, Vector3.down, ref val9, 1.35f, LayerMask.op_Implicit(MiniSemibotFollow.PlacementMask), (QueryTriggerInteraction)1) && Mathf.Abs(((RaycastHit)(ref val9)).point.y - val.y) <= 0.6f) { return new Vector3(targetPos.x, ((RaycastHit)(ref val9)).point.y, targetPos.z); } targetPos += new Vector3((val.x - val8.x) * 0.5f, 0f, (val.z - val8.z) * 0.5f); } return new Vector3(targetPos.x, val.y, targetPos.z); } private void ApplyVisibility() { if ((Object)(object)_cosmetic == (Object)null) { return; } bool flag = _localWearer && !WorldFollowPrefs.GetShowToSelf(_assetId); if (!flag && !MiniSemibotSpawner.IsMenuOrPreviewWearer(_wearer) && HideOnKartActive() && WearerOnKart()) { flag = true; } if (_visApplied && flag == _visState) { return; } if (_renderers == null) { _renderers = _cosmetic.GetComponentsInChildren(true); } Renderer[] renderers = _renderers; foreach (Renderer val in renderers) { if ((Object)(object)val != (Object)null) { val.forceRenderingOff = flag; } } _visApplied = true; _visState = flag; } private bool WearerOnKart() { PlayerAvatar val = (((Object)(object)_wearer != (Object)null) ? _wearer.playerAvatar : null); if (!MiniSemibotFollow.RunIsKartArena()) { if ((Object)(object)val != (Object)null) { return (Object)(object)ItemVehicle.GetVehicleForPlayer(val) != (Object)null; } return false; } return true; } private bool HideOnKartActive() { PlayerAvatar val = (((Object)(object)_wearer != (Object)null) ? _wearer.playerAvatar : null); if ((Object)(object)val != (Object)null && !val.isLocal && SemiFunc.IsMultiplayer()) { if (CustomizerSync.TryGetRemote(MiniSemibotSync.ActorOf(val), _assetId, out BridgeSyncPayload data) && data != null) { return data.HideOnKart == true; } return false; } return WorldFollowPrefs.GetHideOnKart(_assetId); } } internal sealed class WorldFollowerCleanup : MonoBehaviour { internal GameObject? Node; private void OnDestroy() { if ((Object)(object)Node != (Object)null) { Object.Destroy((Object)(object)Node); } } } internal static class WorldCosmeticsMenuState { internal static CosmeticCategoryAsset? Category { get; private set; } internal static MenuPageCosmetics? CurrentPage { get; set; } internal static bool IsWorldCategory(CosmeticCategoryAsset? category) { if ((Object)(object)category != (Object)null) { if (!((Object)(object)category == (Object)(object)Category)) { return ((Object)category).name == "MHB_World"; } return true; } return false; } internal static void EnsureCategory() { if (!((Object)(object)Category != (Object)null)) { Category = ScriptableObject.CreateInstance(); ((Object)Category).name = "MHB_World"; Category.categoryName = "WORLD"; Category.typeList = new List(1) { (CosmeticType)0 }; } } internal static void PartitionHatCosmetics(MetaManager meta, out List realHats, out List worlds) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 realHats = new List(); worlds = new List(); foreach (int item in meta.cosmeticEquipped) { if (item < 0 || item >= meta.cosmeticAssets.Count) { continue; } CosmeticAsset val = meta.cosmeticAssets[item]; if (val != null && (int)val.type <= 0) { if (HhhCosmeticLoader.IsWorldAsset(val)) { worlds.Add(item); } else { realHats.Add(item); } } } } } internal static class WorldCosmeticsRandomize { [HarmonyPatch(typeof(MenuPageCosmetics), "RandomizeAllButton")] internal static class RandomizeAllPostfix { [HarmonyPostfix] private static void Postfix() { SyncBridgeColorsAfterRandomize(); ApplyIndependentRolls(); } } [HarmonyPatch(typeof(MenuPageCosmetics), "RandomizeBodyButton")] internal static class RandomizeBodyPostfix { [HarmonyPostfix] private static void Postfix() { SyncBridgeColorsAfterRandomize(); } } [HarmonyPatch(typeof(MenuPageCosmetics), "RandomizeCosmeticsButton")] internal static class RandomizeCosmeticsPostfix { [HarmonyPostfix] private static void Postfix() { SyncBridgeColorsAfterRandomize(); ApplyIndependentRolls(); } } private static void SyncBridgeColorsAfterRandomize() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected I4, but got Unknown MetaManager instance = MetaManager.instance; if (instance?.cosmeticEquipped == null || instance.colorsEquipped == null) { return; } bool flag = false; foreach (int item in instance.cosmeticEquipped) { if (item < 0 || item >= instance.cosmeticAssets.Count) { continue; } CosmeticAsset val = instance.cosmeticAssets[item]; if (!BridgeTintHelper.CanBridgeCosmeticReceivePaint(val)) { continue; } int num = (int)val.type; if (num >= 0 && num < instance.colorsEquipped.Length) { int num2 = instance.colorsEquipped[num]; if (num2 >= 0) { PerCosmeticColors.SetNoSave(val.assetId, num2); flag = true; } } } if (flag) { PerCosmeticColors.Save(); instance.CosmeticPlayerUpdateLocal(false, false); } } private static void ApplyIndependentRolls() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) MetaManager meta = MetaManager.instance; if ((Object)(object)meta == (Object)null || HhhCosmeticLoader.WorldAssetIds.Count <= 0) { return; } List list = new List(); List list2 = new List(); foreach (int cosmeticUnlock in meta.cosmeticUnlocks) { if (cosmeticUnlock < 0 || cosmeticUnlock >= meta.cosmeticAssets.Count) { continue; } CosmeticAsset val = meta.cosmeticAssets[cosmeticUnlock]; if (!((Object)(object)val == (Object)null) && (int)val.type == 0 && ((PrefabRef)(object)val.prefab).IsValid()) { if (HhhCosmeticLoader.IsWorldAsset(val)) { list2.Add(cosmeticUnlock); } else { list.Add(cosmeticUnlock); } } } if (list2.Count <= 0) { return; } meta.cosmeticEquipped.RemoveAll(delegate(int idx) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 if (idx < 0 || idx >= meta.cosmeticAssets.Count) { return false; } CosmeticAsset val2 = meta.cosmeticAssets[idx]; return (Object)(object)val2 != (Object)null && (int)val2.type == 0; }); if (list.Count > 0 && Random.Range(0f, 1f) <= 0.75f) { meta.cosmeticEquipped.Add(list[Random.Range(0, list.Count)]); } if (Random.Range(0f, 1f) <= 0.75f) { meta.cosmeticEquipped.Add(list2[Random.Range(0, list2.Count)]); } meta.Save(); meta.CosmeticPlayerUpdateLocal(false, false); } } internal static class WorldFollowPrefs { private sealed class Data { [JsonProperty(ItemConverterType = typeof(StringEnumConverter))] public Dictionary Springs { get; set; } = new Dictionary(StringComparer.Ordinal); public Dictionary ShowToSelf { get; set; } = new Dictionary(StringComparer.Ordinal); public Dictionary AvoidWalls { get; set; } = new Dictionary(StringComparer.Ordinal); public Dictionary HideOnKart { get; set; } = new Dictionary(StringComparer.Ordinal); } private const FollowSpringMode DefaultMode = FollowSpringMode.Soft; private static readonly string SavePath = BridgePaths.Of("World.json"); private static Data _data = new Data(); private static bool _loaded; private static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; try { if (File.Exists(SavePath)) { _data = JsonConvert.DeserializeObject(File.ReadAllText(SavePath)) ?? new Data(); } } catch (Exception ex) { BceConsole.LogWarning("World prefs load failed: " + ex.Message); _data = new Data(); } Data data = _data; if (data.Springs == null) { Dictionary dictionary = (data.Springs = new Dictionary(StringComparer.Ordinal)); } data = _data; if (data.ShowToSelf == null) { Dictionary dictionary3 = (data.ShowToSelf = new Dictionary(StringComparer.Ordinal)); } data = _data; if (data.AvoidWalls == null) { Dictionary dictionary3 = (data.AvoidWalls = new Dictionary(StringComparer.Ordinal)); } data = _data; if (data.HideOnKart == null) { Dictionary dictionary3 = (data.HideOnKart = new Dictionary(StringComparer.Ordinal)); } } internal static bool GetHideOnKart(string? assetId) { EnsureLoaded(); bool value = default(bool); return !string.IsNullOrEmpty(assetId) && _data.HideOnKart.TryGetValue(assetId, out value) && value; } internal static void SetHideOnKart(string? assetId, bool on) { EnsureLoaded(); if (!string.IsNullOrEmpty(assetId) && GetHideOnKart(assetId) != on) { _data.HideOnKart[assetId] = on; Save(); } } internal static bool GetAvoidWalls(string? assetId) { EnsureLoaded(); bool value = default(bool); return !string.IsNullOrEmpty(assetId) && _data.AvoidWalls.TryGetValue(assetId, out value) && value; } internal static void SetAvoidWalls(string? assetId, bool on) { EnsureLoaded(); if (!string.IsNullOrEmpty(assetId) && GetAvoidWalls(assetId) != on) { _data.AvoidWalls[assetId] = on; Save(); } } internal static bool GetShowToSelf(string? assetId) { EnsureLoaded(); bool value = default(bool); return !string.IsNullOrEmpty(assetId) && _data.ShowToSelf.TryGetValue(assetId, out value) && value; } internal static void SetShowToSelf(string? assetId, bool show) { EnsureLoaded(); if (!string.IsNullOrEmpty(assetId) && GetShowToSelf(assetId) != show) { _data.ShowToSelf[assetId] = show; Save(); } } internal static FollowSpringMode GetSpring(string? assetId) { EnsureLoaded(); if (string.IsNullOrEmpty(assetId)) { return FollowSpringMode.Soft; } if (!_data.Springs.TryGetValue(assetId, out var value)) { return FollowSpringMode.Soft; } return value; } internal static void SetSpring(string? assetId, FollowSpringMode mode) { EnsureLoaded(); if (!string.IsNullOrEmpty(assetId) && (!_data.Springs.TryGetValue(assetId, out var value) || value != mode)) { _data.Springs[assetId] = mode; Save(); } } private static void Save() { try { AtomicJson.Write(SavePath, JsonConvert.SerializeObject((object)_data, (Formatting)1)); } catch (Exception ex) { BceConsole.LogWarning("World prefs save failed: " + ex.Message); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }