The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of More Customizations v1.1.7
BepInEx/plugins/MoreCustomizations/MoreCustomizations.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using MoreCustomizations.Data; using MoreCustomizations.Helpers; using MoreCustomizations.Patches; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MoreCustomizations")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.7.0")] [assembly: AssemblyInformationalVersion("1.1.7+7ad2de393e1514292505e699ca0490ab434a3e81")] [assembly: AssemblyProduct("MoreCustomizations")] [assembly: AssemblyTitle("MoreCustomizations")] [assembly: AssemblyVersion("1.1.7.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MoreCustomizations { [BepInPlugin("MoreCustomizations", "MoreCustomizations", "1.1.7")] public class MoreCustomizationsPlugin : BaseUnityPlugin { internal static ManualLogSource Logger; internal static Harmony _patcher = new Harmony("MoreCustomizations"); internal static MoreCustomizationsPlugin Singleton { get; private set; } public static IReadOnlyDictionary<Type, IReadOnlyList<CustomizationData>> AllCustomizationsData { get; private set; } private void Awake() { Singleton = this; Logger = ((BaseUnityPlugin)this).Logger; LoadAllCustomizations(); Logger.LogInfo((object)"Patching methods..."); _patcher.PatchAll(typeof(PassportManagerPatch)); _patcher.PatchAll(typeof(CharacterCustomizationPatch)); _patcher.PatchAll(typeof(PlayerCustomizationDummyPatch)); _patcher.PatchAll(typeof(PeakHandlePatch)); Logger.LogInfo((object)"MoreCustomizations is loaded!"); } private void LoadAllCustomizations() { //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: 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_02f7: Unknown result type (might be due to invalid IL or missing references) AllCustomizationsData = null; Dictionary<Type, List<CustomizationData>> dictionary = new Dictionary<Type, List<CustomizationData>>(); string[] files = Directory.GetFiles(Path.Combine(Paths.BepInExRootPath, "plugins"), "*.pcab", SearchOption.AllDirectories); if (files.Length == 0) { throw new FileNotFoundException("No customization files found in '" + Paths.PluginPath + "'."); } Logger.LogInfo((object)$"Found {files.Length} possible contents."); List<CustomizationData> list = new List<CustomizationData>(); string[] array = files; foreach (string text in array) { string text2 = text; int length = Paths.PluginPath.Length; string text3 = text2.Substring(length, text2.Length - length); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); try { AssetBundle val = AssetBundle.LoadFromFile(text); Logger.LogInfo((object)("Asset bundle '" + fileNameWithoutExtension + "' loaded! (" + text3 + ")")); Logger.LogInfo((object)"Catalog list :"); string[] allAssetNames = val.GetAllAssetNames(); foreach (string text4 in allAssetNames) { Logger.LogInfo((object)("- " + text4)); } CustomizationData[] array2 = val.LoadAllAssets<CustomizationData>(); CustomizationData[] array3 = array2; foreach (CustomizationData customizationData in array3) { ((Object)customizationData).name = $"{text3.GetHashCode()}_{((Object)customizationData).name}"; } list.AddRange(array2); } catch (Exception ex) { Logger.LogError((object)("Error occurred while loading custom asset bundle. (" + text3 + ")")); Logger.LogError((object)ex.Message); Logger.LogError((object)ex.StackTrace); } } Logger.LogInfo((object)$"Loading {list.Count} customizations..."); foreach (CustomizationData item in list) { IEnumerable<ValidateStatus> enumerable = from status in item.GetValidateContentStatuses() where status.Type != ValidateStatus.ValidateType.Valid select status; bool flag = false; foreach (ValidateStatus item2 in enumerable) { flag |= item2.Type == ValidateStatus.ValidateType.Error; switch (item2.Type) { case ValidateStatus.ValidateType.Warning: Logger.LogWarning((object)("[Validation Warning:" + ((Object)item).name + "] " + item2.Message)); break; case ValidateStatus.ValidateType.Error: Logger.LogError((object)("[Validation Error:" + ((Object)item).name + "] " + item2.Message)); break; } } if (!flag) { Type type = item.Type; if (!dictionary.TryGetValue(type, out var value2)) { value2 = (dictionary[type] = new List<CustomizationData>()); } value2.Add(item); Logger.LogInfo((object)("Loaded '" + ((Object)item).name + "'!")); } } Logger.LogInfo((object)"Done!"); AllCustomizationsData = ((IEnumerable<KeyValuePair<Type, List<CustomizationData>>>)dictionary).ToDictionary((Func<KeyValuePair<Type, List<CustomizationData>>, Type>)((KeyValuePair<Type, List<CustomizationData>> key) => key.Key), (Func<KeyValuePair<Type, List<CustomizationData>>, IReadOnlyList<CustomizationData>>)((KeyValuePair<Type, List<CustomizationData>> value) => value.Value)); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "MoreCustomizations"; public const string PLUGIN_NAME = "MoreCustomizations"; public const string PLUGIN_VERSION = "1.1.7"; } } namespace MoreCustomizations.Data { public abstract class CustomizationData : ScriptableObject { public abstract Texture IconTexture { get; } public bool IsValid => GetValidateContentStatuses().All((ValidateStatus status) => status.Type != ValidateStatus.ValidateType.Error); public abstract Type Type { get; } public abstract IEnumerable<ValidateStatus> GetValidateContentStatuses(); } public abstract class CustomAccessoryData : CustomizationData { public sealed override Type Type => (Type)10; } public abstract class CustomEyesData : CustomizationData { public sealed override Type Type => (Type)20; } public abstract class CustomMouthData : CustomizationData { public sealed override Type Type => (Type)30; } public abstract class CustomHatData : CustomizationData { public sealed override Type Type => (Type)50; } public abstract class CustomFitData : CustomizationData { public sealed override Type Type => (Type)40; } [CreateAssetMenu(menuName = "PEAK More Customizations/Accessory", fileName = "New Custom Accessory", order = int.MinValue)] public class CustomAccessory_V1 : CustomAccessoryData { [field: SerializeField] public Texture Texture { get; internal set; } public override Texture IconTexture => Texture; public override IEnumerable<ValidateStatus> GetValidateContentStatuses() { if (!Object.op_Implicit((Object)(object)Texture)) { yield return ValidateStatus.Error("Texture is empty."); } else { yield return ValidateStatus.Valid; } } } [CreateAssetMenu(menuName = "PEAK More Customizations/Eye", fileName = "New Custom Eye", order = int.MinValue)] public class CustomEyes_V1 : CustomEyesData { [field: SerializeField] public Texture Texture { get; internal set; } public override Texture IconTexture => Texture; public override IEnumerable<ValidateStatus> GetValidateContentStatuses() { if (!Object.op_Implicit((Object)(object)Texture)) { yield return ValidateStatus.Error("Texture is empty."); } else { yield return ValidateStatus.Valid; } } } [CreateAssetMenu(menuName = "PEAK More Customizations/Fit", fileName = "New Custom Fit", order = int.MinValue)] public class CustomFit_V1 : CustomFitData { [field: SerializeField] [field: Tooltip("The texture for the icon in the Passport")] public Texture Icon { get; internal set; } [field: SerializeField] [field: Tooltip("If set to true, the eyes are rendered on top of the outfit at all times")] public bool DrawUnderEye { get; internal set; } [field: SerializeField] [field: Tooltip("The Mesh of the outfit we imported earlier")] public Mesh FitMesh { get; internal set; } [field: SerializeField] [field: Tooltip("The color texture for the second material slot")] public Texture FitMainTexture { get; internal set; } [field: SerializeField] [field: Tooltip("The color texture for the third material slot")] public Texture FitShoeTexture { get; internal set; } [field: SerializeField] [field: Tooltip("The color texture that can override the pants material. Leave blank to use the default pants material.")] public Texture FitOverridePantsTexture { get; internal set; } [field: SerializeField] [field: Tooltip("The color texture that can override the hat material. Only works on hats 0 and 1. Leave blank to use the default hat material.")] public Texture FitOverrideHatTexture { get; internal set; } [field: SerializeField] [field: Tooltip("Indicated whether the skirt or shorts mesh should be enabled for this outfit variant.")] public bool IsSkirt { get; internal set; } [field: SerializeField] [field: Tooltip("If true, hides both the skirt and shorts mesh for this outfit. Used for outfits like the Astronaut suit, that have no gendered variants.")] public bool NoPants { get; internal set; } public override Texture IconTexture => Icon; public override IEnumerable<ValidateStatus> GetValidateContentStatuses() { bool flag = false; if (!Object.op_Implicit((Object)(object)Icon)) { yield return ValidateStatus.Error("Icon is empty."); flag = true; } if (!Object.op_Implicit((Object)(object)FitMesh)) { yield return ValidateStatus.Error("FitMesh is empty."); flag = true; } if (!Object.op_Implicit((Object)(object)FitMainTexture)) { yield return ValidateStatus.Error("FitMainTexture is empty."); flag = true; } if (!Object.op_Implicit((Object)(object)FitShoeTexture)) { yield return ValidateStatus.Error("FitShoeTexture is empty."); flag = true; } if (!flag) { yield return ValidateStatus.Valid; } } } [CreateAssetMenu(menuName = "PEAK More Customizations/Hat", fileName = "New Custom Hat", order = int.MinValue)] public class CustomHat_V1 : CustomHatData { [field: SerializeField] public Texture Icon { get; internal set; } [field: SerializeField] public GameObject Prefab { get; internal set; } [field: SerializeField] public Texture MainTexture { get; internal set; } [field: SerializeField] public Texture SubTexture { get; internal set; } [field: SerializeField] public Vector3 PositionOffset { get; internal set; } [field: SerializeField] public Vector3 EulerAngleOffset { get; internal set; } public Vector3 SwizzledPositionOffset => new Vector3(PositionOffset.x, 0f - PositionOffset.z, PositionOffset.y); public Vector3 SwizzledRotationOffset => new Vector3(EulerAngleOffset.x, 0f - EulerAngleOffset.z, 0f - EulerAngleOffset.y); public override Texture IconTexture => Icon; public override IEnumerable<ValidateStatus> GetValidateContentStatuses() { bool flag = false; if (!Object.op_Implicit((Object)(object)Icon)) { yield return ValidateStatus.Error("Icon is empty."); flag = true; } if (!Object.op_Implicit((Object)(object)Prefab)) { yield return ValidateStatus.Error("Prefab is empty."); flag = true; } if (!flag) { yield return ValidateStatus.Valid; } } } [CreateAssetMenu(menuName = "PEAK More Customizations/Mouth", fileName = "New Custom Mouth", order = int.MinValue)] public class CustomMouth_V1 : CustomMouthData { [field: SerializeField] public Texture Texture { get; internal set; } public override Texture IconTexture => Texture; public override IEnumerable<ValidateStatus> GetValidateContentStatuses() { if (!Object.op_Implicit((Object)(object)Texture)) { yield return ValidateStatus.Error("Texture is empty."); } else { yield return ValidateStatus.Valid; } } } public struct ValidateStatus { public enum ValidateType { Valid, Warning, Error } public static readonly ValidateStatus Valid = new ValidateStatus("This asset is valid.", ValidateType.Valid); public readonly string Message; public readonly ValidateType Type; public ValidateStatus(string message, ValidateType type) { Message = message; Type = type; } public static ValidateStatus Warning(string message) { return new ValidateStatus(message, ValidateType.Warning); } public static ValidateStatus Error(string message) { return new ValidateStatus(message, ValidateType.Error); } } } namespace MoreCustomizations.Patches { public class CharacterCustomizationPatch { public const string HAT_PATH = "Scout/Armature/Hip/Mid/AimJoint/Torso/Head/Hat"; private static Shader _characterShader; private static MaterialPropertyBlock _materialPropertyBlock = new MaterialPropertyBlock(); private static readonly Vector3 INITIAL_HAT_OFFSET = new Vector3(0f, 0.2f, 6f); [HarmonyPatch(typeof(CharacterCustomization), "Awake")] [HarmonyPostfix] private static void Awake(CharacterCustomization __instance) { //IL_011d: 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_0129: 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_0141: 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_0150: 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_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown IReadOnlyDictionary<Type, IReadOnlyList<CustomizationData>> allCustomizationsData = MoreCustomizationsPlugin.AllCustomizationsData; if (allCustomizationsData == null) { MoreCustomizationsPlugin.Logger.LogError((object)"Customizations data are not loaded!"); return; } if (allCustomizationsData.Count == 0) { MoreCustomizationsPlugin.Logger.LogWarning((object)"There's no customizations data."); return; } if (!Object.op_Implicit((Object)(object)_characterShader)) { _characterShader = Shader.Find("W/Character"); } if (!allCustomizationsData.TryGetValue((Type)50, out var value)) { return; } Transform val = ((Component)__instance).transform.Find("Scout/Armature/Hip/Mid/AimJoint/Torso/Head/Hat"); if (!Object.op_Implicit((Object)(object)val)) { MoreCustomizationsPlugin.Logger.LogError((object)"Something went wrong in CharacterCustomizationPatch..."); return; } List<Renderer> list = new List<Renderer>(__instance.refs.playerHats); foreach (CustomHat_V1 item in value.OfType<CustomHat_V1>()) { if (!Object.op_Implicit((Object)(object)item) || !item.IsValid) { continue; } GameObject val2 = Object.Instantiate<GameObject>(item.Prefab, val, false); Renderer componentInChildren = val2.GetComponentInChildren<Renderer>(); if (!Object.op_Implicit((Object)(object)componentInChildren)) { MoreCustomizationsPlugin.Logger.LogError((object)("Cannot find Renderer component of customization data '" + ((Object)item).name + "'.")); Object.Destroy((Object)(object)val2); continue; } val2.transform.localPosition = INITIAL_HAT_OFFSET + item.SwizzledPositionOffset; val2.transform.localRotation = Quaternion.Euler(item.SwizzledRotationOffset) * Quaternion.AngleAxis(90f, Vector3.right); ((Component)componentInChildren).gameObject.SetActive(false); ((Object)componentInChildren).name = ((Object)item).name; Material val3 = new Material(_characterShader); Material val4 = new Material(_characterShader); if (Object.op_Implicit((Object)(object)item.MainTexture)) { val3.SetTexture("_MainTex", item.MainTexture); } if (Object.op_Implicit((Object)(object)item.SubTexture)) { val4.SetTexture("_MainTex", item.SubTexture); } componentInChildren.materials = (Material[])(object)new Material[2] { val3, val4 }; list.Add(componentInChildren); } __instance.refs.playerHats = list.ToArray(); } } public class PassportManagerPatch { private static Material materialTemplate; [HarmonyPatch(typeof(PassportManager), "Awake")] [HarmonyPostfix] private static void Awake(PassportManager __instance) { //IL_0105: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Invalid comparison between Unknown and I4 //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Invalid comparison between Unknown and I4 //IL_0113: 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_012f: Invalid comparison between Unknown and I4 //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Invalid comparison between Unknown and I4 //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Invalid comparison between Unknown and I4 //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Invalid comparison between Unknown and I4 //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: 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_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Invalid comparison between Unknown and I4 IReadOnlyDictionary<Type, IReadOnlyList<CustomizationData>> allCustomizationsData = MoreCustomizationsPlugin.AllCustomizationsData; if (allCustomizationsData == null) { MoreCustomizationsPlugin.Logger.LogError((object)"Customizations data are not loaded!"); return; } if (allCustomizationsData.Count == 0) { MoreCustomizationsPlugin.Logger.LogWarning((object)"There's no customizations data."); return; } Customization component = ((Component)__instance).GetComponent<Customization>(); List<CustomizationOption> list = new List<CustomizationOption>(component.skins); List<CustomizationOption> list2 = new List<CustomizationOption>(component.accessories); List<CustomizationOption> list3 = new List<CustomizationOption>(component.eyes); List<CustomizationOption> list4 = new List<CustomizationOption>(component.mouths); List<CustomizationOption> list5 = new List<CustomizationOption>(component.fits); List<CustomizationOption> list6 = new List<CustomizationOption>(component.hats); string[] array = new string[2] { "Ice Hood Blue", "Ice Hood Pink" }; foreach (string missingHat in array) { if (!list6.Any((CustomizationOption h) => ((Object)h).name == missingHat)) { list6.Add(CreateHatPlaceholder()); } } foreach (var (val2, readOnlyList2) in allCustomizationsData) { List<CustomizationOption> list7; if ((int)val2 <= 20) { if ((int)val2 != 0) { if ((int)val2 != 10) { if ((int)val2 != 20) { goto IL_015b; } list7 = list3; } else { list7 = list2; } } else { list7 = list; } } else if ((int)val2 != 30) { if ((int)val2 != 40) { if ((int)val2 != 50) { goto IL_015b; } list7 = list6; } else { list7 = list5; } } else { list7 = list4; } goto IL_015e; IL_015b: list7 = null; goto IL_015e; IL_015e: List<CustomizationOption> list8 = list7; if (list8 == null) { continue; } foreach (CustomizationData item in readOnlyList2) { if (!Object.op_Implicit((Object)(object)item) || !item.IsValid) { continue; } CustomizationOption val3 = ScriptableObject.CreateInstance<CustomizationOption>(); val3.requiredAchievement = (ACHIEVEMENTTYPE)0; ((Object)val3).name = ((Object)item).name; val3.type = item.Type; val3.texture = item.IconTexture; if ((int)val2 == 40) { CustomFit_V1 customFit_V = item as CustomFit_V1; if (!Object.op_Implicit((Object)(object)customFit_V)) { continue; } if (!Object.op_Implicit((Object)(object)materialTemplate)) { materialTemplate = component?.fits.FirstOrDefault()?.fitMaterial; if (!Object.op_Implicit((Object)(object)materialTemplate)) { MoreCustomizationsPlugin.Logger.LogWarning((object)"Could not find existing fitMaterial to copy! Using fallback material, expect some visual errors"); materialTemplate = FitMaterialFallback.MaterialTemplate; } } val3.fitMesh = customFit_V.FitMesh; val3.isSkirt = customFit_V.IsSkirt; val3.noPants = customFit_V.NoPants; val3.drawUnderEye = customFit_V.DrawUnderEye; val3.fitMaterial = Object.Instantiate<Material>(materialTemplate); val3.fitMaterial.SetTexture("_MainTex", customFit_V.FitMainTexture); val3.fitMaterialShoes = Object.Instantiate<Material>(materialTemplate); val3.fitMaterialShoes.SetTexture("_MainTex", customFit_V.FitShoeTexture); if (Object.op_Implicit((Object)(object)customFit_V.FitOverrideHatTexture)) { val3.fitMaterialOverrideHat = Object.Instantiate<Material>(materialTemplate); val3.fitMaterialOverrideHat.SetTexture("_MainTex", customFit_V.FitOverrideHatTexture); } if (Object.op_Implicit((Object)(object)customFit_V.FitOverridePantsTexture)) { val3.fitMaterialOverridePants = Object.Instantiate<Material>(materialTemplate); val3.fitMaterialOverridePants.SetTexture("_MainTex", customFit_V.FitOverridePantsTexture); } } list8.Add(val3); } } component.skins = list.ToArray(); component.accessories = list2.ToArray(); component.eyes = list3.ToArray(); component.mouths = list4.ToArray(); component.fits = list5.ToArray(); component.hats = list6.ToArray(); } private static CustomizationOption CreateHatPlaceholder() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) CustomizationOption obj = ScriptableObject.CreateInstance<CustomizationOption>(); ((Object)obj).name = "None"; obj.type = (Type)50; obj.requiresAscent = true; obj.requiredAscent = 99999; return obj; } [HarmonyPatch(typeof(PassportManager), "CameraIn")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> CameraInTranspiler(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand != null && instruction.operand.Equals(1f)) { instruction.operand = 3f; yield return instruction; } else { yield return instruction; } } } [HarmonyPatch(typeof(PassportManager), "CameraOut")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> CameraOutTranspiler(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand != null && instruction.operand.Equals(1f)) { instruction.operand = 3f; yield return instruction; } else { yield return instruction; } } } } public class PeakHandlePatch { [HarmonyPatch(typeof(PeakHandler), "SetCosmetics")] [HarmonyPrefix] private static void SetCosmetics(PeakHandler __instance, List<Character> characters) { if (!CustomizationRefsHelper.SyncCustomHats(__instance.firstCutsceneScout)) { MoreCustomizationsPlugin.Logger.LogError((object)"Something went wrong in PeakHandlePatch [firstCutsceneScout]..."); } for (int i = 0; i < __instance.cutsceneScoutRefs.Count(); i++) { if (!CustomizationRefsHelper.SyncCustomHats(__instance.cutsceneScoutRefs[i])) { MoreCustomizationsPlugin.Logger.LogError((object)string.Format("Something went wrong in {0} [cutsceneScoutRefs-{1}]...", "PeakHandlePatch", i)); } } } } public class PlayerCustomizationDummyPatch { [HarmonyPatch(typeof(PlayerCustomizationDummy), "SetPlayerHat")] [HarmonyPrefix] private static void SetPlayerHat(PlayerCustomizationDummy __instance, int index) { if (!CustomizationRefsHelper.SyncCustomHats(__instance.refs)) { MoreCustomizationsPlugin.Logger.LogError((object)"Something went wrong in SetPlayerHat patch..."); } } } } namespace MoreCustomizations.Helpers { public class CustomizationRefsHelper { public const string REF_TO_HATS_PATH = "Armature/Hip/Mid/AimJoint/Torso/Head/Hat"; public static bool SyncCustomHats(CustomizationRefs dstRefs, CustomizationRefs srcRefs = null) { if ((Object)(object)srcRefs == (Object)null) { Character localCharacter = Character.localCharacter; CharacterCustomization val = default(CharacterCustomization); if (!Object.op_Implicit((Object)(object)localCharacter) || !((Component)localCharacter).TryGetComponent<CharacterCustomization>(ref val)) { MoreCustomizationsPlugin.Logger.LogError((object)"Cannot get [LocalCharacter] or its' [CustomizationRefs] ..."); return false; } srcRefs = val.refs; } Renderer[] playerHats = srcRefs.playerHats; Renderer[] playerHats2 = dstRefs.playerHats; if (playerHats.Length == playerHats2.Length) { return true; } Renderer val2 = playerHats2.FirstOrDefault(); if (!Object.op_Implicit((Object)(object)val2)) { MoreCustomizationsPlugin.Logger.LogError((object)"Cannot find renders in dstPlayerHats..."); return false; } int layer = ((Component)val2).gameObject.layer; Transform val3 = ((Component)srcRefs).transform.Find("Armature/Hip/Mid/AimJoint/Torso/Head/Hat"); Transform val4 = ((Component)dstRefs).transform.Find("Armature/Hip/Mid/AimJoint/Torso/Head/Hat"); List<Renderer> list = new List<Renderer>(playerHats2); for (int i = playerHats2.Length; i < playerHats.Length; i++) { Transform val5 = ((Component)playerHats[i]).transform; while ((Object)(object)val5.parent != (Object)(object)val3) { val5 = val5.parent; } GameObject obj = Object.Instantiate<GameObject>(((Component)val5).gameObject, val4, false); ((Object)obj).name = ((Object)val5).name; Renderer componentInChildren = obj.GetComponentInChildren<Renderer>(true); ((Component)componentInChildren).gameObject.layer = layer; list.Add(componentInChildren); } dstRefs.playerHats = list.ToArray(); return true; } } public static class FitMaterialFallback { private static readonly (string, float)[] FLOATS = new(string, float)[83] { ("_AddPrecomputedVelocity", 0f), ("_AddSpecular", 0f), ("_AlphaClip", 0f), ("_AlphaCutoff", 0.5f), ("_AlphaToMask", 0f), ("_BaseSmooth", 0f), ("_Blend", 0f), ("_BlendModePreserveSpecular", 1f), ("_Brightness", 1f), ("_BumpScale", 1f), ("_ClearCoatMask", 0f), ("_ClearCoatSmoothness", 0f), ("_Cull", 2f), ("_Cutoff", 0.5f), ("_DetailAlbedoMapScale", 1f), ("_DetailNormalMapScale", 1f), ("_DstBlend", 0f), ("_DstBlendAlpha", 0f), ("_EnvironmentReflections", 1f), ("_Flip1", 0f), ("_Flip2", 0f), ("_Flip3", 0f), ("_Flip4", 0f), ("_FlipHeightMask", 0f), ("_GlossMapScale", 0f), ("_Glossiness", 0f), ("_GlossyReflections", 0f), ("_Glow", 0f), ("_Height1", 0f), ("_Height2", 0f), ("_Height3", 0f), ("_Height4", 0f), ("_HueStr", 1f), ("_INTERACTABLE", 0f), ("_Interactable", 0f), ("_Metalic", 0f), ("_Metallic", 0f), ("_Mode", 0f), ("_OcclusionStrength", 1f), ("_Opacity", 1f), ("_Outline", 1f), ("_Parallax", 0.005f), ("_QueueControl", 0f), ("_QueueOffset", 0f), ("_ReceiveShadows", 1f), ("_ReflectionBoost", 0f), ("_Smooth1", 0f), ("_Smooth2", 0f), ("_Smooth3", 0f), ("_Smooth4", 0f), ("_Smoothness", 0.5f), ("_SmoothnessTextureChannel", 0f), ("_SpecularHighlights", 1f), ("_SrcBlend", 1f), ("_SrcBlendAlpha", 1f), ("_StatusGlow", 0f), ("_Surface", 0f), ("_ToggleSwitch0", 0f), ("_Triplanar1", 0f), ("_Triplanar1On", 0f), ("_Triplanar2", 0f), ("_Triplanar2On", 0f), ("_Triplanar3", 0f), ("_Triplanar3On", 0f), ("_Triplanar4", 0f), ("_Triplanar4On", 0f), ("_UV1", 1.15f), ("_UV2", 0.27f), ("_UV3", 1f), ("_UV4", 1f), ("_UVSec", 0f), ("_UseHeightMask1", 0f), ("_UseHeightMask2", 0f), ("_UseHeightMask3", 0f), ("_UseHeightMask4", 0f), ("_UseRawVertexColor", 0f), ("_UseSkinTone", 0f), ("_UseTextureAlpha", 0f), ("_UseVertexColor", 0f), ("_VertexColor", 1f), ("_VertexGhost", 0f), ("_WorkflowMode", 1f), ("_ZWrite", 1f) }; private static readonly (string, Color)[] COLORS = new(string, Color)[18] { ("_BaseColor", new Color(1f, 1f, 1f, 1f)), ("_Color", new Color(1f, 1f, 1f, 1f)), ("_Color0", new Color(4f, 2.191751f, 0f, 0f)), ("_Color1", new Color(91f / 106f, 0.6924617f, 0.6924617f, 1f)), ("_Color2", new Color(69f / 106f, 0.58534664f, 0.5066305f, 0.6509804f)), ("_Color3", new Color(1f, 1f, 1f, 0f)), ("_Color4", new Color(1f, 1f, 1f, 0f)), ("_EmissionColor", new Color(0f, 0f, 0f, 1f)), ("_HeightMaskSmoothness", new Color(0f, 0f, 0f, 0f)), ("_HueShifts", new Color(0f, 0f, 0f, 0f)), ("_Remap1", new Color(0.35514024f, 0.551402f, 0f, 0f)), ("_Remap2", new Color(0.31775698f, 0.71962625f, 0f, 0f)), ("_Remap3", new Color(0f, 1f, 0f, 0f)), ("_Remap4", new Color(0f, 1f, 0f, 0f)), ("_SkinColor", new Color(1f, 1f, 1f, 0f)), ("_SpecColor", new Color(0.19999996f, 0.19999996f, 0.19999996f, 1f)), ("_StatusColor", new Color(2.600001f, 0.5094339f, 4f, 1f)), ("_Tint", new Color(1f, 1f, 1f, 1f)) }; public static Material MaterialTemplate { get { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //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_0067: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(Shader.Find("W/Character")); (string, float)[] fLOATS = FLOATS; for (int i = 0; i < fLOATS.Length; i++) { var (text, num) = fLOATS[i]; val.SetFloat(text, num); } (string, Color)[] cOLORS = COLORS; for (int i = 0; i < cOLORS.Length; i++) { var (text2, val2) = cOLORS[i]; val.SetColor(text2, val2); } return val; } } } }