Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Sam Model v1.0.1
BepInEx/plugins/SamModel.dll
Decompiled 8 hours agousing System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using ModelReplacement; using ModelReplacement.AvatarBodyUpdater; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; [assembly: AssemblyTitle("SamModel")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("1.0.1.0")] namespace SamModel; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("reagan.sammodel", "Sam Model", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "reagan.sammodel"; public const string Name = "Sam Model"; public const string Version = "1.0.1"; internal static ManualLogSource Log; internal static ConfigEntry<string> SuitNames; internal static ConfigEntry<string> FitTo; internal static ConfigEntry<float> ScaleMultiplier; internal static ConfigEntry<float> HipsOffset; internal static ConfigEntry<float> MaxSmoothness; internal static ConfigEntry<bool> CompressTextures; internal static ConfigEntry<bool> GenerateViewModel; private static bool started; private static int attempts; private void Awake() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; SuitNames = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SuitNames", "Sam", "Comma separated suit names that turn the wearer into Sam."); FitTo = ((BaseUnityPlugin)this).Config.Bind<string>("Model", "FitTo", "Arms", new ConfigDescription("What the automatic size is matched to. Arms: the hands land on the player's hands (about as tall as a vanilla player). Legs: the legs are as long as the player's (smaller, hands fall short).", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Arms", "Legs" }), new object[0])); ScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Model", "ScaleMultiplier", 1f, "Extra scale on top of the automatic size."); HipsOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Model", "HipsOffset", 0f, "Raises (positive) or lowers the model, in game units; a player is about 2.6 units tall. The soles are put on the floor automatically, use this only to fine-tune."); MaxSmoothness = ((BaseUnityPlugin)this).Config.Bind<float>("Model", "MaxSmoothness", 0.75f, "Upper limit of surface smoothness. Lower it if the gear looks too shiny."); CompressTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance", "CompressTextures", true, "Compress textures on load. Uses about a quarter of the video memory; loading takes a little longer."); GenerateViewModel = ((BaseUnityPlugin)this).Config.Bind<bool>("Model", "GenerateViewModel", false, "Let ModelReplacementAPI build first person arms from the model instead of showing the vanilla arms."); SamAssets.Directory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); EnsureSuitTexture(SamAssets.Directory); SceneManager.sceneLoaded += OnSceneLoaded; } private static void EnsureSuitTexture(string directory) { try { string[] files = Directory.GetFiles(directory, "Sam.png", SearchOption.AllDirectories); string[] array = files; foreach (string path in array) { string fileName = Path.GetFileName(Path.GetDirectoryName(path)); if (string.Equals(fileName, "moresuits", StringComparison.OrdinalIgnoreCase)) { return; } } if (files.Length == 0) { Log.LogWarning((object)"Sam.png (the suit texture for More Suits) is missing; the suit will not appear on the rack."); return; } string text = Path.Combine(directory, "moresuits"); Directory.CreateDirectory(text); File.Copy(files[0], Path.Combine(text, "Sam.png"), overwrite: true); File.Delete(files[0]); Log.LogInfo((object)("Moved Sam.png into " + text + ".")); } catch (Exception ex) { Log.LogWarning((object)("Could not place Sam.png into a moresuits folder: " + ex.Message)); } } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (started) { return; } if ((Object)(object)Shader.Find("HDRP/Lit") == (Object)null && ++attempts < 4) { Log.LogInfo((object)("Render pipeline not ready in scene '" + ((Scene)(ref scene)).name + "', building the model on the next scene.")); return; } started = true; SceneManager.sceneLoaded -= OnSceneLoaded; try { float realtimeSinceStartup = Time.realtimeSinceStartup; SamAssets.Build(); string[] array = SuitNames.Value.Split(','); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length > 0) { ModelReplacementAPI.RegisterSuitModelReplacement(text2, typeof(SamReplacement)); Log.LogInfo((object)("Suit '" + text2 + "' now wears the Sam model.")); } } Log.LogInfo((object)("Sam model ready in " + (Time.realtimeSinceStartup - realtimeSinceStartup).ToString("0.0") + " s.")); } catch (Exception ex) { Log.LogError((object)("Sam model could not be built, the suit will look like a normal suit.\n" + ex)); } } } public class SamReplacement : BodyReplacementBase { private static bool apiScaleUnusable; private bool scaleReported; protected override GameObject LoadAssetsAndReturnModel() { return SamAssets.GetTemplate(((BodyReplacementBase)this).controller); } protected override void AddModelScripts() { EnforceScale(base.replacementModel); } public override void LateUpdate() { ((BodyReplacementBase)this).LateUpdate(); if (apiScaleUnusable && (Object)(object)base.replacementDeadBody != (Object)null) { EnforceScale(base.replacementDeadBody); } } private void EnforceScale(GameObject model) { //IL_001c: 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_010b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)model == (Object)null) { return; } float scale = SamAssets.GetScale(((BodyReplacementBase)this).controller); Vector3 localScale = model.transform.localScale; bool flag = !float.IsNaN(localScale.x) && !float.IsInfinity(localScale.x) && localScale.x > 0f; if (!flag) { apiScaleUnusable = true; } if (!flag || Mathf.Abs(localScale.x - scale) > 0.01f * scale || Mathf.Abs(localScale.y - scale) > 0.01f * scale || Mathf.Abs(localScale.z - scale) > 0.01f * scale) { if (!scaleReported) { scaleReported = true; Plugin.Log.LogInfo((object)("API scale was " + localScale.x.ToString("0.000") + ", using " + scale.ToString("0.000") + ".")); } model.transform.localScale = new Vector3(scale, scale, scale); } } } internal static class SamAssets { private class BoneInfo { public string Name; public string Driver; public int Parent; public int Human; public Vector3 Position; public Quaternion Rotation; } private const string ModelFile = "sam_model.bin"; private const float GameHipsPerLeg = 1.1868f; private const float GameShoulderPerLeg = 1.8379f; internal static string Directory; private static GameObject template; private static SkinnedMeshRenderer body; private static OffsetBuilder offsets; private static Bounds meshBounds; private static Quaternion hipsRest = Quaternion.identity; private static float modelLeg; private static float modelArm; private static float modelHipsHeight; private static float modelShoulderHeight; private static float gameLeg = -1f; private static float gameArm = -1f; private static float gameHipsScale = 1f; internal static GameObject GetTemplate(PlayerControllerB player) { //IL_0011: 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_0026: Unknown result type (might be due to invalid IL or missing references) float scale = GetScale(player); template.transform.localScale = Vector3.one; offsets.rootPositionOffset = GetHipsOffset(scale); offsets.GenerateViewModel = Plugin.GenerateViewModel.Value; return template; } internal static float GetScale(PlayerControllerB player) { Measure(player); float num = ((gameLeg > 0f) ? (gameLeg / modelLeg) : 1.23f); float num2 = num; if (gameLeg > 0f && gameArm > 0f && !string.Equals(Plugin.FitTo.Value, "Legs", StringComparison.OrdinalIgnoreCase)) { float num3 = gameArm / modelArm; float num4 = 1.8379f * gameLeg / modelShoulderHeight; num2 = 0.5f * (num3 + num4); } return num2 * Mathf.Clamp(Plugin.ScaleMultiplier.Value, 0.2f, 5f); } private static Vector3 GetHipsOffset(float scale) { //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_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) //IL_0048: Unknown result type (might be due to invalid IL or missing references) float num = Plugin.HipsOffset.Value; if (gameLeg > 0f) { num += scale * modelHipsHeight - 1.1868f * gameLeg; } return Quaternion.Inverse(hipsRest) * Vector3.up * (num / gameHipsScale); } private static void Measure(PlayerControllerB player) { //IL_00e0: 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_00f1: 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_010a: 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_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_0136: 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_021d: Unknown result type (might be due to invalid IL or missing references) if (gameLeg > 0f || (Object)(object)player == (Object)null || (Object)(object)player.thisPlayerModel == (Object)null) { return; } Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(); Transform[] bones = player.thisPlayerModel.bones; foreach (Transform val in bones) { if ((Object)(object)val != (Object)null) { dictionary[((Object)val).name] = val; } } if (!dictionary.TryGetValue("thigh.L", out var value) || !dictionary.TryGetValue("shin.L", out var value2) || !dictionary.TryGetValue("foot.L", out var value3) || !dictionary.TryGetValue("arm.L_upper", out var value4) || !dictionary.TryGetValue("arm.L_lower", out var value5) || !dictionary.TryGetValue("hand.L", out var value6) || !dictionary.TryGetValue("spine", out var value7)) { Plugin.Log.LogWarning((object)"The player rig has unexpected bone names; using the default size."); return; } gameLeg = Vector3.Distance(value.position, value2.position) + Vector3.Distance(value2.position, value3.position); gameArm = Vector3.Distance(value4.position, value5.position) + Vector3.Distance(value5.position, value6.position); gameHipsScale = Mathf.Max(value7.lossyScale.y, 0.0001f); float scale = GetScale(null); ManualLogSource log = Plugin.Log; string[] array = new string[15] { "Player leg ", gameLeg.ToString("0.000"), ", arm ", gameArm.ToString("0.000"), "; model leg ", modelLeg.ToString("0.000"), ", arm ", modelArm.ToString("0.000"), "; fit '", Plugin.FitTo.Value, "' gives scale ", scale.ToString("0.000"), ", hips offset ", null, null }; Vector3 hipsOffset = GetHipsOffset(scale); array[13] = ((Vector3)(ref hipsOffset)).ToString("0.000"); array[14] = "."; log.LogInfo((object)string.Concat(array)); } internal static void Build() { //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_0107: 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_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_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: 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_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_0297: 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_0323: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Expected O, but got Unknown //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Expected O, but got Unknown //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Expected O, but got Unknown //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Expected O, but got Unknown //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_0625: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_063b: Unknown result type (might be due to invalid IL or missing references) //IL_064a: Unknown result type (might be due to invalid IL or missing references) //IL_0666: Unknown result type (might be due to invalid IL or missing references) //IL_0675: 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_077c: Unknown result type (might be due to invalid IL or missing references) //IL_0792: Unknown result type (might be due to invalid IL or missing references) //IL_080b: Unknown result type (might be due to invalid IL or missing references) //IL_088b: Unknown result type (might be due to invalid IL or missing references) //IL_07ba: Unknown result type (might be due to invalid IL or missing references) //IL_07f5: Unknown result type (might be due to invalid IL or missing references) //IL_08eb: Unknown result type (might be due to invalid IL or missing references) //IL_08f2: Expected O, but got Unknown //IL_09d8: Unknown result type (might be due to invalid IL or missing references) //IL_09dd: Unknown result type (might be due to invalid IL or missing references) string text = Find("sam_model.bin"); if (text == null) { throw new FileNotFoundException("sam_model.bin not found under " + Directory); } BoneInfo[] array; Vector3[] array7; Vector3[] array8; Vector2[] array9; BoneWeight[] array10; string[] array11; int[][] array12; using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(text))) { if (new string(binaryReader.ReadChars(4)) != "HGLC" || binaryReader.ReadUInt32() != 1) { throw new InvalidDataException("unexpected model file header"); } int num = (int)binaryReader.ReadUInt32(); int num2 = (int)binaryReader.ReadUInt32(); int num3 = (int)binaryReader.ReadUInt32(); array = new BoneInfo[num]; for (int i = 0; i < num; i++) { BoneInfo boneInfo = new BoneInfo(); boneInfo.Name = ReadString(binaryReader); boneInfo.Driver = ReadString(binaryReader); boneInfo.Parent = binaryReader.ReadInt32(); boneInfo.Human = binaryReader.ReadInt32(); boneInfo.Position = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); boneInfo.Rotation = new Quaternion(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array[i] = boneInfo; } float[] array2 = ReadFloats(binaryReader, num2 * 3); float[] array3 = ReadFloats(binaryReader, num2 * 3); float[] array4 = ReadFloats(binaryReader, num2 * 2); byte[] array5 = binaryReader.ReadBytes(num2 * 4); float[] array6 = ReadFloats(binaryReader, num2 * 4); array7 = (Vector3[])(object)new Vector3[num2]; array8 = (Vector3[])(object)new Vector3[num2]; array9 = (Vector2[])(object)new Vector2[num2]; array10 = (BoneWeight[])(object)new BoneWeight[num2]; for (int j = 0; j < num2; j++) { ref Vector3 reference = ref array7[j]; reference = new Vector3(array2[j * 3], array2[j * 3 + 1], array2[j * 3 + 2]); ref Vector3 reference2 = ref array8[j]; reference2 = new Vector3(array3[j * 3], array3[j * 3 + 1], array3[j * 3 + 2]); ref Vector2 reference3 = ref array9[j]; reference3 = new Vector2(array4[j * 2], array4[j * 2 + 1]); BoneWeight val = default(BoneWeight); ((BoneWeight)(ref val)).boneIndex0 = array5[j * 4]; ((BoneWeight)(ref val)).weight0 = array6[j * 4]; ((BoneWeight)(ref val)).boneIndex1 = array5[j * 4 + 1]; ((BoneWeight)(ref val)).weight1 = array6[j * 4 + 1]; ((BoneWeight)(ref val)).boneIndex2 = array5[j * 4 + 2]; ((BoneWeight)(ref val)).weight2 = array6[j * 4 + 2]; ((BoneWeight)(ref val)).boneIndex3 = array5[j * 4 + 3]; ((BoneWeight)(ref val)).weight3 = array6[j * 4 + 3]; array10[j] = val; } array11 = new string[num3]; array12 = new int[num3][]; for (int k = 0; k < num3; k++) { array11[k] = ReadString(binaryReader); int num4 = (int)binaryReader.ReadUInt32(); byte[] array13 = binaryReader.ReadBytes(num4 * 4); array12[k] = new int[num4]; Buffer.BlockCopy(array13, 0, array12[k], 0, array13.Length); } } GameObject val2 = new GameObject("SamModel"); val2.transform.position = Vector3.zero; val2.transform.rotation = Quaternion.identity; Transform[] array14 = (Transform[])(object)new Transform[array.Length]; Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(); for (int l = 0; l < array.Length; l++) { GameObject val3 = new GameObject(array[l].Name); val3.transform.SetParent((array[l].Parent < 0) ? val2.transform : array14[array[l].Parent], false); val3.transform.position = array[l].Position; val3.transform.rotation = array[l].Rotation; array14[l] = val3.transform; dictionary[array[l].Name] = val3.transform; } modelLeg = Vector3.Distance(dictionary["LeftUpperLeg"].position, dictionary["LeftLowerLeg"].position) + Vector3.Distance(dictionary["LeftLowerLeg"].position, dictionary["LeftFoot"].position); modelArm = Vector3.Distance(dictionary["LeftUpperArm"].position, dictionary["LeftLowerArm"].position) + Vector3.Distance(dictionary["LeftLowerArm"].position, dictionary["LeftHand"].position); hipsRest = dictionary["Hips"].rotation; GameObject val4 = new GameObject("Body"); val4.transform.SetParent(val2.transform, false); Mesh val5 = new Mesh(); ((Object)val5).name = "Sam"; val5.indexFormat = (IndexFormat)1; val5.vertices = array7; val5.normals = array8; val5.uv = array9; val5.boneWeights = array10; Matrix4x4[] array15 = (Matrix4x4[])(object)new Matrix4x4[array.Length]; for (int m = 0; m < array.Length; m++) { ref Matrix4x4 reference4 = ref array15[m]; reference4 = array14[m].worldToLocalMatrix * val4.transform.localToWorldMatrix; } val5.bindposes = array15; List<string> list = new List<string>(); List<int[]> list2 = new List<int[]>(); for (int n = 0; n < array11.Length; n++) { int num5 = array11[n].IndexOf('#'); if (num5 < 0 || PartEnabled(array11[n].Substring(num5 + 1))) { list.Add((num5 >= 0) ? array11[n].Substring(0, num5) : array11[n]); list2.Add(array12[n]); } } val5.subMeshCount = list2.Count; for (int num6 = 0; num6 < list2.Count; num6++) { val5.SetTriangles(list2[num6], num6, false); } val5.RecalculateBounds(); val5.RecalculateTangents(); meshBounds = val5.bounds; modelHipsHeight = dictionary["Hips"].position.y - ((Bounds)(ref meshBounds)).min.y; modelShoulderHeight = dictionary["LeftUpperArm"].position.y - ((Bounds)(ref meshBounds)).min.y; Material[] array16 = (Material[])(object)new Material[list.Count]; Shader val6 = Shader.Find("HDRP/Lit"); if ((Object)(object)val6 == (Object)null) { throw new InvalidOperationException("shader HDRP/Lit is not available"); } Dictionary<string, Material> dictionary2 = new Dictionary<string, Material>(); for (int num7 = 0; num7 < list.Count; num7++) { if (!dictionary2.TryGetValue(list[num7], out var value)) { value = BuildMaterial(val6, list[num7]); dictionary2[list[num7]] = value; } array16[num7] = value; } body = val4.AddComponent<SkinnedMeshRenderer>(); body.sharedMesh = val5; body.bones = array14; body.rootBone = null; ((Renderer)body).sharedMaterials = array16; ((Renderer)body).localBounds = meshBounds; body.quality = (SkinQuality)4; List<HumanBone> list3 = new List<HumanBone>(); List<SkeletonBone> list4 = new List<SkeletonBone>(); list4.Add(ToSkeletonBone(val2.transform)); for (int num8 = 0; num8 < array.Length; num8++) { list4.Add(ToSkeletonBone(array14[num8])); if (array[num8].Human >= 0 && array[num8].Human < HumanTrait.BoneCount) { HumanBone item = default(HumanBone); ((HumanBone)(ref item)).boneName = array[num8].Name; ((HumanBone)(ref item)).humanName = HumanTrait.BoneName[array[num8].Human]; ((HumanLimit)(ref item.limit)).useDefaultValues = true; list3.Add(item); } } HumanDescription val7 = new HumanDescription { human = list3.ToArray(), skeleton = list4.ToArray() }; ((HumanDescription)(ref val7)).upperArmTwist = 0.5f; ((HumanDescription)(ref val7)).lowerArmTwist = 0.5f; ((HumanDescription)(ref val7)).upperLegTwist = 0.5f; ((HumanDescription)(ref val7)).lowerLegTwist = 0.5f; ((HumanDescription)(ref val7)).armStretch = 0.05f; ((HumanDescription)(ref val7)).legStretch = 0.05f; ((HumanDescription)(ref val7)).feetSpacing = 0f; ((HumanDescription)(ref val7)).hasTranslationDoF = false; Avatar val8 = AvatarBuilder.BuildHumanAvatar(val2, val7); ((Object)val8).name = "SamAvatar"; if (!val8.isValid || !val8.isHuman) { Object.Destroy((Object)(object)val2); throw new InvalidOperationException("the humanoid avatar is not valid (see the Unity log above for the bone it rejects)"); } Animator val9 = val2.AddComponent<Animator>(); val9.avatar = val8; val9.applyRootMotion = false; val9.cullingMode = (AnimatorCullingMode)0; GameObject val10 = new GameObject("ItemHolder"); val10.transform.SetParent(dictionary["RightHand"], false); offsets = val2.AddComponent<OffsetBuilder>(); offsets.itemHolder = val10; int num9 = 0; BoneInfo[] array17 = array; foreach (BoneInfo boneInfo2 in array17) { if (boneInfo2.Driver.Length > 0 && (Object)(object)val9.GetBoneTransform((HumanBodyBones)boneInfo2.Human) == (Object)(object)dictionary[boneInfo2.Name]) { num9++; } } ManualLogSource log = Plugin.Log; object[] array18 = new object[9] { "Built Sam: ", array7.Length, " vertices, ", array.Length, " bones, ", num9, " of them driven by the player rig, bounds ", null, null }; Vector3 size = ((Bounds)(ref meshBounds)).size; array18[7] = ((Vector3)(ref size)).ToString("0.00"); array18[8] = "."; log.LogInfo((object)string.Concat(array18)); Object.DontDestroyOnLoad((Object)(object)val2); val2.SetActive(false); template = val2; } private static SkeletonBone ToSkeletonBone(Transform t) { //IL_0002: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_003c: Unknown result type (might be due to invalid IL or missing references) return new SkeletonBone { name = ((Object)t).name, position = t.localPosition, rotation = t.localRotation, scale = t.localScale }; } private static bool PartEnabled(string part) { return true; } private static Material BuildMaterial(Shader lit, string set) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001e: 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: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 //IL_00d2: 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_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(lit); ((Object)val).name = "Sam_" + set; val.SetColor("_BaseColor", Color.white); Texture2D val2 = LoadImage("sam_" + set + "_bc", linear: false); bool flag = false; if ((Object)(object)val2 != (Object)null) { flag = (int)val2.format == 4 || (int)val2.format == 5; Finish(val2, alreadyApplied: true); val.SetTexture("_BaseColorMap", (Texture)(object)val2); } Texture2D val3 = LoadImage("sam_" + set + "_n", linear: true); if ((Object)(object)val3 != (Object)null) { Color32[] pixels = val3.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { ref Color32 reference = ref pixels[i]; reference = new Color32(byte.MaxValue, pixels[i].g, byte.MaxValue, pixels[i].r); } Texture2D val4 = FromPixels(val3, pixels, "sam_" + set + "_n"); val.SetTexture("_NormalMap", (Texture)(object)val4); val.SetFloat("_NormalScale", 1f); val.EnableKeyword("_NORMALMAP"); val.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); } Texture2D val5 = LoadImage("sam_" + set + "_agm", linear: true); if ((Object)(object)val5 != (Object)null) { Color32[] pixels2 = val5.GetPixels32(); for (int j = 0; j < pixels2.Length; j++) { ref Color32 reference2 = ref pixels2[j]; reference2 = new Color32(pixels2[j].b, pixels2[j].r, (byte)0, pixels2[j].g); } Texture2D val6 = FromPixels(val5, pixels2, "sam_" + set + "_mask"); val.SetTexture("_MaskMap", (Texture)(object)val6); val.EnableKeyword("_MASKMAP"); val.SetFloat("_Metallic", 1f); val.SetFloat("_MetallicRemapMin", 0f); val.SetFloat("_MetallicRemapMax", 1f); val.SetFloat("_AORemapMin", 0f); val.SetFloat("_AORemapMax", 1f); val.SetFloat("_SmoothnessRemapMin", 0f); val.SetFloat("_SmoothnessRemapMax", Mathf.Clamp01(Plugin.MaxSmoothness.Value)); } else { val.SetFloat("_Metallic", 0f); val.SetFloat("_Smoothness", 0.3f); } if (flag) { val.SetFloat("_AlphaCutoffEnable", 1f); val.SetFloat("_AlphaCutoff", 0.33f); val.SetFloat("_DoubleSidedEnable", 1f); val.SetFloat("_CullMode", 0f); val.SetFloat("_CullModeForward", 0f); val.EnableKeyword("_ALPHATEST_ON"); val.EnableKeyword("_DOUBLESIDED_ON"); val.renderQueue = 2450; } try { Validate(val); } catch (Exception ex) { Plugin.Log.LogWarning((object)("HDRP material validation is unavailable (" + ex.GetType().Name + "); keywords set by hand.")); } return val; } private static void Validate(Material m) { HDMaterial.ValidateMaterial(m); } private static string FindImage(string name) { string text = Find(name + ".png"); if (text == null) { return Find(name + ".jpg"); } return text; } private static Texture2D LoadImage(string name, bool linear) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown string text = FindImage(name); if (text == null) { Plugin.Log.LogWarning((object)("Texture " + name + " is missing.")); return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear); if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text), false)) { Plugin.Log.LogWarning((object)("Texture " + text + " could not be decoded.")); Object.Destroy((Object)(object)val); return null; } ((Object)val).name = name; return val; } private static Texture2D FromPixels(Texture2D source, Color32[] pixels, string name) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown Texture2D val = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)4, true, true); ((Object)val).name = name; val.SetPixels32(pixels); val.Apply(true, false); Object.Destroy((Object)(object)source); Finish(val, alreadyApplied: false); return val; } private static void Finish(Texture2D tex, bool alreadyApplied) { ((Texture)tex).wrapMode = (TextureWrapMode)1; ((Texture)tex).filterMode = (FilterMode)2; ((Texture)tex).anisoLevel = 4; if (Plugin.CompressTextures.Value && ((Texture)tex).width % 4 == 0 && ((Texture)tex).height % 4 == 0) { tex.Compress(true); } tex.Apply(false, true); } private static string Find(string fileName) { string text = Path.Combine(Directory, fileName); if (File.Exists(text)) { return text; } string text2 = Path.Combine(Path.Combine(Directory, "sam"), fileName); if (File.Exists(text2)) { return text2; } string[] files = System.IO.Directory.GetFiles(Directory, fileName, SearchOption.AllDirectories); if (files.Length <= 0) { return null; } return files[0]; } private static string ReadString(BinaryReader r) { int count = r.ReadUInt16(); return Encoding.UTF8.GetString(r.ReadBytes(count)); } private static float[] ReadFloats(BinaryReader r, int count) { byte[] array = r.ReadBytes(count * 4); if (array.Length != count * 4) { throw new EndOfStreamException("model file is truncated"); } float[] array2 = new float[count]; Buffer.BlockCopy(array, 0, array2, 0, array.Length); return array2; } }