using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using Microsoft.CodeAnalysis; 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("RealisticNose")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("RealisticNose")] [assembly: AssemblyTitle("RealisticNose")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 RealisticNose { internal static class NoseSwapper { private static Mesh _source; private static readonly Dictionary Originals = new Dictionary(); private static readonly Dictionary Fitted = new Dictionary(); private static ManualLogSource Log => Plugin.Log; public static bool LoadModel() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_015b: 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) string text = ResolveModelPath(Plugin.ObjFile.Value); bool flag = default(bool); if (text == null) { ManualLogSource log = Log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(56, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("model '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Plugin.ObjFile.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' not found next to the plugin "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("or anywhere under "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Paths.PluginPath); } log.LogError(val); return false; } string error; Mesh val2 = ObjMesh.Load(text, Plugin.InvertFaces.Value, out error); if ((Object)(object)val2 == (Object)null) { ManualLogSource log2 = Log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(17, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("failed to read "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Path.GetFileName(text)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(error); } log2.LogError(val); return false; } ((Object)val2).hideFlags = (HideFlags)61; _source = val2; Fitted.Clear(); Bounds bounds = val2.bounds; ManualLogSource log3 = Log; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(31, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("loaded "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(Path.GetFileName(text)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(val2.vertexCount); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" verts, "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("size "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(Fmt(((Bounds)(ref bounds)).size)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", center "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(Fmt(((Bounds)(ref bounds)).center)); } log3.LogInfo(val3); return true; } private static string ResolveModelPath(string file) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown if (string.IsNullOrEmpty(file)) { return null; } if (Path.IsPathRooted(file)) { if (!File.Exists(file)) { return null; } return file; } string directoryName = Path.GetDirectoryName(typeof(NoseSwapper).Assembly.Location); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(directoryName, file); if (File.Exists(text)) { return text; } } try { string pluginPath = Paths.PluginPath; if (!string.IsNullOrEmpty(pluginPath) && Directory.Exists(pluginPath)) { string[] files = Directory.GetFiles(pluginPath, Path.GetFileName(file), SearchOption.AllDirectories); if (files.Length != 0) { return files[0]; } } } catch (Exception ex) { ManualLogSource log = Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(36, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("search under plugins folder failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogWarning(val); } return null; } public static void Apply(PlayerLips lips) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00ec: 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_00f5: Unknown result type (might be due to invalid IL or missing references) if (lips == null || (Object)(object)_source == (Object)null) { return; } List list = FindNoseRenderers(lips); if (list.Count == 0) { Log.LogWarning((object)"no nose renderer found on this PlayerLips"); return; } bool flag = default(bool); foreach (Renderer item in list) { Mesh mesh = GetMesh(item); if ((Object)(object)mesh == (Object)null) { continue; } int instanceID = ((Object)item).GetInstanceID(); if (!Originals.ContainsKey(instanceID)) { Originals[instanceID] = mesh; ManualLogSource log = Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(50, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("nose renderer '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)item).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': original mesh '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)mesh).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(mesh.vertexCount); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" verts, bounds "); Bounds bounds = mesh.bounds; ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Fmt(((Bounds)(ref bounds)).size)); } log.LogInfo(val); } SetMesh(item, BuildFitted(Originals[instanceID], item)); } } public static void RestoreAll() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown foreach (KeyValuePair original in Originals) { Renderer val = FindRendererById(original.Key); if ((Object)(object)val != (Object)null) { SetMesh(val, original.Value); } } ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(32, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("restored "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(Originals.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" original nose mesh(es)"); } log.LogInfo(val2); Originals.Clear(); Fitted.Clear(); } private static List FindNoseRenderers(PlayerLips lips) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown List list = new List(); bool flag = default(bool); try { Transform lipTransform = lips.lipTransform; if ((Object)(object)lipTransform != (Object)null) { Il2CppArrayBase componentsInChildren = ((Component)lipTransform).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { list.Add(componentsInChildren[i]); } } } } catch (Exception ex) { ManualLogSource log = Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("lipTransform lookup failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogWarning(val); } if (list.Count > 0) { return list; } try { Il2CppReferenceArray propertyBlockHelpers = lips.propertyBlockHelpers; if (propertyBlockHelpers != null) { for (int j = 0; j < ((Il2CppArrayBase)(object)propertyBlockHelpers).Length; j++) { PropertyBlockHelper val2 = ((Il2CppArrayBase)(object)propertyBlockHelpers)[j]; if ((Object)(object)val2 != (Object)null && (Object)(object)val2.targetRenderer != (Object)null) { list.Add(val2.targetRenderer); } } } } catch (Exception ex2) { ManualLogSource log2 = Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(36, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("propertyBlockHelpers lookup failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex2.Message); } log2.LogWarning(val); } return list; } private static Renderer FindRendererById(int id) { foreach (Renderer item in Resources.FindObjectsOfTypeAll()) { if ((Object)(object)item != (Object)null && ((Object)item).GetInstanceID() == id) { return item; } } return null; } private static Mesh GetMesh(Renderer r) { SkinnedMeshRenderer val = ((Il2CppObjectBase)r).TryCast(); if ((Object)(object)val != (Object)null) { return val.sharedMesh; } MeshFilter component = ((Component)r).GetComponent(); if (!((Object)(object)component != (Object)null)) { return null; } return component.sharedMesh; } private static void SetMesh(Renderer r, Mesh mesh) { if ((Object)(object)mesh == (Object)null) { return; } SkinnedMeshRenderer val = ((Il2CppObjectBase)r).TryCast(); if ((Object)(object)val != (Object)null) { val.sharedMesh = mesh; return; } MeshFilter component = ((Component)r).GetComponent(); if ((Object)(object)component != (Object)null) { component.sharedMesh = mesh; } } private static Mesh BuildFitted(Mesh original, Renderer renderer) { //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) //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_00c1: 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_00d8: 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_00f9: 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_0105: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_014b: 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_0163: 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_016f: 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_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0175: 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) //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_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: 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_01ac: Expected O, but got Unknown //IL_004c: 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_006b: 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_01d6: 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_0070: 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_0074: 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_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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_02c7: 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_0309: 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_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0331: 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) //IL_033a: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)original).GetInstanceID(); if (Fitted.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null) { return value; } Quaternion val = Quaternion.identity; Vector3 basePoint = Vector3.zero; float num = 1f; Bounds bounds; if (Plugin.AutoFit.Value) { Orient(original, out var dir, out basePoint, out var length); Vector3 val2 = ((Mathf.Abs(Vector3.Dot(dir, Vector3.up)) > 0.99f) ? Vector3.forward : Vector3.up); val = Quaternion.LookRotation(dir, val2); float num2 = length; bounds = _source.bounds; num = num2 / Mathf.Max(((Bounds)(ref bounds)).size.z, 0.0001f); } Vector3 val3 = new Vector3(Plugin.ScaleX.Value, Plugin.ScaleY.Value, Plugin.ScaleZ.Value) * (Plugin.Scale.Value * num); Quaternion val4 = val * Quaternion.Euler(Plugin.RotX.Value, Plugin.RotY.Value, Plugin.RotZ.Value); Vector3 val5 = basePoint + new Vector3(Plugin.OffsetX.Value, Plugin.OffsetY.Value, Plugin.OffsetZ.Value); Bounds bounds2 = _source.bounds; Matrix4x4 val6 = Matrix4x4.Translate(new Vector3(0f - ((Bounds)(ref bounds2)).center.x, 0f - ((Bounds)(ref bounds2)).center.y, 0f - ((Bounds)(ref bounds2)).min.z)); Matrix4x4 val7 = Matrix4x4.TRS(val5, val4, val3) * val6; Mesh val8 = new Mesh { name = ((Object)_source).name + "_fitted", hideFlags = (HideFlags)61 }; Il2CppStructArray vertices = _source.vertices; Il2CppStructArray val9 = new Il2CppStructArray((long)((Il2CppArrayBase)(object)vertices).Length); for (int i = 0; i < ((Il2CppArrayBase)(object)vertices).Length; i++) { ((Il2CppArrayBase)(object)val9)[i] = ((Matrix4x4)(ref val7)).MultiplyPoint3x4(((Il2CppArrayBase)(object)vertices)[i]); } val8.vertices = val9; Il2CppStructArray uv = _source.uv; if (uv != null && ((Il2CppArrayBase)(object)uv).Length == ((Il2CppArrayBase)(object)vertices).Length) { val8.uv = uv; } val8.triangles = _source.triangles; val8.RecalculateNormals(); val8.RecalculateTangents(); val8.RecalculateBounds(); if ((Object)(object)((Il2CppObjectBase)renderer).TryCast() != (Object)null) { Log.LogWarning((object)("'" + ((Object)renderer).name + "' is a SkinnedMeshRenderer; the replacement has no bone weights and may not deform correctly.")); } Fitted[instanceID] = val8; ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val10 = new BepInExInfoLogInterpolatedStringHandler(41, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("fitted '"); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted(((Object)original).name); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("': scale "); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted(Fmt(val3)); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(", base "); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted(Fmt(val5)); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("bounds "); bounds = val8.bounds; ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted(Fmt(((Bounds)(ref bounds)).size)); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" center "); bounds = val8.bounds; ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted(Fmt(((Bounds)(ref bounds)).center)); } log.LogInfo(val10); return val8; } private static void Orient(Mesh original, out Vector3 dir, out Vector3 basePoint, out float length) { //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_0011: 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_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_001f: 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_0050: 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_003f: 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_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_00d1: 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_00f3: 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_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0233: 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_022c: 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_023d: 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) //IL_0249: 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_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Expected O, but got Unknown Bounds bounds = original.bounds; Vector3 size = ((Bounds)(ref bounds)).size; int num = 2; if (size.x >= size.y && size.x >= size.z) { num = 0; } else if (size.y >= size.x && size.y >= size.z) { num = 1; } length = Comp(size, num); float num2 = Comp(((Bounds)(ref bounds)).center, num); float num3 = num2 - length * 0.5f; float num4 = num2 + length * 0.5f; int i = (num + 1) % 3; int i2 = (num + 2) % 3; float num5 = length * 0.2f; double num6 = 0.0; double num7 = 0.0; int num8 = 0; int num9 = 0; Il2CppStructArray vertices = original.vertices; for (int j = 0; j < ((Il2CppArrayBase)(object)vertices).Length; j++) { Vector3 v = ((Il2CppArrayBase)(object)vertices)[j]; float num10 = Comp(v, num); float num11 = Comp(v, i) - Comp(((Bounds)(ref bounds)).center, i); float num12 = Comp(v, i2) - Comp(((Bounds)(ref bounds)).center, i2); float num13 = Mathf.Sqrt(num11 * num11 + num12 * num12); if (num10 <= num3 + num5) { num6 += (double)num13; num8++; } else if (num10 >= num4 - num5) { num7 += (double)num13; num9++; } } bool flag; string text; if (num8 > 0 && num9 > 0) { float num14 = (float)(num6 / (double)num8); float num15 = (float)(num7 / (double)num9); flag = num15 < num14; text = $"vertex spread ({num14:0.####} lo vs {num15:0.####} hi)"; } else { flag = Mathf.Abs(num4) > Mathf.Abs(num3); text = $"pivot offset (origin {Mathf.Abs(num3):0.###} from lo, {Mathf.Abs(num4):0.###} from hi; " + $"mesh not readable={!original.isReadable})"; } if (Plugin.FlipDirection.Value) { flag = !flag; text += " [flipped by config]"; } Vector3 val = (Vector3)(num switch { 1 => Vector3.up, 0 => Vector3.right, _ => Vector3.forward, }); dir = (flag ? val : (-val)); basePoint = ((Bounds)(ref bounds)).center; basePoint = WithComp(basePoint, num, flag ? num3 : num4); ManualLogSource log = Log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(40, 5, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("oriented '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((Object)original).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("': axis "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted("XYZ"[num]); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", length "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(length, "0.###"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("tip at "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(flag ? "max" : "min"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" by "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(text); } log.LogInfo(val2); } private static float Comp(Vector3 v, int i) { //IL_0015: 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_0007: Unknown result type (might be due to invalid IL or missing references) return i switch { 1 => v.y, 0 => v.x, _ => v.z, }; } private static Vector3 WithComp(Vector3 v, int i, float value) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) switch (i) { case 0: v.x = value; break; case 1: v.y = value; break; default: v.z = value; break; } return v; } public static void Dump(PlayerLips lips) { //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_006b: 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_00ae: 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_0129: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown bool flag = default(bool); try { Log.LogInfo((object)"---- nose hierarchy dump ----"); Transform lipTransform = lips.lipTransform; if ((Object)(object)lipTransform == (Object)null) { Log.LogInfo((object)"lipTransform is null"); return; } ManualLogSource log = Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("lipTransform '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)lipTransform).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' localPos "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Fmt(lipTransform.localPosition)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("localScale "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Fmt(lipTransform.localScale)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" localEuler "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Fmt(lipTransform.localEulerAngles)); } log.LogInfo(val); Transform parent = lipTransform.parent; ManualLogSource log2 = Log; val = new BepInExInfoLogInterpolatedStringHandler(14, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("parent chain: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)(object)parent != (Object)null) ? PathOf(parent) : "(none)"); } log2.LogInfo(val); DumpTransform(lipTransform, 0); Il2CppReferenceArray propertyBlockHelpers = lips.propertyBlockHelpers; ManualLogSource log3 = Log; val = new BepInExInfoLogInterpolatedStringHandler(22, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("propertyBlockHelpers: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Il2CppArrayBase)(object)propertyBlockHelpers)?.Length ?? 0); } log3.LogInfo(val); if (propertyBlockHelpers != null) { for (int i = 0; i < ((Il2CppArrayBase)(object)propertyBlockHelpers).Length; i++) { PropertyBlockHelper obj = ((Il2CppArrayBase)(object)propertyBlockHelpers)[i]; Renderer val2 = ((obj != null) ? obj.targetRenderer : null); ManualLogSource log4 = Log; val = new BepInExInfoLogInterpolatedStringHandler(22, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ["); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(i); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] targetRenderer = "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)(object)val2 != (Object)null) ? PathOf(((Component)val2).transform) : "null"); } log4.LogInfo(val); } } Log.LogInfo((object)"---- end dump ----"); } catch (Exception ex) { ManualLogSource log5 = Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(13, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("dump failed: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex); } log5.LogError(val3); } } private static void DumpTransform(Transform t, int depth) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_0075: 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_007e: 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_0095: Unknown result type (might be due to invalid IL or missing references) string text = new string(' ', depth * 2); Renderer component = ((Component)t).GetComponent(); string text2 = ""; if ((Object)(object)component != (Object)null) { Mesh mesh = GetMesh(component); string name = ((MemberInfo)((Object)component).GetIl2CppType()).Name; object obj; if (!((Object)(object)mesh != (Object)null)) { obj = "none"; } else { object[] obj2 = new object[4] { ((Object)mesh).name, mesh.vertexCount, null, null }; Bounds bounds = mesh.bounds; obj2[2] = Fmt(((Bounds)(ref bounds)).size); bounds = mesh.bounds; obj2[3] = Fmt(((Bounds)(ref bounds)).center); obj = string.Format("'{0}' verts={1} bounds={2} center={3}", obj2); } text2 = " [" + name + "] mesh=" + (string?)obj; } ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(0, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)t).name); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text2); } log.LogInfo(val); for (int i = 0; i < t.childCount; i++) { DumpTransform(t.GetChild(i), depth + 1); } } private static string PathOf(Transform t) { string text = ((Object)t).name; Transform parent = t.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private static string Fmt(Vector3 v) { //IL_0005: 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_001b: Unknown result type (might be due to invalid IL or missing references) return $"({v.x:0.###}, {v.y:0.###}, {v.z:0.###})"; } } internal static class ObjMesh { private static readonly char[] Sep = new char[2] { ' ', '\t' }; public static Mesh Load(string path, bool invert, out string error) { //IL_01e4: 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_0201: Expected O, but got Unknown //IL_021b: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) error = null; try { List list = new List(); List list2 = new List(); Dictionary remap = new Dictionary(); List list3 = new List(); List list4 = new List(); List list5 = new List(); string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0 || text[0] == '#') { continue; } string[] array2 = text.Split(Sep, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 0) { continue; } switch (array2[0]) { case "v": if (array2.Length >= 4) { list.Add(new Vector3(0f - F(array2[1]), F(array2[2]), F(array2[3]))); } break; case "vt": if (array2.Length >= 3) { list2.Add(new Vector2(F(array2[1]), F(array2[2]))); } break; case "f": { if (array2.Length < 4) { break; } int[] array3 = new int[array2.Length - 1]; for (int j = 1; j < array2.Length; j++) { array3[j - 1] = Corner(array2[j], list, list2, remap, list3, list4); } for (int k = 1; k < array3.Length - 1; k++) { list5.Add(array3[0]); if (invert) { list5.Add(array3[k]); list5.Add(array3[k + 1]); } else { list5.Add(array3[k + 1]); list5.Add(array3[k]); } } break; } } } if (list3.Count == 0 || list5.Count == 0) { error = "no geometry found in " + Path.GetFileName(path); return null; } Mesh val = new Mesh { name = "RealisticNose_" + Path.GetFileNameWithoutExtension(path) }; Il2CppStructArray val2 = new Il2CppStructArray((long)list3.Count); for (int l = 0; l < list3.Count; l++) { ((Il2CppArrayBase)(object)val2)[l] = list3[l]; } val.vertices = val2; if (list4.Count == list3.Count) { Il2CppStructArray val3 = new Il2CppStructArray((long)list4.Count); for (int m = 0; m < list4.Count; m++) { ((Il2CppArrayBase)(object)val3)[m] = list4[m]; } val.uv = val3; } Il2CppStructArray val4 = new Il2CppStructArray((long)list5.Count); for (int n = 0; n < list5.Count; n++) { ((Il2CppArrayBase)(object)val4)[n] = list5[n]; } val.triangles = val4; val.RecalculateNormals(); val.RecalculateTangents(); val.RecalculateBounds(); return val; } catch (Exception ex) { error = ex.Message; return null; } } private static int Corner(string token, List positions, List texcoords, Dictionary remap, List verts, List uvs) { //IL_0058: 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_0071: 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) if (remap.TryGetValue(token, out var value)) { return value; } string[] array = token.Split('/'); int num = Index(array[0], positions.Count); int num2 = ((array.Length > 1 && array[1].Length > 0) ? Index(array[1], texcoords.Count) : (-1)); verts.Add((num >= 0) ? positions[num] : Vector3.zero); uvs.Add((num2 >= 0) ? texcoords[num2] : Vector2.zero); return remap[token] = verts.Count - 1; } private static int Index(string s, int count) { if (!int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return -1; } if (result > 0) { return result - 1; } if (result < 0) { return count + result; } return -1; } private static float F(string s) { if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return 0f; } return result; } } [BepInPlugin("deck.bigwalk.realisticnose", "Binus", "1.0.1")] public class Plugin : BasePlugin { public const string Guid = "deck.bigwalk.realisticnose"; public static ManualLogSource Log; public static ConfigEntry Enabled; public static ConfigEntry ObjFile; public static ConfigEntry AutoFit; public static ConfigEntry FlipDirection; public static ConfigEntry InvertFaces; public static ConfigEntry Scale; public static ConfigEntry ScaleX; public static ConfigEntry ScaleY; public static ConfigEntry ScaleZ; public static ConfigEntry RotX; public static ConfigEntry RotY; public static ConfigEntry RotZ; public static ConfigEntry OffsetX; public static ConfigEntry OffsetY; public static ConfigEntry OffsetZ; public static ConfigEntry DumpHierarchy; public override void Load() { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: 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 Log = ((BasePlugin)this).Log; Enabled = ((BasePlugin)this).Config.Bind("General", "Enabled", true, "Replace the character's nose mesh."); ObjFile = ((BasePlugin)this).Config.Bind("General", "ObjFile", "binus2.obj", "Wavefront .obj to load. Looked for next to this plugin, then anywhere under BepInEx/plugins; an absolute path also works. Drop in your own model here."); AutoFit = ((BasePlugin)this).Config.Bind("Fit", "AutoFit", true, "Scale the model to match the size of the nose mesh it replaces. Turn off to size it purely with the Scale values below."); InvertFaces = ((BasePlugin)this).Config.Bind("Model", "InvertFaces", false, "Reverse triangle winding. Turn on if the model renders inside out - you see through the near surface and only the far side is visible."); FlipDirection = ((BasePlugin)this).Config.Bind("Fit", "FlipDirection", true, "Turn off if the nose points into the head instead of out of the face. Flips it end for end and re-anchors it, which RotationY=180 alone would not do. On by default because Big Walk's nose mesh has its pivot at the tip."); Scale = ((BasePlugin)this).Config.Bind("Fit", "Scale", 1f, new ConfigDescription("Overall size multiplier, applied on top of AutoFit.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 20f), Array.Empty())); ScaleX = ((BasePlugin)this).Config.Bind("Fit", "ScaleX", 1f, "Per-axis width multiplier."); ScaleY = ((BasePlugin)this).Config.Bind("Fit", "ScaleY", 1f, "Per-axis height multiplier."); ScaleZ = ((BasePlugin)this).Config.Bind("Fit", "ScaleZ", 1f, "Per-axis length multiplier."); RotX = ((BasePlugin)this).Config.Bind("Fit", "RotationX", 0f, "Degrees, relative to the fitted orientation. The model should point along +Z."); RotY = ((BasePlugin)this).Config.Bind("Fit", "RotationY", 0f, "Degrees."); RotZ = ((BasePlugin)this).Config.Bind("Fit", "RotationZ", -90f, "Degrees of roll about the nose's own axis. -90 by default because Big Walk's nose bone does not use +Y as up; change this if your model sits rolled."); OffsetX = ((BasePlugin)this).Config.Bind("Fit", "OffsetX", 0f, "Local-space nudge."); OffsetY = ((BasePlugin)this).Config.Bind("Fit", "OffsetY", 0f, "Local-space nudge."); OffsetZ = ((BasePlugin)this).Config.Bind("Fit", "OffsetZ", 0f, "Local-space nudge."); DumpHierarchy = ((BasePlugin)this).Config.Bind("Debug", "DumpHierarchy", false, "Log the nose object hierarchy the first time a character spawns. Turn on and include BepInEx/LogOutput.log when reporting a problem."); Harmony.CreateAndPatchAll(typeof(NosePatches), "deck.bigwalk.realisticnose"); ClassInjector.RegisterTypeInIl2Cpp(); GameObject val = new GameObject("BinusRuntime") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)val); val.AddComponent(); Log.LogInfo((object)"Binus loaded"); } } [HarmonyPatch] internal static class NosePatches { private static bool _dumped; [HarmonyPostfix] [HarmonyPatch(typeof(PlayerLips), "Initialize")] private static void OnLipsInitialized(PlayerLips __instance) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown if (!Plugin.Enabled.Value) { return; } try { if (Plugin.DumpHierarchy.Value && !_dumped) { _dumped = true; NoseSwapper.Dump(__instance); } NoseRuntime.Queue(__instance); } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(23, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("nose init hook failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } log.LogError(val); } } } public class NoseRuntime : MonoBehaviour { private static readonly List Pending = new List(); private bool _loaded; private float _nextSweep; public NoseRuntime(IntPtr ptr) : base(ptr) { } public static void Queue(PlayerLips lips) { lock (Pending) { Pending.Add(lips); } } private void Update() { if (!_loaded) { _loaded = true; NoseSwapper.LoadModel(); } if (Pending.Count > 0) { PlayerLips[] array; lock (Pending) { array = Pending.ToArray(); Pending.Clear(); } PlayerLips[] array2 = array; for (int i = 0; i < array2.Length; i++) { SafeApply(array2[i]); } } if (Time.unscaledTime >= _nextSweep) { _nextSweep = Time.unscaledTime + 3f; SweepNow(); } } private static void SweepNow() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown if (!Plugin.Enabled.Value) { return; } try { List allPlayerCharacters = PlayerCharacter.allPlayerCharacters; if (allPlayerCharacters == null) { return; } for (int i = 0; i < allPlayerCharacters.Count; i++) { PlayerCharacter val = allPlayerCharacters[i]; if ((Object)(object)val != (Object)null && val.lips != null) { SafeApply(val.lips); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("nose sweep failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex); } log.LogError(val2); } } private static void SafeApply(PlayerLips lips) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown try { NoseSwapper.Apply(lips); } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("nose swap failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } log.LogError(val); } } } }