using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; 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 System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("ScallionMiku")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("ScallionMiku")] [assembly: AssemblyTitle("ScallionMiku")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class IgnoresAccessChecksToAttribute : Attribute { private readonly string _assemblyName; public string AssemblyName => _assemblyName; public IgnoresAccessChecksToAttribute(string assemblyName) { _assemblyName = assemblyName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] public sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte value) { NullableFlags = new byte[1] { value }; } public NullableAttribute(byte[] value) { NullableFlags = value; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] public sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte value) { Flag = value; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int version) { Version = version; } } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class BepInAutoPluginAttribute : Attribute { private string _guid; private string _name; private string _version; public string GUID { get { return _guid; } set { _guid = value; } } public string Name { get { return _name; } set { _name = value; } } public string Version { get { return _version; } set { _version = value; } } public BepInAutoPluginAttribute(string guid = null, string name = null, string version = null) { _guid = guid; _name = name; _version = version; } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class PatcherAutoPluginAttribute : Attribute { private string _guid; private string _name; private string _version; public string GUID { get { return _guid; } set { _guid = value; } } public string Name { get { return _name; } set { _name = value; } } public string Version { get { return _version; } set { _version = value; } } public PatcherAutoPluginAttribute(string guid = null, string name = null, string version = null) { _guid = guid; _name = name; _version = version; } } } namespace ScallionMiku { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.github.Thanks.ScallionMiku", "ScallionMiku", "1.0.3")] public class Plugin : BaseUnityPlugin { private enum ConfigKey { ModEnabled, WorldScale, BackpackScale, PositionOffsetX, PositionOffsetY, PositionOffsetZ, FaceExpression } private enum FaceExpressionOption { None, Smile, Blink, Wink, WinkRight, Wink2, Wink2Right, A, I, U, E, O, A2, MouthCornerUp, MouthCornerDown, Hau } [CompilerGenerated] private sealed class d__182 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Transform <>2__current; private int <>l__initialThreadId; private object menuInstance; public object <>3__menuInstance; private Type menuType; public Type <>3__menuType; Transform IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__182(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { object? obj2; Transform val2; switch (<>1__state) { default: return false; case 0: { <>1__state = -1; object obj = menuInstance; Component val = (Component)((obj is Component) ? obj : null); if (val != null) { <>2__current = val.transform; <>1__state = 1; return true; } goto IL_004d; } case 1: <>1__state = -1; goto IL_004d; case 2: { <>1__state = -1; break; } IL_004d: obj2 = menuType?.GetProperty("Content", InstanceFlags)?.GetValue(menuInstance); val2 = (Transform)((obj2 is Transform) ? obj2 : null); if (val2 != null) { <>2__current = val2; <>1__state = 2; return true; } break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__182 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__182(0); } d__.menuInstance = <>3__menuInstance; d__.menuType = <>3__menuType; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__181 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Transform <>2__current; private int <>l__initialThreadId; private object menuInstance; public object <>3__menuInstance; private Type menuType; public Type <>3__menuType; private HashSet 5__2; private IEnumerator <>7__wrap2; Transform IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__181(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = new HashSet(); <>7__wrap2 = EnumerateCandidateTransforms(menuInstance, menuType).GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (<>7__wrap2.MoveNext()) { Transform current = <>7__wrap2.Current; if ((Object)(object)current != (Object)null && 5__2.Add(((Object)current).GetInstanceID())) { <>2__current = current; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap2 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap2 != null) { <>7__wrap2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__181 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__181(0); } d__.menuInstance = <>3__menuInstance; d__.menuType = <>3__menuType; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__161 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private ConfigDefinition <>2__current; private int <>l__initialThreadId; private ConfigKey configKey; public ConfigKey <>3__configKey; private string 5__2; private string 5__3; private string 5__4; private string 5__5; ConfigDefinition IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__161(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = GetConfigKeyName(configKey); 5__3 = GetKeyName(configKey, isChineseLanguage: true); 5__4 = GetConfigSectionName(configKey); 5__5 = GetSectionName(configKey, isChineseLanguage: true); <>2__current = new ConfigDefinition(5__4, 5__2); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = new ConfigDefinition(5__4, 5__3); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = new ConfigDefinition(5__5, 5__2); <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = new ConfigDefinition(5__5, 5__3); <>1__state = 4; return true; case 4: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__161 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__161(0); } d__.configKey = <>3__configKey; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const float LiveConfigRefreshInterval = 0.03f; private const int SimplifiedChineseLanguageIndex = 9; private const string ModConfigPluginGuid = "com.github.PEAKModding.PEAKLib.ModConfig"; private const float ModConfigUiLocalizationIntervalSeconds = 0.25f; private static readonly string[] LegacyPluginIds = new string[2] { "com.github.Thanks.MikuBongFix", "com.github.FelineEntity.MikuBongFix" }; private const string BundleFileName = "ScallionMiku"; private const string ExternalIconFileName = "ScallionMikuUI.png"; private const string PrefabAssetPath = "assets/葱音未来_by_翼月生/scallionmiku.prefab"; private const string MaterialAssetPath = "assets/葱音未来_by_翼月生/materials/scallionmiku-8.shintai.mat"; private const string IconTextureAssetPath = "assets/葱音未来_by_翼月生/textures/身体.png"; private const string MainTextureAssetPath = "assets/葱音未来_by_翼月生/textures/身体.png"; private const string ConfigSection = "Main"; private const string LocalizedConfigSection = "主要"; private const string WorldScaleConfigKey = "Fufu Size In World"; private const string BackpackModelScaleConfigKey = "Backpack Model Scale"; private const string LegacyFufuBackpackScaleConfigKey = "Fufu Size In Backpack"; private const string LegacyMikuBackpackScaleConfigKey = "Miku Size In Backpack"; private const float WorldMinScaleMultiplier = 0.4f; private const float WorldMaxScaleMultiplier = 1.1f; private const float BackpackMinScaleMultiplier = 0.2f; private const float BackpackMaxScaleMultiplier = 1f; private const float PositionOffsetMin = -2f; private const float PositionOffsetMax = 2f; private const float DefaultWorldScaleMultiplier = 0.9f; private const float DefaultBackpackScaleMultiplier = 0.4f; private const string ExpressionConfigKey = "Face Expression"; private const string LocalizedExpressionConfigKey = "表情"; private const string DefaultExpressionName = "None"; private const float DefaultExpressionWeight = 1f; private const float RuntimeScaleAdjustment = 0.78f; private const float BaseScaleMultiplier = 1.5f; private const float BundledBaseScaleMin = 0.04f; private const float BundledBaseScaleMax = 1.2f; private const FaceExpressionOption DefaultExpressionOption = FaceExpressionOption.None; private static readonly Vector3 DefaultBundledReplacementBaseScale = new Vector3(0.52f, 0.52f, 0.52f); private static readonly Vector3 RuntimeReferenceVisibleSizeAtBaseScale = new Vector3(1.5852638f, 1.2168914f, 0.8999324f); private static readonly Vector3 DefaultPositionOffset = Vector3.zero; private static readonly string[] PreferredTextureProps = new string[2] { "_BaseMap", "_MainTex" }; private static readonly string[] PrefabNameHints = new string[3] { "scallionmiku", "miku", "scallion" }; private static readonly string[] MaterialNameHints = new string[3] { "scallionmiku-8.shintai", "shintai", "miku" }; private static readonly string[] IconTextureNameHints = new string[4] { "身体", "shintai", "miku", "scallionmiku" }; private static readonly string[] MainTextureNameHints = new string[5] { "身体", "shintai", "miku", "scallionmiku", "albedo" }; private static readonly Color MikuStyleTint = new Color(0.98f, 1f, 1f, 1f); private static ConfigEntry _modEnabled; private static ConfigEntry _worldScaleMultiplier; private static ConfigEntry _backpackScaleMultiplier; private static ConfigEntry _positionOffsetX; private static ConfigEntry _positionOffsetY; private static ConfigEntry _positionOffsetZ; private static ConfigEntry _expressionOption; private bool _liveConfigStateInitialized; private bool _lastObservedModEnabled; private float _lastObservedWorldScale; private float _lastObservedBackpackScale; private Vector3 _lastObservedPositionOffset; private string _lastObservedExpressionName; private bool _pendingLiveConfigRefresh; private float _nextLiveConfigRefreshTime; private bool _liveConfigEventsBound; private bool _lastDetectedChineseLanguage; private bool _isRefreshingLanguage; private bool _pendingConfigFileLocalizationRefresh; private bool _pendingConfigFileLocalizationSave; private float _nextModConfigUiLocalizationTime; private static readonly BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly PropertyInfo ConfigFileEntriesProperty = typeof(ConfigFile).GetProperty("Entries", InstanceFlags); private static ManualLogSource _log; private static AssetBundle _bundle; private static GameObject _mochiPrefab; private static Material _mochiMaterial; private static Material _runtimeMikuMaterial; private static Texture2D _mochiTexture; private static Texture2D _mikuMainTexture; private static Vector3 _bundledReplacementBaseScale = DefaultBundledReplacementBaseScale; private static RuntimeReplacementModel _runtimeReplacementModel; public const string Name = "ScallionMiku"; public const string Id = "com.github.Thanks.ScallionMiku"; public const string Version = "1.0.3"; internal static Harmony Harmony = new Harmony("com.github.Thanks.ScallionMiku"); internal static ManualLogSource Log { get { return _log; } private set { _log = value; } } internal static AssetBundle Bundle { get { return _bundle; } private set { _bundle = value; } } internal static GameObject MochiPrefab { get { return _mochiPrefab; } private set { _mochiPrefab = value; } } internal static Material MochiMaterial { get { return _mochiMaterial; } private set { _mochiMaterial = value; } } internal static Material RuntimeMikuMaterial { get { return _runtimeMikuMaterial; } private set { _runtimeMikuMaterial = value; } } internal static Texture2D MochiTexture { get { return _mochiTexture; } private set { _mochiTexture = value; } } internal static Texture2D MikuMainTexture { get { return _mikuMainTexture; } private set { _mikuMainTexture = value; } } internal static RuntimeReplacementModel RuntimeReplacementModel { get { return _runtimeReplacementModel; } private set { _runtimeReplacementModel = value; } } internal static bool ModEnabled { get { if (_modEnabled != null) { return _modEnabled.Value; } return true; } } internal static bool KeepOriginalRendererRefs => RuntimeReplacementModel == null; internal static bool EnableVisibilityGuard => true; internal static float WorldScaleMultiplier { get { if (_worldScaleMultiplier != null) { return Mathf.Clamp(_worldScaleMultiplier.Value, 0.4f, 1.1f); } return 0.9f; } } internal static float DefaultWorldScaleSetting => 0.9f; internal static float BackpackScaleMultiplier { get { if (_backpackScaleMultiplier != null) { return Mathf.Clamp(_backpackScaleMultiplier.Value, 0.2f, 1f); } return 0.4f; } } internal static float DefaultBackpackScaleSetting => 0.4f; internal static Vector3 ReplacementBaseScale { get { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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) if (RuntimeReplacementModel == null) { return _bundledReplacementBaseScale * 0.78f * 1.5f; } return RuntimeReplacementModel.RecommendedBaseScale * 0.78f * 1.5f; } } internal static Vector3 PositionOffset => new Vector3((_positionOffsetX == null) ? DefaultPositionOffset.x : Mathf.Clamp(_positionOffsetX.Value, -2f, 2f), (_positionOffsetY == null) ? DefaultPositionOffset.y : Mathf.Clamp(_positionOffsetY.Value, -2f, 2f), (_positionOffsetZ == null) ? DefaultPositionOffset.z : Mathf.Clamp(_positionOffsetZ.Value, -2f, 2f)); internal static string ExpressionName { get { string text = ((_expressionOption == null) ? "None" : GetExpressionName(_expressionOption.Value)); if (!string.IsNullOrEmpty(text)) { return text; } return "None"; } } internal static float ExpressionWeight => 1f; internal static string ReplacementDisplayName => "Miku"; internal static int ReplacementRefreshRevision { get; private set; } = 1; internal static string directory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; _lastDetectedChineseLanguage = DetectChineseLanguage(); MigrateLegacyConfigIfNeeded(); InitializeConfig(_lastDetectedChineseLanguage); NormalizeMigratedScaleConfigIfNeeded(); MarkConfigFileLocalizationDirty(saveConfigFile: true); LoadAssets(); try { Harmony.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception ex) { Log.LogError((object)("Failed to apply Harmony patches: " + ex)); } BindLiveConfigEvents(); CaptureLiveConfigState(); Log.LogInfo((object)("[ScallionMiku] Config language: " + BuildLanguageDetectionSummary(_lastDetectedChineseLanguage))); } private void Update() { HandleLanguageChangeIfNeeded(); HandlePendingConfigFileLocalizationRefresh(); TryLocalizeVisibleModConfigUiThrottled(); if (HasLiveConfigStateChanged()) { CaptureLiveConfigState(); _pendingLiveConfigRefresh = true; } if (_pendingLiveConfigRefresh && !(Time.realtimeSinceStartup < _nextLiveConfigRefreshTime)) { RefreshReplacementInstancesNow(); } } private bool HasLiveConfigStateChanged() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!_liveConfigStateInitialized) { return true; } if (_lastObservedModEnabled != ModEnabled) { return true; } if (!Mathf.Approximately(_lastObservedWorldScale, WorldScaleMultiplier)) { return true; } if (!Mathf.Approximately(_lastObservedBackpackScale, BackpackScaleMultiplier)) { return true; } if (_lastObservedPositionOffset != PositionOffset) { return true; } return !string.Equals(_lastObservedExpressionName, ExpressionName, StringComparison.Ordinal); } private void CaptureLiveConfigState() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) _lastObservedModEnabled = ModEnabled; _lastObservedWorldScale = WorldScaleMultiplier; _lastObservedBackpackScale = BackpackScaleMultiplier; _lastObservedPositionOffset = PositionOffset; _lastObservedExpressionName = ExpressionName; _liveConfigStateInitialized = true; } private void BindLiveConfigEvents() { if (!_liveConfigEventsBound) { BindLiveConfigEvent(_modEnabled); BindLiveConfigEvent(_worldScaleMultiplier); BindLiveConfigEvent(_backpackScaleMultiplier); BindLiveConfigEvent(_positionOffsetX); BindLiveConfigEvent(_positionOffsetY); BindLiveConfigEvent(_positionOffsetZ); BindLiveConfigEvent(_expressionOption); _liveConfigEventsBound = true; } } private void BindLiveConfigEvent(ConfigEntry entry) { if (entry != null) { entry.SettingChanged -= OnLiveConfigSettingChanged; entry.SettingChanged += OnLiveConfigSettingChanged; } } private void OnLiveConfigSettingChanged(object sender, EventArgs args) { MarkConfigFileLocalizationDirty(saveConfigFile: false); CaptureLiveConfigState(); if (Time.realtimeSinceStartup >= _nextLiveConfigRefreshTime) { RefreshReplacementInstancesNow(); } else { _pendingLiveConfigRefresh = true; } } private void RefreshReplacementInstancesNow() { _pendingLiveConfigRefresh = false; _nextLiveConfigRefreshTime = Time.realtimeSinceStartup + 0.03f; ReplacementRefreshRevision = ((ReplacementRefreshRevision == int.MaxValue) ? 1 : (ReplacementRefreshRevision + 1)); Patch_AskRoutine.HandleModConfigStateChanged(); ItemPatch.RefreshAllReplacementInstances(); } private void MigrateLegacyConfigIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (string.IsNullOrEmpty(configFilePath) || File.Exists(configFilePath) || LegacyPluginIds == null) { return; } for (int i = 0; i < LegacyPluginIds.Length; i++) { string text = LegacyPluginIds[i]; if (!string.IsNullOrEmpty(text)) { string text2 = Path.Combine(Paths.ConfigPath, text + ".cfg"); if (File.Exists(text2)) { File.Copy(text2, configFilePath, overwrite: false); ((BaseUnityPlugin)this).Config.Reload(); VerboseLog("Migrated legacy config to: " + configFilePath); break; } } } } catch (Exception ex) { Log.LogWarning((object)("Failed to migrate legacy config file: " + ex.Message)); } } private void InitializeConfig(bool isChineseLanguage) { RemoveConfigVersionSettingIfNeeded(); NormalizeLegacyExpressionConfigIfNeeded(); _modEnabled = BindEntry(ConfigKey.ModEnabled, defaultValue: true, isChineseLanguage); _worldScaleMultiplier = BindEntry(ConfigKey.WorldScale, 0.9f, isChineseLanguage); _backpackScaleMultiplier = BindEntry(ConfigKey.BackpackScale, 0.4f, isChineseLanguage); _positionOffsetX = BindEntry(ConfigKey.PositionOffsetX, DefaultPositionOffset.x, isChineseLanguage); _positionOffsetY = BindEntry(ConfigKey.PositionOffsetY, DefaultPositionOffset.y, isChineseLanguage); _positionOffsetZ = BindEntry(ConfigKey.PositionOffsetZ, DefaultPositionOffset.z, isChineseLanguage); _expressionOption = BindEntry(ConfigKey.FaceExpression, FaceExpressionOption.None, isChineseLanguage); MigrateLocalizedConfigEntries(); } private ConfigEntry BindEntry(ConfigKey configKey, T defaultValue, bool isChineseLanguage) { return ((BaseUnityPlugin)this).Config.Bind(GetSectionName(configKey, isChineseLanguage), GetKeyName(configKey, isChineseLanguage), defaultValue, CreateConfigDescription(configKey, isChineseLanguage)); } private ConfigDescription CreateConfigDescription(ConfigKey configKey, bool isChineseLanguage) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown string localizedDescription = GetLocalizedDescription(configKey, isChineseLanguage); switch (configKey) { case ConfigKey.WorldScale: return new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0.4f, 1.1f), Array.Empty()); case ConfigKey.BackpackScale: return new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 1f), Array.Empty()); case ConfigKey.PositionOffsetX: case ConfigKey.PositionOffsetY: case ConfigKey.PositionOffsetZ: return new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(-2f, 2f), Array.Empty()); default: return new ConfigDescription(localizedDescription, (AcceptableValueBase)null, Array.Empty()); } } private void RemoveConfigVersionSettingIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (string.IsNullOrEmpty(configFilePath) || !File.Exists(configFilePath)) { return; } string[] array = File.ReadAllLines(configFilePath); List list = new List(array.Length); bool flag = false; bool flag2 = false; for (int i = 0; i < array.Length; i++) { string text = array[i] ?? string.Empty; string text2 = text.Trim(); if (text2.StartsWith("[", StringComparison.Ordinal) && text2.EndsWith("]", StringComparison.Ordinal)) { flag2 = string.Equals(text2.Substring(1, text2.Length - 2).Trim(), "Internal", StringComparison.OrdinalIgnoreCase); if (flag2) { flag = true; continue; } } if (flag2) { flag = true; } else { list.Add(text); } } if (flag) { File.WriteAllLines(configFilePath, list.ToArray()); ((BaseUnityPlugin)this).Config.Reload(); VerboseLog("Removed obsolete Internal/Config Version config entry."); } } catch (Exception ex) { Log.LogWarning((object)("Failed to remove obsolete Config Version entry: " + ex.Message)); } } private void NormalizeLegacyExpressionConfigIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (string.IsNullOrEmpty(configFilePath) || !File.Exists(configFilePath)) { return; } string[] array = File.ReadAllLines(configFilePath); bool flag = false; for (int i = 0; i < array.Length; i++) { if (TrySplitConfigSettingLine(array[i], out var leading, out var keyName, out var separatorAndValue) && IsConfigKeyName(keyName, ConfigKey.FaceExpression)) { int num = separatorAndValue.IndexOf('='); string obj = ((num >= 0) ? separatorAndValue.Substring(num + 1).Trim() : string.Empty); if (!TryParseExpressionOption(obj, out var option)) { option = FaceExpressionOption.None; } string text = option.ToString(); if (!string.Equals(obj, text, StringComparison.Ordinal)) { string keyName2 = GetKeyName(ConfigKey.FaceExpression, _lastDetectedChineseLanguage); array[i] = leading + keyName2 + " = " + text; flag = true; } } } if (flag) { File.WriteAllLines(configFilePath, array); ((BaseUnityPlugin)this).Config.Reload(); VerboseLog("Migrated Face Expression config from PMX morph text to enum value for PEAKLib.ModConfig compatibility."); } } catch (Exception ex) { Log.LogWarning((object)("Failed to normalize Face Expression config value: " + ex.Message)); } } private static bool TryParseExpressionOption(string rawValue, out FaceExpressionOption option) { option = FaceExpressionOption.None; if (string.IsNullOrEmpty(rawValue)) { return false; } string text = rawValue.Trim().Trim(new char[1] { '"' }); if (Enum.TryParse(text, ignoreCase: true, out option) && Enum.IsDefined(typeof(FaceExpressionOption), option)) { return true; } for (int i = 0; i <= 15; i++) { FaceExpressionOption faceExpressionOption = (FaceExpressionOption)i; if (string.Equals(text, GetExpressionName(faceExpressionOption), StringComparison.Ordinal)) { option = faceExpressionOption; return true; } } return false; } private static string GetExpressionName(FaceExpressionOption option) { return option switch { FaceExpressionOption.Smile => "笑い", FaceExpressionOption.Blink => "まばたき", FaceExpressionOption.Wink => "ウィンク", FaceExpressionOption.WinkRight => "ウィンク右", FaceExpressionOption.Wink2 => "ウィンク2", FaceExpressionOption.Wink2Right => "ウィンク2右", FaceExpressionOption.A => "あ", FaceExpressionOption.I => "い", FaceExpressionOption.U => "う", FaceExpressionOption.E => "え", FaceExpressionOption.O => "お", FaceExpressionOption.A2 => "あ2", FaceExpressionOption.MouthCornerUp => "口角上げ", FaceExpressionOption.MouthCornerDown => "口角下げ", FaceExpressionOption.Hau => "はぅ", _ => "None", }; } private void MarkConfigFileLocalizationDirty(bool saveConfigFile) { _pendingConfigFileLocalizationRefresh = true; _pendingConfigFileLocalizationSave |= saveConfigFile; } private void HandlePendingConfigFileLocalizationRefresh() { if (_pendingConfigFileLocalizationRefresh && !_isRefreshingLanguage) { bool pendingConfigFileLocalizationSave = _pendingConfigFileLocalizationSave; _pendingConfigFileLocalizationRefresh = false; _pendingConfigFileLocalizationSave = false; TryRefreshLocalizedConfigFile(_lastDetectedChineseLanguage, pendingConfigFileLocalizationSave); } } private void HandleLanguageChangeIfNeeded() { bool flag = DetectChineseLanguage(); if (flag != _lastDetectedChineseLanguage) { ReinitializeLocalizedConfig(flag); } } private void ReinitializeLocalizedConfig(bool isChineseLanguage) { if (_isRefreshingLanguage) { return; } _isRefreshingLanguage = true; try { _lastDetectedChineseLanguage = isChineseLanguage; ApplyLocalizedConfigMetadata(isChineseLanguage); MarkConfigFileLocalizationDirty(saveConfigFile: true); Log.LogInfo((object)("[ScallionMiku] Config language changed: " + (isChineseLanguage ? "Chinese" : "English"))); } catch (Exception ex) { Log.LogWarning((object)("[ScallionMiku] Failed to update config language: " + ex.Message)); } finally { _isRefreshingLanguage = false; } } private void ApplyLocalizedConfigMetadata(bool isChineseLanguage) { try { ConfigEntryBase[] configEntriesSnapshot = GetConfigEntriesSnapshot(((BaseUnityPlugin)this).Config); foreach (ConfigEntryBase val in configEntriesSnapshot) { if (val != null && !(val.Definition == (ConfigDefinition)null) && val.Description != null && TryGetConfigKey(val.Definition.Key, out var configKey)) { string localizedDescription = GetLocalizedDescription(configKey, isChineseLanguage); if (!string.IsNullOrWhiteSpace(localizedDescription)) { SetPrivateField(val.Description, "k__BackingField", localizedDescription); } } } TryLocalizeVisibleModConfigUi(); } catch (Exception ex) { Log.LogWarning((object)("[ScallionMiku] Failed to apply localized config metadata: " + ex.Message)); } } private static ConfigEntryBase[] GetConfigEntriesSnapshot(ConfigFile configFile) { if (configFile == null || !(ConfigFileEntriesProperty != null) || !(ConfigFileEntriesProperty.GetValue(configFile) is IDictionary dictionary) || dictionary.Count == 0) { return Array.Empty(); } List list = new List(); foreach (DictionaryEntry item in dictionary) { object? value = item.Value; ConfigEntryBase val = (ConfigEntryBase)((value is ConfigEntryBase) ? value : null); if (val != null) { list.Add(val); } } return list.ToArray(); } private static void SetPrivateField(object target, string fieldName, object value) { if (target != null && !string.IsNullOrWhiteSpace(fieldName)) { target.GetType().GetField(fieldName, InstanceFlags)?.SetValue(target, value); } } private void TryRefreshLocalizedConfigFile(bool isChineseLanguage, bool saveConfigFile) { try { if (((BaseUnityPlugin)this).Config != null && !string.IsNullOrWhiteSpace(((BaseUnityPlugin)this).Config.ConfigFilePath)) { if (saveConfigFile) { ((BaseUnityPlugin)this).Config.Save(); } RewriteConfigFileLocalization(((BaseUnityPlugin)this).Config.ConfigFilePath, isChineseLanguage); } } catch (Exception ex) { Log.LogWarning((object)("[ScallionMiku] Failed to refresh localized config file: " + ex.Message)); } } private static void RewriteConfigFileLocalization(string configFilePath, bool isChineseLanguage) { if (!string.IsNullOrWhiteSpace(configFilePath) && File.Exists(configFilePath)) { string[] array = File.ReadAllLines(configFilePath); string[] array2 = new string[array.Length]; bool flag = false; for (int i = 0; i < array.Length; i++) { string text = array[i] ?? string.Empty; flag |= !string.Equals(text, array2[i] = RewriteConfigFileLine(text, isChineseLanguage), StringComparison.Ordinal); } if (flag) { File.WriteAllLines(configFilePath, array2); } } } private static string RewriteConfigFileLine(string line, bool isChineseLanguage) { if (string.IsNullOrWhiteSpace(line)) { return line ?? string.Empty; } string text = line.Trim(); if (text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal)) { if (!TryGetLocalizedSectionName(text.Substring(1, text.Length - 2).Trim(), isChineseLanguage, out var localizedSectionName)) { return line; } int num = line.IndexOf('['); int num2 = line.LastIndexOf(']'); if (num < 0 || num2 < num) { return line; } return line.Substring(0, num + 1) + localizedSectionName + line.Substring(num2); } if (!TrySplitConfigSettingLine(line, out var leading, out var keyName, out var separatorAndValue)) { return line; } if (!TryGetConfigKey(keyName, out var configKey)) { return line; } return leading + GetKeyName(configKey, isChineseLanguage) + separatorAndValue; } private static bool TrySplitConfigSettingLine(string line, out string leading, out string keyName, out string separatorAndValue) { leading = string.Empty; keyName = string.Empty; separatorAndValue = string.Empty; if (string.IsNullOrWhiteSpace(line)) { return false; } string text = line.TrimStart(Array.Empty()); if (text.StartsWith("#", StringComparison.Ordinal) || text.StartsWith(";", StringComparison.Ordinal)) { return false; } int num = line.IndexOf('='); if (num <= 0) { return false; } int i; for (i = 0; i < num && char.IsWhiteSpace(line[i]); i++) { } int num2 = num - 1; while (num2 >= i && char.IsWhiteSpace(line[num2])) { num2--; } if (num2 < i) { return false; } leading = line.Substring(0, i); keyName = line.Substring(i, num2 - i + 1); separatorAndValue = line.Substring(num2 + 1); return true; } private static bool TryGetLocalizedSectionName(string sectionName, bool isChineseLanguage, out string localizedSectionName) { if (string.Equals(sectionName, "Main", StringComparison.OrdinalIgnoreCase) || string.Equals(sectionName, "主要", StringComparison.Ordinal)) { localizedSectionName = (isChineseLanguage ? "主要" : "Main"); return true; } localizedSectionName = string.Empty; return false; } private void MigrateLocalizedConfigEntries() { IDictionary orphanedEntries = GetOrphanedEntries(((BaseUnityPlugin)this).Config); if (orphanedEntries != null && orphanedEntries.Count != 0 && (false | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_modEnabled, ConfigKey.ModEnabled, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_worldScaleMultiplier, ConfigKey.WorldScale, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_backpackScaleMultiplier, ConfigKey.BackpackScale, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_positionOffsetX, ConfigKey.PositionOffsetX, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_positionOffsetY, ConfigKey.PositionOffsetY, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_positionOffsetZ, ConfigKey.PositionOffsetZ, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_expressionOption, ConfigKey.FaceExpression, orphanedEntries))) { ((BaseUnityPlugin)this).Config.Save(); } } private static bool TryMigrateLocalizedConfigValue(ConfigEntryBase entry, ConfigKey configKey, IDictionary orphanedEntries) { if (entry == null || entry.Definition == (ConfigDefinition)null || orphanedEntries == null) { return false; } bool flag = false; foreach (ConfigDefinition aliasDefinition in GetAliasDefinitions(configKey)) { if (DefinitionsEqual(aliasDefinition, entry.Definition) || !orphanedEntries.Contains(aliasDefinition)) { continue; } if (!flag) { object obj = orphanedEntries[aliasDefinition]; if (obj != null) { entry.SetSerializedValue(NormalizeSerializedConfigValue(configKey, obj.ToString())); } flag = true; } orphanedEntries.Remove(aliasDefinition); } return flag; } private static string NormalizeSerializedConfigValue(ConfigKey configKey, string serializedValue) { if (configKey == ConfigKey.FaceExpression && TryParseExpressionOption(serializedValue, out var option)) { return option.ToString(); } return serializedValue; } [IteratorStateMachine(typeof(d__161))] private static IEnumerable GetAliasDefinitions(ConfigKey configKey) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__161(-2) { <>3__configKey = configKey }; } private static IDictionary GetOrphanedEntries(ConfigFile configFile) { return ((object)configFile)?.GetType().GetProperty("OrphanedEntries", InstanceFlags)?.GetValue(configFile) as IDictionary; } private static bool DefinitionsEqual(ConfigDefinition left, ConfigDefinition right) { if (string.Equals((left != null) ? left.Section : null, (right != null) ? right.Section : null, StringComparison.Ordinal)) { return string.Equals((left != null) ? left.Key : null, (right != null) ? right.Key : null, StringComparison.Ordinal); } return false; } private static bool DetectChineseLanguage() { bool isChineseLanguage; bool num = TryGetConfiguredGameLanguage(out isChineseLanguage); string languageName; bool flag = TryGetLocalizedTextLanguageName(out languageName); if (num && isChineseLanguage) { return true; } if (flag && IsChineseLanguageName(languageName)) { return true; } return false; } private static string BuildLanguageDetectionSummary(bool isChineseLanguage) { bool isChineseLanguage2; string languageValueText; string text = (TryGetConfiguredGameLanguage(out isChineseLanguage2, out languageValueText) ? (languageValueText + "/" + (isChineseLanguage2 ? "Chinese" : "English")) : "unknown"); string languageName; string text2 = (TryGetLocalizedTextLanguageName(out languageName) ? languageName : "unknown"); return (isChineseLanguage ? "Chinese" : "English") + " (prefs=" + text + ", runtime=" + text2 + ")"; } private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage) { string languageValueText; return TryGetConfiguredGameLanguage(out isChineseLanguage, out languageValueText); } private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage, out string languageValueText) { isChineseLanguage = false; languageValueText = string.Empty; try { if (!PlayerPrefs.HasKey("LanguageSetting")) { return false; } int result = PlayerPrefs.GetInt("LanguageSetting", int.MinValue); if (result != int.MinValue) { languageValueText = result.ToString(CultureInfo.InvariantCulture); isChineseLanguage = IsChineseLanguageIndex(result); return true; } string text = (languageValueText = PlayerPrefs.GetString("LanguageSetting", string.Empty)); if (string.IsNullOrWhiteSpace(text)) { return false; } if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { isChineseLanguage = IsChineseLanguageIndex(result); return true; } isChineseLanguage = IsChineseLanguageName(text); return true; } catch { return false; } } private static bool TryGetLocalizedTextLanguageName(out string languageName) { languageName = string.Empty; try { languageName = ((object)(Language)(ref LocalizedText.CURRENT_LANGUAGE)).ToString(); return !string.IsNullOrWhiteSpace(languageName); } catch { return false; } } private static bool IsChineseLanguageName(string languageName) { if (string.IsNullOrWhiteSpace(languageName)) { return false; } if (int.TryParse(languageName.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return IsChineseLanguageIndex(result); } if (languageName.IndexOf("Chinese", StringComparison.OrdinalIgnoreCase) < 0 && languageName.IndexOf("中文", StringComparison.OrdinalIgnoreCase) < 0) { return languageName.StartsWith("zh", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsChineseLanguageIndex(int languageValue) { if (languageValue != 9) { return languageValue == 10; } return true; } private static string GetConfigSectionName(ConfigKey configKey) { return GetSectionName(configKey, isChineseLanguage: false); } private static string GetSectionName(ConfigKey configKey, bool isChineseLanguage) { if (!isChineseLanguage) { return "Main"; } return "主要"; } private static string GetConfigKeyName(ConfigKey configKey) { return GetKeyName(configKey, isChineseLanguage: false); } private static string GetKeyName(ConfigKey configKey, bool isChineseLanguage) { if (isChineseLanguage) { switch (configKey) { case ConfigKey.ModEnabled: return "启用葱音未来替换"; case ConfigKey.WorldScale: return "世界模型大小"; case ConfigKey.BackpackScale: return "背包模型大小"; case ConfigKey.PositionOffsetX: return "模型位置偏移 X"; case ConfigKey.PositionOffsetY: return "模型位置偏移 Y"; case ConfigKey.PositionOffsetZ: return "模型位置偏移 Z"; case ConfigKey.FaceExpression: return "表情"; } } return configKey switch { ConfigKey.ModEnabled => "Enable Fufu Replacement", ConfigKey.WorldScale => "Fufu Size In World", ConfigKey.BackpackScale => "Backpack Model Scale", ConfigKey.PositionOffsetX => "Model Position Offset X", ConfigKey.PositionOffsetY => "Model Position Offset Y", ConfigKey.PositionOffsetZ => "Model Position Offset Z", ConfigKey.FaceExpression => "Face Expression", _ => string.Empty, }; } private static string GetLocalizedDescription(ConfigKey configKey, bool isChineseLanguage) { if (isChineseLanguage) { switch (configKey) { case ConfigKey.ModEnabled: return "总开关。关闭后会恢复原版 BingBong 的外观、名称、图标和碰撞体。"; case ConfigKey.WorldScale: return "葱音未来模型在手持或放在世界中时的大小倍率。"; case ConfigKey.BackpackScale: return "葱音未来模型显示在背包中时的大小倍率。"; case ConfigKey.PositionOffsetX: return "运行时模型在 X 轴上的额外本地位置偏移。"; case ConfigKey.PositionOffsetY: return "运行时模型在 Y 轴上的额外本地位置偏移。"; case ConfigKey.PositionOffsetZ: return "运行时模型在 Z 轴上的额外本地位置偏移。"; case ConfigKey.FaceExpression: return "基础 PMX 表情。枚举会在运行时映射回实际 morph 名称,例如 Smile=笑い,Blink=まばたき,Wink=ウィンク。"; } } return configKey switch { ConfigKey.ModEnabled => "Master switch for the mod. When disabled, the original BingBong visuals, name, icon, and colliders are restored.", ConfigKey.WorldScale => "Scale multiplier for Fufu while held or lying in the world.", ConfigKey.BackpackScale => "Scale multiplier for the replacement model while the item is shown in the backpack.", ConfigKey.PositionOffsetX => "Extra local position offset on the X axis for the runtime model.", ConfigKey.PositionOffsetY => "Extra local position offset on the Y axis for the runtime model.", ConfigKey.PositionOffsetZ => "Extra local position offset on the Z axis for the runtime model.", ConfigKey.FaceExpression => "Base PMX facial expression. Mapping: Smile=笑い, Blink=まばたき, Wink=ウィンク, WinkRight=ウィンク右, Wink2=ウィンク2, Wink2Right=ウィンク2右, A=あ, I=い, U=う, E=え, O=お, A2=あ2, MouthCornerUp=口角上げ, MouthCornerDown=口角下げ, Hau=はぅ.", _ => string.Empty, }; } private static bool TryGetConfigKey(string keyName, out ConfigKey configKey) { foreach (ConfigKey value in Enum.GetValues(typeof(ConfigKey))) { if (IsConfigKeyName(keyName, value)) { configKey = value; return true; } } configKey = ConfigKey.ModEnabled; return false; } private static bool IsConfigKeyName(string keyName, ConfigKey configKey) { if (!string.Equals(keyName, GetConfigKeyName(configKey), StringComparison.OrdinalIgnoreCase)) { return string.Equals(keyName, GetKeyName(configKey, isChineseLanguage: true), StringComparison.Ordinal); } return true; } private void TryLocalizeVisibleModConfigUiThrottled() { if (!(Time.unscaledTime < _nextModConfigUiLocalizationTime)) { _nextModConfigUiLocalizationTime = Time.unscaledTime + 0.25f; TryLocalizeVisibleModConfigUi(); } } private void TryLocalizeVisibleModConfigUi() { if (!TryGetModConfigMenuInstance(out var menuType, out var menuInstance)) { return; } Behaviour val = (Behaviour)((menuInstance is Behaviour) ? menuInstance : null); if (val == null || (Object)(object)val == (Object)null) { return; } try { if (!val.isActiveAndEnabled || !((Component)val).gameObject.activeInHierarchy) { return; } } catch { return; } Dictionary map = BuildModConfigUiLocalizationMap(DetectChineseLanguage()); foreach (Transform item in EnumerateModConfigUiRoots(menuInstance, menuType)) { ApplyTextLocalizationToRoot(item, map); } ApplyTextLocalizationToLoadedUi(map); } private static bool TryGetModConfigMenuInstance(out Type menuType, out object menuInstance) { menuType = null; menuInstance = null; if (!Chainloader.PluginInfos.TryGetValue("com.github.PEAKModding.PEAKLib.ModConfig", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { return false; } Assembly assembly = ((object)value.Instance).GetType().Assembly; menuType = assembly.GetType("PEAKLib.ModConfig.Components.ModdedSettingsMenu"); menuInstance = menuType?.GetProperty("Instance", StaticFlags)?.GetValue(null); if (menuType != null) { return menuInstance != null; } return false; } [IteratorStateMachine(typeof(d__181))] private static IEnumerable EnumerateModConfigUiRoots(object menuInstance, Type menuType) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__181(-2) { <>3__menuInstance = menuInstance, <>3__menuType = menuType }; } [IteratorStateMachine(typeof(d__182))] private static IEnumerable EnumerateCandidateTransforms(object menuInstance, Type menuType) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__182(-2) { <>3__menuInstance = menuInstance, <>3__menuType = menuType }; } private static void ApplyTextLocalizationToRoot(Transform root, Dictionary map) { if (!((Object)(object)root == (Object)null) && map != null && map.Count != 0) { TMP_Text[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyTextLocalization(componentsInChildren[i], map); } } } private static void ApplyTextLocalizationToLoadedUi(Dictionary map) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (map == null || map.Count == 0) { return; } try { TMP_Text[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_Text val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { ApplyTextLocalization(val, map); } } } } catch { } } private static void ApplyTextLocalization(TMP_Text text, Dictionary map) { if (!((Object)(object)text == (Object)null) && map != null && map.Count != 0) { string text2 = ((text.text == null) ? string.Empty : text.text.Trim()); if (!string.IsNullOrWhiteSpace(text2) && map.TryGetValue(text2, out var value) && !string.Equals(text2, value, StringComparison.Ordinal)) { text.text = value; } } } private static Dictionary BuildModConfigUiLocalizationMap(bool isChineseLanguage) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); AddUiLocalizationPair(dictionary, "ScallionMiku", GetLocalizedModDisplayName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "ScallionMiku", GetLocalizedModDisplayName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "com.github.Thanks.ScallionMiku", GetLocalizedModDisplayName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "Main", GetSectionName(ConfigKey.ModEnabled, isChineseLanguage)); AddUiLocalizationPair(dictionary, "主要", GetSectionName(ConfigKey.ModEnabled, isChineseLanguage)); foreach (ConfigKey value in Enum.GetValues(typeof(ConfigKey))) { string sectionName = GetSectionName(value, isChineseLanguage); string keyName = GetKeyName(value, isChineseLanguage); AddUiLocalizationPair(dictionary, GetConfigSectionName(value), sectionName); AddUiLocalizationPair(dictionary, GetSectionName(value, isChineseLanguage: true), sectionName); AddUiLocalizationPair(dictionary, GetConfigKeyName(value), keyName); AddUiLocalizationPair(dictionary, ToReadableName(GetConfigKeyName(value)), keyName); AddUiLocalizationPair(dictionary, GetKeyName(value, isChineseLanguage: true), keyName); AddUiLocalizationPair(dictionary, GetLocalizedDescription(value, isChineseLanguage: false), GetLocalizedDescription(value, isChineseLanguage)); AddUiLocalizationPair(dictionary, GetLocalizedDescription(value, isChineseLanguage: true), GetLocalizedDescription(value, isChineseLanguage)); } AddExpressionOptionUiLocalization(dictionary, isChineseLanguage); return dictionary; } private static void AddExpressionOptionUiLocalization(Dictionary map, bool isChineseLanguage) { AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.None, isChineseLanguage, "无"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Smile, isChineseLanguage, "笑い"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Blink, isChineseLanguage, "眨眼"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Wink, isChineseLanguage, "眨左眼"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.WinkRight, isChineseLanguage, "眨右眼"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Wink2, isChineseLanguage, "眨左眼 2"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Wink2Right, isChineseLanguage, "眨右眼 2"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.A, isChineseLanguage, "口型 あ"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.I, isChineseLanguage, "口型 い"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.U, isChineseLanguage, "口型 う"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.E, isChineseLanguage, "口型 え"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.O, isChineseLanguage, "口型 お"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.A2, isChineseLanguage, "口型 あ2"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.MouthCornerUp, isChineseLanguage, "嘴角上扬"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.MouthCornerDown, isChineseLanguage, "嘴角下垂"); AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Hau, isChineseLanguage, "はぅ"); } private static void AddExpressionOptionUiLocalizationPair(Dictionary map, FaceExpressionOption option, bool isChineseLanguage, string chineseLabel) { string text = option.ToString(); if (isChineseLanguage) { AddUiLocalizationPair(map, text, chineseLabel); } else { AddUiLocalizationPair(map, chineseLabel, text); } } private static void AddUiLocalizationPair(Dictionary map, string source, string localized) { if (map != null && !string.IsNullOrWhiteSpace(source) && !string.IsNullOrWhiteSpace(localized)) { string text = source.Trim(); string text3 = (map[text] = localized.Trim()); map[text3] = text3; string key = text.Replace(" ", string.Empty); string key2 = text3.Replace(" ", string.Empty); if (!map.ContainsKey(key)) { map[key] = text3; } if (!map.ContainsKey(key2)) { map[key2] = text3; } map[text.ToUpperInvariant()] = text3; map[text3.ToUpperInvariant()] = text3; } } private static string ToReadableName(string keyName) { if (string.IsNullOrWhiteSpace(keyName)) { return string.Empty; } List list = new List(keyName.Length + 8); for (int i = 0; i < keyName.Length; i++) { char c = keyName[i]; if (i > 0 && char.IsUpper(c) && !char.IsWhiteSpace(keyName[i - 1]) && !char.IsUpper(keyName[i - 1])) { list.Add(' '); } list.Add(c); } return new string(list.ToArray()); } private static string GetLocalizedModDisplayName(bool isChineseLanguage) { if (!isChineseLanguage) { return "ScallionMiku"; } return "葱音未来"; } private void NormalizeMigratedScaleConfigIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (!string.IsNullOrEmpty(configFilePath) && File.Exists(configFilePath) && (FileContainsSetting(configFilePath, "Miku Size In World") || FileContainsSetting(configFilePath, "Fufu Size In Backpack") || FileContainsSetting(configFilePath, "Miku Size In Backpack") || FileContainsSetting(configFilePath, "Enable Miku Replacement"))) { bool flag = false; if (TryReadFloatSetting(configFilePath, "Miku Size In World", out var value) && _worldScaleMultiplier != null && _worldScaleMultiplier.Value <= 0.4001f) { _worldScaleMultiplier.Value = Mathf.Clamp(value, 0.4f, 1.1f); flag = true; } if (!FileContainsSetting(configFilePath, "Backpack Model Scale") && TryReadFirstFloatSetting(configFilePath, out var value2, "Fufu Size In Backpack", "Miku Size In Backpack") && _backpackScaleMultiplier != null) { _backpackScaleMultiplier.Value = Mathf.Clamp(value2, 0.2f, 1f); flag = true; } if (flag) { ((BaseUnityPlugin)this).Config.Save(); VerboseLog("Normalized migrated ScallionMiku scale settings for current runtime model."); } } } catch (Exception ex) { Log.LogWarning((object)("Failed to normalize migrated config values: " + ex.Message)); } } private static bool FileContainsSetting(string configPath, string key) { if (string.IsNullOrEmpty(configPath) || string.IsNullOrEmpty(key) || !File.Exists(configPath)) { return false; } string[] array = File.ReadAllLines(configPath); foreach (string text in array) { if (text != null && text.StartsWith(key + " =", StringComparison.Ordinal)) { return true; } } return false; } private static bool TryReadFloatSetting(string configPath, string key, out float value) { value = 0f; if (string.IsNullOrEmpty(configPath) || string.IsNullOrEmpty(key) || !File.Exists(configPath)) { return false; } string[] array = File.ReadAllLines(configPath); foreach (string text in array) { if (text != null && text.StartsWith(key + " =", StringComparison.Ordinal)) { return float.TryParse(text.Substring((key + " =").Length).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out value); } } return false; } private static bool TryReadFirstFloatSetting(string configPath, out float value, params string[] keys) { value = 0f; if (keys == null || keys.Length == 0) { return false; } foreach (string key in keys) { if (TryReadFloatSetting(configPath, key, out value)) { return true; } } return false; } private void LoadAssets() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = LoadExternalIconTexture(); _bundledReplacementBaseScale = DefaultBundledReplacementBaseScale; string text = ResolveBundlePath(); RuntimeReplacementModel = null; Bundle = null; MochiPrefab = null; MochiMaterial = null; MochiTexture = val; MikuMainTexture = null; RuntimeMikuMaterial = null; if (File.Exists(text)) { if (!TryLoadReplacementBundle(text, val)) { Log.LogError((object)("Found ScallionMiku bundle but failed to initialize replacement from: " + text)); } } else { Log.LogError((object)("ScallionMiku bundle is missing. Bundle-only runtime is enabled, so no PMX fallback will be loaded: " + text)); } } private bool TryLoadReplacementBundle(string bundlePath, Texture2D externalIconTexture) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) Bundle = AssetBundle.LoadFromFile(bundlePath); if ((Object)(object)Bundle == (Object)null) { Log.LogError((object)("Failed to load ScallionMiku AssetBundle: " + bundlePath)); return false; } RuntimeReplacementModel = null; MochiPrefab = LoadBundleAssetWithFallback("assets/葱音未来_by_翼月生/scallionmiku.prefab", PrefabNameHints); MochiMaterial = LoadBundleAssetWithFallback("assets/葱音未来_by_翼月生/materials/scallionmiku-8.shintai.mat", MaterialNameHints); MochiTexture = externalIconTexture ?? LoadBundleAssetWithFallback("assets/葱音未来_by_翼月生/textures/身体.png", IconTextureNameHints); Texture2D val = LoadBundleAssetWithFallback("assets/葱音未来_by_翼月生/textures/身体.png", MainTextureNameHints); MikuMainTexture = CreateReadableTexture(val) ?? val; if ((Object)(object)MochiPrefab == (Object)null) { Log.LogError((object)"Failed to load replacement prefab from asset bundle."); Bundle.Unload(false); Bundle = null; return false; } _bundledReplacementBaseScale = CalculateBundledReplacementBaseScale(MochiPrefab); ConfigureMochiMaterial(MikuMainTexture); RuntimeMikuMaterial = CreateRuntimeMikuMaterial(MikuMainTexture); ItemPatch.SanitizeLoadedPrefabRendererMaterials(MochiPrefab, "TryLoadReplacementBundle"); if ((Object)(object)RuntimeMikuMaterial == (Object)null) { Log.LogWarning((object)"Runtime fallback material was not created. The bundled material will be used when available."); } if ((Object)(object)MochiTexture == (Object)null) { Log.LogWarning((object)"Failed to load replacement icon texture."); } if ((Object)(object)MikuMainTexture == (Object)null) { Log.LogWarning((object)"Failed to load replacement main texture."); } VerboseLog("Loaded ScallionMiku replacement from asset bundle: " + bundlePath); return true; } private static Vector3 CalculateBundledReplacementBaseScale(GameObject prefab) { //IL_0009: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return DefaultBundledReplacementBaseScale; } Vector3 val; if (!TryCalculatePrefabBounds(prefab.transform, out var combinedBounds, out var rendererCount)) { ManualLogSource log = Log; val = DefaultBundledReplacementBaseScale; log.LogWarning((object)("Failed to calculate bundled prefab bounds. Falling back to default bundle base scale: " + ((Vector3)(ref val)).ToString("F4"))); return DefaultBundledReplacementBaseScale; } float num = Mathf.Max(((Bounds)(ref combinedBounds)).size.y, 0.0001f); float num2 = RuntimeReferenceVisibleSizeAtBaseScale.y * 0.78f * 1.5f; float num3 = Mathf.Clamp(num2 / num, 0.04f, 1.2f); Vector3 result = default(Vector3); ((Vector3)(ref result))..ctor(num3, num3, num3); string[] obj = new string[8] { "Auto-calculated ScallionMiku bundle base scale. rendererCount=", rendererCount.ToString(CultureInfo.InvariantCulture), ", prefabBoundsSize=", null, null, null, null, null }; val = ((Bounds)(ref combinedBounds)).size; obj[3] = ((Vector3)(ref val)).ToString("F4"); obj[4] = ", targetHeight="; obj[5] = num2.ToString("F4", CultureInfo.InvariantCulture); obj[6] = ", baseScale="; obj[7] = ((Vector3)(ref result)).ToString("F4"); VerboseLog(string.Concat(obj)); return result; } private static bool TryCalculatePrefabBounds(Transform root, out Bounds combinedBounds, out int rendererCount) { //IL_0001: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) combinedBounds = default(Bounds); rendererCount = 0; if ((Object)(object)root == (Object)null) { return false; } bool hasBounds = false; Matrix4x4 worldToLocalMatrix = root.worldToLocalMatrix; MeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { MeshFilter component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null)) { AppendTransformedBounds(worldToLocalMatrix, ((Component)val).transform.localToWorldMatrix, component.sharedMesh.bounds, ref combinedBounds, ref hasBounds); rendererCount++; } } } SkinnedMeshRenderer[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.sharedMesh == (Object)null)) { Bounds localBounds = ((Renderer)val2).localBounds; Vector3 size = ((Bounds)(ref localBounds)).size; Bounds sourceBounds = ((((Vector3)(ref size)).sqrMagnitude > 1E-06f) ? ((Renderer)val2).localBounds : val2.sharedMesh.bounds); AppendTransformedBounds(worldToLocalMatrix, ((Component)val2).transform.localToWorldMatrix, sourceBounds, ref combinedBounds, ref hasBounds); rendererCount++; } } return hasBounds; } private static void AppendTransformedBounds(Matrix4x4 rootWorldToLocal, Matrix4x4 childLocalToWorld, Bounds sourceBounds, ref Bounds combinedBounds, ref bool hasBounds) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Matrix4x4 val = rootWorldToLocal * childLocalToWorld; Vector3 center = ((Bounds)(ref sourceBounds)).center; Vector3 extents = ((Bounds)(ref sourceBounds)).extents; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val2 = center + Vector3.Scale(extents, new Vector3((float)i, (float)j, (float)k)); Vector3 val3 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(val2); if (!hasBounds) { combinedBounds = new Bounds(val3, Vector3.zero); hasBounds = true; } else { ((Bounds)(ref combinedBounds)).Encapsulate(val3); } } } } } private static string ResolveBundlePath() { return Path.Combine(directory, "ScallionMiku"); } private Texture2D LoadExternalIconTexture() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //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) string text = Path.Combine(directory, "ScallionMikuUI.png"); if (!File.Exists(text)) { return null; } try { using FileStream fileStream = File.OpenRead(text); Bitmap val = new Bitmap((Stream)fileStream); try { int width = ((Image)val).Width; int height = ((Image)val).Height; Color32[] array = (Color32[])(object)new Color32[width * height]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Color pixel = val.GetPixel(j, height - 1 - i); array[i * width + j] = new Color32(pixel.R, pixel.G, pixel.B, pixel.A); } } Texture2D val2 = new Texture2D(width, height, (TextureFormat)4, false, false) { name = Path.GetFileNameWithoutExtension(text) }; val2.SetPixels32(array); ((Texture)val2).filterMode = (FilterMode)1; ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).anisoLevel = 1; val2.Apply(false, false); return val2; } finally { ((IDisposable)val)?.Dispose(); } } catch (Exception ex) { Log.LogWarning((object)("Failed to load external icon texture '" + text + "': " + ex.Message)); return null; } } internal static GameObject CreateReplacementVisualInstance(string name) { if (RuntimeReplacementModel != null) { return RuntimeReplacementModel.Instantiate(name); } if ((Object)(object)MochiPrefab == (Object)null) { return null; } return Object.Instantiate(MochiPrefab); } internal static void VerboseLog(string message) { } private static T LoadBundleAssetWithFallback(string preferredPath, params string[] nameHints) where T : Object { if ((Object)(object)Bundle == (Object)null) { return default(T); } if (!string.IsNullOrEmpty(preferredPath)) { T val = Bundle.LoadAsset(preferredPath); if ((Object)(object)val != (Object)null) { return val; } } string[] allAssetNames = Bundle.GetAllAssetNames(); if (allAssetNames != null) { foreach (string text in allAssetNames) { if (AssetNameLooksRelevant(text, preferredPath, nameHints)) { T val2 = Bundle.LoadAsset(text); if ((Object)(object)val2 != (Object)null) { VerboseLog("Loaded fallback " + typeof(T).Name + " from bundle path: " + text); return val2; } } } } T[] array = Bundle.LoadAllAssets(); if (array == null || array.Length == 0) { Log.LogWarning((object)("No " + typeof(T).Name + " assets found in bundle for requested path: " + preferredPath)); return default(T); } T val3 = FindAssetByObjectName(array, preferredPath, nameHints); if ((Object)(object)val3 != (Object)null) { VerboseLog("Loaded fallback " + typeof(T).Name + " by object name: " + ((Object)val3).name); return val3; } if (array.Length == 1) { Log.LogWarning((object)("Loaded only available " + typeof(T).Name + " asset as fallback: " + ((Object)array[0]).name)); return array[0]; } Log.LogWarning((object)("Unable to identify " + typeof(T).Name + " for requested path '" + preferredPath + "'. Candidates: " + string.Join(", ", Array.ConvertAll(array, (T asset) => (!((Object)(object)asset != (Object)null)) ? "" : ((Object)asset).name)))); return default(T); } private static T FindAssetByObjectName(T[] assets, string preferredPath, string[] nameHints) where T : Object { string needle = (string.IsNullOrEmpty(preferredPath) ? string.Empty : Path.GetFileNameWithoutExtension(preferredPath)); foreach (T val in assets) { if (!((Object)(object)val == (Object)null)) { string value = ((Object)val).name ?? string.Empty; if (NameMatches(value, needle) || NameMatchesAnyHint(value, nameHints)) { return val; } } } return default(T); } private static bool AssetNameLooksRelevant(string assetName, string preferredPath, string[] nameHints) { if (string.IsNullOrEmpty(assetName)) { return false; } if (!string.IsNullOrEmpty(preferredPath)) { if (assetName.Equals(preferredPath, StringComparison.OrdinalIgnoreCase)) { return true; } string fileName = Path.GetFileName(preferredPath); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(preferredPath); if (!string.IsNullOrEmpty(fileName) && assetName.EndsWith(fileName, StringComparison.OrdinalIgnoreCase)) { return true; } if (NameMatches(assetName, fileNameWithoutExtension)) { return true; } } return NameMatchesAnyHint(assetName, nameHints); } private static bool NameMatchesAnyHint(string value, string[] hints) { if (string.IsNullOrEmpty(value) || hints == null) { return false; } for (int i = 0; i < hints.Length; i++) { if (NameMatches(value, hints[i])) { return true; } } return false; } private static bool NameMatches(string value, string needle) { if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(needle)) { return false; } return value.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0; } private static void ConfigureMochiMaterial(Texture2D mikuMainTexture) { if ((Object)(object)MochiMaterial == (Object)null) { return; } if ((Object)(object)MochiMaterial.shader == (Object)null || !MochiMaterial.shader.isSupported) { Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"); if ((Object)(object)val != (Object)null) { MochiMaterial.shader = val; } } if ((Object)(object)mikuMainTexture != (Object)null) { ApplyTextureSet(MochiMaterial, mikuMainTexture); } ApplyMikuColorStyle(MochiMaterial); VerboseLog("Configured bundled material: " + ((Object)MochiMaterial).name); } private static bool TryAssignTextureIfMissing(Material material, string propertyName, Texture2D texture) { //IL_0043: 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) if ((Object)(object)material == (Object)null || (Object)(object)texture == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName)) { return false; } try { if ((Object)(object)material.GetTexture(propertyName) != (Object)null) { return false; } material.SetTexture(propertyName, (Texture)(object)texture); material.SetTextureScale(propertyName, Vector2.one); material.SetTextureOffset(propertyName, Vector2.zero); return true; } catch (Exception ex) { VerboseLog("Skip texture assignment on material '" + ((Object)material).name + "', property '" + propertyName + "': " + ex.Message); return false; } } private static void TryAssignTextureIfMissing(Material material, string[] propertyNames, Texture2D texture) { if (!((Object)(object)material == (Object)null) && !((Object)(object)texture == (Object)null) && propertyNames != null) { for (int i = 0; i < propertyNames.Length; i++) { TryAssignTextureIfMissing(material, propertyNames[i], texture); } } } private static void ApplyTextureSet(Material material, Texture2D albedo) { if (!((Object)(object)material == (Object)null)) { TryAssignTextureIfMissing(material, PreferredTextureProps, albedo); ApplyMikuColorStyle(material); } } private static void ApplyMikuColorStyle(Material material) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_Tint")) { material.SetColor("_Tint", MikuStyleTint); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", MikuStyleTint); } if (material.HasProperty("_Color")) { material.SetColor("_Color", MikuStyleTint); } if (material.HasProperty("_Smoothness")) { material.SetFloat("_Smoothness", 0.3f); } if (material.HasProperty("_Glossiness")) { material.SetFloat("_Glossiness", 0.3f); } if (material.HasProperty("_Metallic")) { material.SetFloat("_Metallic", 0f); } if (material.HasProperty("_BumpScale")) { material.SetFloat("_BumpScale", 0f); } if (material.HasProperty("_OcclusionStrength")) { material.SetFloat("_OcclusionStrength", 0f); } if (material.HasProperty("_SpecularHighlights")) { material.SetFloat("_SpecularHighlights", 0f); } if (material.HasProperty("_EnvironmentReflections")) { material.SetFloat("_EnvironmentReflections", 0f); } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); material.DisableKeyword("_EMISSION"); } material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } } private static Texture2D CreateReadableTexture(Texture2D source) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown if ((Object)(object)source == (Object)null) { return null; } try { source.GetPixel(0, 0); return source; } catch { } RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; try { Graphics.Blit((Texture)(object)source, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)4, true, false) { name = ((Object)source).name + "_Readable" }; val.ReadPixels(new Rect(0f, 0f, (float)((Texture)source).width, (float)((Texture)source).height), 0, 0); val.Apply(true, false); return val; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } private static Material CreateRuntimeMikuMaterial(Texture2D texture) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("W/Peak_Standard"); if ((Object)(object)val == (Object)null) { Log.LogError((object)"Failed to create runtime material because no compatible shader was found."); return null; } Material val2 = new Material(val) { name = "Miku_RuntimeMaterial", renderQueue = 2000, color = Color.white }; if ((Object)(object)texture != (Object)null) { TryAssignTextureIfMissing(val2, "_BaseMap", texture); TryAssignTextureIfMissing(val2, "_MainTex", texture); } if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 0f); } if (val2.HasProperty("_Blend")) { val2.SetFloat("_Blend", 0f); } if (val2.HasProperty("_ZWrite")) { val2.SetFloat("_ZWrite", 1f); } if (val2.HasProperty("_Cull")) { val2.SetFloat("_Cull", 0f); } val2.SetOverrideTag("RenderType", "Opaque"); val2.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); val2.EnableKeyword("_SURFACE_TYPE_OPAQUE"); ApplyMikuColorStyle(val2); return val2; } } public class MikuMarker : MonoBehaviour { public bool HasAppliedState; public int LastRefreshRevision = -1; public int LastLayer = int.MinValue; public ItemState LastItemState; public bool LastShouldShow; public bool HiddenByOriginalRule; public Vector3 LastLocalPosition; public Quaternion LastLocalRotation = Quaternion.identity; public Vector3 LastLocalScale; } public class MikuCollisionMarker : MonoBehaviour { } public class MikuTwinTailClothState : MonoBehaviour { public int MeshInstanceId; public int MovableVertexCount; } public class MikuScaleRefreshGuard : MonoBehaviour { private bool _pendingRefresh; private bool _hardReset; private int _targetFrame = -1; private bool _clothSuspendedForPause; public void QueueRefresh(bool hardReset) { _pendingRefresh = true; _hardReset |= hardReset; _targetFrame = Mathf.Max(_targetFrame, Time.frameCount + 1); } private void LateUpdate() { bool flag = Time.timeScale <= 0.0001f; if (flag) { SuspendClothsForPause(); } else if (_clothSuspendedForPause) { ResumeClothsAfterPause(); } if (_pendingRefresh && Time.frameCount >= _targetFrame) { _pendingRefresh = false; _targetFrame = -1; RefreshSkinnedMeshes(); RefreshCloths(_hardReset || flag); _hardReset = false; } } private void RefreshSkinnedMeshes() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } val.updateWhenOffscreen = true; Vector3 size; Bounds val2; if ((Object)(object)val.sharedMesh != (Object)null) { Bounds bounds = val.sharedMesh.bounds; size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude > 1E-06f) { val2 = val.sharedMesh.bounds; goto IL_006b; } } val2 = ((Renderer)val).localBounds; goto IL_006b; IL_006b: Bounds localBounds = val2; size = ((Bounds)(ref localBounds)).size; if (((Vector3)(ref size)).sqrMagnitude > 1E-06f) { ((Bounds)(ref localBounds)).Expand(new Vector3(0.2f, 0.25f, 0.2f)); ((Renderer)val).localBounds = localBounds; } } } private void RefreshCloths(bool hardReset) { Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Cloth val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } val.ClearTransformMotion(); if (hardReset && val.enabled) { val.enabled = false; if (!_clothSuspendedForPause) { val.enabled = true; } } val.ClearTransformMotion(); } } private void SuspendClothsForPause() { Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Cloth val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.ClearTransformMotion(); if (val.enabled) { val.enabled = false; } } } _clothSuspendedForPause = true; } private void ResumeClothsAfterPause() { RefreshSkinnedMeshes(); Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Cloth val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.enabled = true; val.ClearTransformMotion(); } } _clothSuspendedForPause = false; } } public class MikuDeformGuard : MonoBehaviour { private const float SqueezeDuration = 0.78f; private const float SqueezeCompressPhase = 0.42f; private Transform[] _allTransforms = Array.Empty(); private Vector3[] _initialChildScales = Array.Empty(); private Vector3 _rootLocalPosition; private Quaternion _rootLocalRotation; private Vector3 _rootLocalScale; private Item _boundItem; private bool _wasUsing; private float _squeezeElapsed = 0.78f; internal Item BoundItem => _boundItem; public void Initialize(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _rootLocalPosition = rootLocalPosition; _rootLocalRotation = rootLocalRotation; _rootLocalScale = rootLocalScale; _wasUsing = false; _squeezeElapsed = 0.78f; Capture(); } public void Bind(Item item) { _boundItem = item; } public void SetRootTarget(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _rootLocalPosition = rootLocalPosition; _rootLocalRotation = rootLocalRotation; _rootLocalScale = rootLocalScale; } private bool IsHeldAndUsing() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if ((Object)(object)_boundItem != (Object)null && (int)_boundItem.itemState == 1) { if (!_boundItem.isUsingPrimary) { return _boundItem.isUsingSecondary; } return true; } return false; } private void UpdateSingleSqueezeState() { bool flag = IsHeldAndUsing(); if (flag && !_wasUsing) { _squeezeElapsed = 0f; } _wasUsing = flag; if (_squeezeElapsed < 0.78f) { _squeezeElapsed += Time.deltaTime; } } private float EvaluateSingleSqueezeWeight() { if (_squeezeElapsed >= 0.78f) { return 0f; } float num = Mathf.Clamp01(_squeezeElapsed / 0.78f); if (num <= 0.42f) { return Mathf.SmoothStep(0f, 1f, num / 0.42f); } float num2 = (num - 0.42f) / 0.58000004f; return Mathf.SmoothStep(1f, 0f, Mathf.Clamp01(num2)); } private Vector3 GetDesiredRootScale(float squeezeWeight) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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) if (squeezeWeight <= 0.0005f) { return _rootLocalScale; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(1f - 0.14f * squeezeWeight, 1f + 0.11f * squeezeWeight, 1f - 0.14f * squeezeWeight); return Vector3.Scale(_rootLocalScale, val); } public void Capture() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) _allTransforms = ((Component)this).GetComponentsInChildren(true); _initialChildScales = (Vector3[])(object)new Vector3[_allTransforms.Length]; for (int i = 0; i < _allTransforms.Length; i++) { _initialChildScales[i] = _allTransforms[i].localScale; } } private void LateUpdate() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00ec: Unknown result type (might be due to invalid IL or missing references) if (_allTransforms.Length == 0 || _allTransforms.Length != _initialChildScales.Length) { Capture(); } if (((Component)this).transform.localPosition != _rootLocalPosition) { ((Component)this).transform.localPosition = _rootLocalPosition; } if (((Component)this).transform.localRotation != _rootLocalRotation) { ((Component)this).transform.localRotation = _rootLocalRotation; } UpdateSingleSqueezeState(); float squeezeWeight = EvaluateSingleSqueezeWeight(); Vector3 desiredRootScale = GetDesiredRootScale(squeezeWeight); if (((Component)this).transform.localScale != desiredRootScale) { ((Component)this).transform.localScale = desiredRootScale; } for (int i = 0; i < _allTransforms.Length; i++) { Transform val = _allTransforms[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)((Component)this).transform) && val.localScale != _initialChildScales[i]) { val.localScale = _initialChildScales[i]; } } } } public class MikuRendererGuard : MonoBehaviour { private const float RefreshInterval = 0.1f; private float _nextRefreshTime; private Item _boundItem; private Renderer[] _cachedRenderers = Array.Empty(); internal Item BoundItem => _boundItem; public void Bind(Item item) { _boundItem = item; } private void LateUpdate() { if (!Plugin.ModEnabled || !Plugin.EnableVisibilityGuard) { return; } MikuMarker component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null && component.HiddenByOriginalRule) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextRefreshTime) { return; } _nextRefreshTime = realtimeSinceStartup + 0.1f; if (!((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(true); } int num = (((Object)(object)_boundItem != (Object)null) ? ((Component)_boundItem).gameObject.layer : ((Component)this).gameObject.layer); if (((Component)this).gameObject.layer != num) { ((Component)this).gameObject.layer = num; } Renderer[] renderableChildren = GetRenderableChildren(); foreach (Renderer val in renderableChildren) { if (!((Object)(object)val == (Object)null)) { EnsureRendererVisible(val, num); } } } private Renderer[] GetRenderableChildren() { if (_cachedRenderers.Length == 0 || HasNullRenderer(_cachedRenderers)) { _cachedRenderers = ((Component)this).GetComponentsInChildren(true); } return _cachedRenderers; } private static bool HasNullRenderer(Renderer[] renderers) { for (int i = 0; i < renderers.Length; i++) { if ((Object)(object)renderers[i] == (Object)null) { return true; } } return false; } private static void EnsureRendererVisible(Renderer renderer, int targetLayer) { if (!((Component)renderer).gameObject.activeSelf) { ((Component)renderer).gameObject.SetActive(true); } if (renderer.forceRenderingOff) { renderer.forceRenderingOff = false; } if (!renderer.enabled) { renderer.enabled = true; } renderer.SetPropertyBlock((MaterialPropertyBlock)null); ((Component)renderer).gameObject.layer = targetLayer; renderer.allowOcclusionWhenDynamic = false; ItemPatch.NormalizeRuntimeRendererMaterials(renderer, "RendererGuard"); } private static void NormalizeRendererMaterialColor(Renderer renderer) { //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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) Material[] sharedMaterials = renderer.sharedMaterials; foreach (Material val in sharedMaterials) { if (!((Object)(object)val == (Object)null)) { Color white = Color.white; if (val.HasProperty("_Tint")) { val.SetColor("_Tint", white); } if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", white); } if (val.HasProperty("_Color")) { val.SetColor("_Color", white); } } } } } [HarmonyPatch(typeof(Item))] public class ItemPatch { private const int VisibleLayer = 0; private static readonly Color MikuMaterialTint = new Color(0.98f, 1f, 1f, 1f); private const string MikuVisualName = "MikuFumo_Visual"; private const string MikuCollisionName = "MikuCollisionProxy"; private static readonly Vector3 BaselineMikuLocalPosition = new Vector3(-0.06f, -0.5f, 0f); private static readonly Vector3 WorldMikuLocalPosition = BaselineMikuLocalPosition; private static readonly Quaternion WorldMikuLocalRotation = Quaternion.identity; private static readonly Quaternion BundledWorldMikuLocalRotation = Quaternion.Euler(0f, 180f, 0f); private static readonly Vector3 HeldMikuLocalPosition = BaselineMikuLocalPosition; private static readonly Quaternion HeldMikuLocalRotation = Quaternion.Euler(10f, 0f, 0f); private static readonly Quaternion BundledHeldMikuLocalRotation = Quaternion.Euler(10f, 180f, 0f); private const int TwinTailChainStartIndex = 3; private const int TwinTailChainEndIndex = 9; private const int TwinTailAnchorIndex = 2; private const float TwinTailMinInfluenceThreshold = 0.12f; private const float TwinTailMaxDistanceCap = 0.78f; private const float TwinTailStretchingStiffness = 0.98f; private const float TwinTailBendingStiffness = 0.9f; private const float TwinTailDamping = 0.2f; private const float TwinTailFriction = 0.2f; private const float TwinTailCollisionMassScale = 0.06f; private const float TwinTailSolverFrequency = 36f; private const float TwinTailWorldVelocityScale = 0.2f; private const float TwinTailWorldAccelerationScale = 0.75f; private const double SlowCreateProfileTotalThresholdMs = 12.0; private const double SlowCreateProfileStageThresholdMs = 4.0; private static readonly string[] UnwantedFootKeywords = new string[3] { "hand", "glove", "mitten" }; private static readonly string[] CollisionExcludedRendererKeywords = new string[8] { "hair", "tail", "twintail", "twin_tail", "pigtail", "ponytail", "bang", "ahoge" }; private static readonly FieldRef CharacterDataRef = AccessTools.FieldRefAccess("data"); private static readonly FieldRef CharacterCurrentItemRef = AccessTools.FieldRefAccess("_currentitem"); private static readonly HashSet LoggedRuntimeRendererMaterialWarnings = new HashSet(); private static bool SlowCreateProfileLogged; private static bool IsBingBong(Item item) { if ((Object)(object)item != (Object)null) { if (((Object)item).name.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) < 0) { return ((Object)item).name.IndexOf("Bing Bong", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } internal static bool IsMikuTransform(Transform transform) { if ((Object)(object)transform != (Object)null) { if (!((Object)(object)((Component)transform).GetComponentInParent() != (Object)null)) { return (Object)(object)((Component)transform).GetComponentInParent() != (Object)null; } return true; } return false; } private static bool IsInBackpack(Item item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((Object)(object)item != (Object)null) { return (int)item.itemState == 2; } return false; } private static bool IsHeld(Item item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((Object)(object)item != (Object)null) { return (int)item.itemState == 1; } return false; } private static bool ShouldShowReplacement(Item item) { if ((Object)(object)item != (Object)null && Plugin.ModEnabled) { return !IsReplacementHiddenByOriginal(item); } return false; } private static bool IsReplacementHiddenByOriginal(Item item) { return IsReplacementHiddenByOriginal(FindMikuRoot(item)); } private static bool IsReplacementHiddenByOriginal(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return false; } MikuMarker component = ((Component)mikuRoot).GetComponent(); if ((Object)(object)component != (Object)null) { return component.HiddenByOriginalRule; } return false; } private static void SetReplacementHiddenByOriginal(Transform mikuRoot, bool hidden) { if (!((Object)(object)mikuRoot == (Object)null)) { MikuMarker component = ((Component)mikuRoot).GetComponent(); if ((Object)(object)component != (Object)null) { component.HiddenByOriginalRule = hidden; } } } private static void HideReplacementForOriginalRule(Item item, Transform mikuRoot) { if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null)) { SetReplacementHiddenByOriginal(mikuRoot, hidden: true); Transform val = FindMikuCollisionRoot(item); SetColliderArrayEnabled(((Object)(object)val != (Object)null) ? GetUsableProxyColliders(val) : Array.Empty(), enabled: false); DisableOriginalColliders(item); RestoreOriginalItemRendererRefs(item); if (((Component)mikuRoot).gameObject.activeSelf) { ((Component)mikuRoot).gameObject.SetActive(false); } } } private static Vector3 ResolveScaleByState(Item item) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) float num = (IsInBackpack(item) ? Plugin.BackpackScaleMultiplier : Plugin.WorldScaleMultiplier); return Plugin.ReplacementBaseScale * num; } private static Vector3 ApplyPlayerFacingScale(Vector3 scale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) return new Vector3(0f - Mathf.Abs(scale.x), Mathf.Abs(scale.y), 0f - Mathf.Abs(scale.z)); } private static bool UseBundledPositiveFacing() { return Plugin.RuntimeReplacementModel == null; } private static Vector3 CompensateRuntimeScalePosition(Vector3 basePosition, Vector3 currentScale, Vector3 referenceScale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return basePosition; } private static void ResolvePoseByState(Item item, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale) { //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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0031: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ResolveScaleByState(item); if (IsHeld(item)) { bool flag = UseBundledPositiveFacing(); localRotation = (flag ? BundledHeldMikuLocalRotation : HeldMikuLocalRotation); localScale = (Vector3)(flag ? new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z)) : ApplyPlayerFacingScale(val)); Vector3 val2 = Plugin.ReplacementBaseScale * Plugin.DefaultWorldScaleSetting; Vector3 referenceScale = (Vector3)(flag ? new Vector3(Mathf.Abs(val2.x), Mathf.Abs(val2.y), Mathf.Abs(val2.z)) : ApplyPlayerFacingScale(val2)); localPosition = CompensateRuntimeScalePosition(HeldMikuLocalPosition, localScale, referenceScale); } else if (IsInBackpack(item)) { localRotation = WorldMikuLocalRotation; localScale = val; Vector3 referenceScale2 = Plugin.ReplacementBaseScale * Plugin.DefaultBackpackScaleSetting; localPosition = CompensateRuntimeScalePosition(WorldMikuLocalPosition, localScale, referenceScale2); } else { bool flag2 = UseBundledPositiveFacing(); localRotation = (flag2 ? BundledWorldMikuLocalRotation : WorldMikuLocalRotation); localScale = (Vector3)(flag2 ? new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z)) : ApplyPlayerFacingScale(val)); Vector3 val3 = Plugin.ReplacementBaseScale * Plugin.DefaultWorldScaleSetting; Vector3 referenceScale3 = (Vector3)(flag2 ? new Vector3(Mathf.Abs(val3.x), Mathf.Abs(val3.y), Mathf.Abs(val3.z)) : ApplyPlayerFacingScale(val3)); localPosition = CompensateRuntimeScalePosition(WorldMikuLocalPosition, localScale, referenceScale3); } localPosition += Plugin.PositionOffset; } private static Transform FindMikuRoot(Item item) { if ((Object)(object)item == (Object)null) { return null; } Transform val = ((Component)item).transform.Find("MikuFumo_Visual"); if ((Object)(object)val != (Object)null) { return val; } MikuMarker[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { return ((Component)componentsInChildren[i]).transform; } } return null; } private static Transform FindMikuCollisionRoot(Item item) { if ((Object)(object)item == (Object)null) { return null; } Transform val = ((Component)item).transform.Find("MikuCollisionProxy"); if ((Object)(object)val != (Object)null) { return val; } MikuCollisionMarker[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { return ((Component)componentsInChildren[i]).transform; } } return null; } private static MikuExpressionController FindExpressionController(Transform mikuRoot) { if (!((Object)(object)mikuRoot != (Object)null)) { return null; } return ((Component)mikuRoot).GetComponentInChildren(true); } private static Item FindBoundItemFromMikuRoot(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return null; } MikuRendererGuard component = ((Component)mikuRoot).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.BoundItem != (Object)null) { return component.BoundItem; } MikuDeformGuard component2 = ((Component)mikuRoot).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.BoundItem != (Object)null) { return component2.BoundItem; } MikuExpressionController mikuExpressionController = FindExpressionController(mikuRoot); if ((Object)(object)mikuExpressionController != (Object)null && (Object)(object)mikuExpressionController.BoundItem != (Object)null) { return mikuExpressionController.BoundItem; } return ((Component)mikuRoot).GetComponentInParent(); } private static MikuScaleRefreshGuard EnsureScaleRefreshGuard(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return null; } MikuScaleRefreshGuard mikuScaleRefreshGuard = ((Component)mikuRoot).GetComponent(); if ((Object)(object)mikuScaleRefreshGuard == (Object)null) { mikuScaleRefreshGuard = ((Component)mikuRoot).gameObject.AddComponent(); } return mikuScaleRefreshGuard; } private static void QueueScaleSensitiveRefresh(Transform mikuRoot, bool forceHardReset) { MikuScaleRefreshGuard mikuScaleRefreshGuard = EnsureScaleRefreshGuard(mikuRoot); if (!((Object)(object)mikuScaleRefreshGuard == (Object)null)) { bool flag = Time.timeScale <= 0.0001f; mikuScaleRefreshGuard.QueueRefresh(forceHardReset || flag); } } private static MikuExpressionController EnsureExpressionController(Transform mikuRoot) { MikuExpressionController mikuExpressionController = FindExpressionController(mikuRoot); if ((Object)(object)mikuExpressionController != (Object)null || (Object)(object)mikuRoot == (Object)null) { return mikuExpressionController; } SkinnedMeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); List list = new List(); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && val.sharedMesh.blendShapeCount > 0) { list.Add(val); } } if (list.Count > 0) { MikuExpressionController mikuExpressionController2 = ((Component)mikuRoot).gameObject.AddComponent(); mikuExpressionController2.Initialize((IEnumerable)list); return mikuExpressionController2; } return null; } private static Texture GetMikuTexture() { if ((Object)(object)Plugin.MikuMainTexture != (Object)null) { return (Texture)(object)Plugin.MikuMainTexture; } Texture val = TryGetTexture(Plugin.MochiMaterial); if ((Object)(object)val != (Object)null) { return val; } return TryGetTexture(Plugin.RuntimeMikuMaterial); } private static Texture TryGetTexture(Material material) { if ((Object)(object)material == (Object)null) { return null; } if (material.HasProperty("_BaseMap")) { Texture texture = material.GetTexture("_BaseMap"); if ((Object)(object)texture != (Object)null) { return texture; } } if (material.HasProperty("_MainTex")) { return material.GetTexture("_MainTex"); } return null; } private static bool TrySetTextureSafe(Material material, string propertyName, Texture texture) { if ((Object)(object)material == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName)) { return false; } try { material.SetTexture(propertyName, texture); return true; } catch (Exception ex) { Plugin.VerboseLog("[ItemPatch] Skip SetTexture on material '" + ((Object)material).name + "' property '" + propertyName + "': " + ex.Message); return false; } } private static void TrySetTextureTransformSafe(Material material, string propertyName, Vector2 scale, Vector2 offset) { //IL_001e: 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) if ((Object)(object)material == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName)) { return; } try { material.SetTextureScale(propertyName, scale); material.SetTextureOffset(propertyName, offset); } catch (Exception ex) { Plugin.VerboseLog("[ItemPatch] Skip texture transform on material '" + ((Object)material).name + "' property '" + propertyName + "': " + ex.Message); } } private static void ApplyMikuTextureSafe(Material material, Texture mikuTexture) { //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_004a: 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) if (!((Object)(object)material == (Object)null) && !((Object)(object)mikuTexture == (Object)null)) { if (TrySetTextureSafe(material, "_BaseMap", mikuTexture)) { TrySetTextureTransformSafe(material, "_BaseMap", Vector2.one, Vector2.zero); } if (TrySetTextureSafe(material, "_MainTex", mikuTexture)) { TrySetTextureTransformSafe(material, "_MainTex", Vector2.one, Vector2.zero); } } } private static void DisableOptionalSurfaceTextures(Material material) { if (!((Object)(object)material == (Object)null)) { TrySetTextureSafe(material, "_BumpMap", null); TrySetTextureSafe(material, "_NormalMap", null); TrySetTextureSafe(material, "_OcclusionMap", null); TrySetTextureSafe(material, "_MetallicGlossMap", null); TrySetTextureSafe(material, "_SpecGlossMap", null); material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } } private static void OptimizeTextureSampling(Texture texture) { Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (!((Object)(object)val == (Object)null)) { ((Texture)val).filterMode = (FilterMode)2; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).anisoLevel = Mathf.Max(((Texture)val).anisoLevel, 16); ((Texture)val).mipMapBias = Mathf.Min(((Texture)val).mipMapBias, -0.75f); } } private static void ApplyRealisticMaterialTuning(Material material) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { Color val = ResolveMaterialTint(material); val.a = 1f; if (material.HasProperty("_Tint")) { material.SetColor("_Tint", val); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", val); } if (material.HasProperty("_Color")) { material.SetColor("_Color", val); } if (material.HasProperty("_Smoothness")) { material.SetFloat("_Smoothness", 0.3f); } if (material.HasProperty("_Glossiness")) { material.SetFloat("_Glossiness", 0.3f); } if (material.HasProperty("_Metallic")) { material.SetFloat("_Metallic", 0f); } if (material.HasProperty("_BumpScale")) { material.SetFloat("_BumpScale", 0f); } if (material.HasProperty("_OcclusionStrength")) { material.SetFloat("_OcclusionStrength", 0f); } if (material.HasProperty("_SpecularHighlights")) { material.SetFloat("_SpecularHighlights", 0f); } if (material.HasProperty("_EnvironmentReflections")) { material.SetFloat("_EnvironmentReflections", 0f); } DisableOptionalSurfaceTextures(material); if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); material.DisableKeyword("_EMISSION"); } } } private static Material CreateFallbackMaterial() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("W/Peak_Standard"); if ((Object)(object)val == (Object)null) { return null; } return new Material(val) { color = Color.white }; } private static Color ResolveMaterialTint(Material material) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null) { return MikuMaterialTint; } if (material.HasProperty("_Tint")) { return material.GetColor("_Tint"); } if (material.HasProperty("_BaseColor")) { return material.GetColor("_BaseColor"); } if (material.HasProperty("_Color")) { return material.GetColor("_Color"); } return MikuMaterialTint; } private static void OptimizeMaterialTextureSampling(Material material) { OptimizeTextureSampling(TryGetTexture(material)); } private static Material CreateRendererMaterialInstance(Material template = null) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) template = template ?? Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial; bool flag = Plugin.RuntimeReplacementModel == null; if ((Object)(object)template == (Object)null) { Material val = CreateFallbackMaterial(); if ((Object)(object)val == (Object)null) { return null; } template = val; } Material val2; if (flag) { val2 = new Material(template); if ((Object)(object)val2.shader == (Object)null || !val2.shader.isSupported) { Material val3 = CreateFallbackMaterial(); if ((Object)(object)val3 != (Object)null) { Texture obj = TryGetTexture(template); Texture mikuTexture = GetMikuTexture(); if (obj == null) { obj = mikuTexture; } Texture val4 = obj; Color val5 = ResolveMaterialTint(template); val5.a = 1f; val2 = val3; if ((Object)(object)val4 != (Object)null) { OptimizeTextureSampling(val4); ApplyMikuTextureSafe(val2, val4); } if (val2.HasProperty("_Tint")) { val2.SetColor("_Tint", val5); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val5); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", val5); } } } } else { val2 = new Material(template); } if ((Object)(object)val2 == (Object)null) { return null; } ((Object)val2).name = (((Object)(object)template != (Object)null) ? ((Object)template).name : "MikuMaterial") + "_Runtime"; Texture val6 = (((Object)(object)template != (Object)null) ? TryGetTexture(template) : TryGetTexture(val2)); Texture mikuTexture2 = GetMikuTexture(); if ((Object)(object)val6 != (Object)null) { OptimizeTextureSampling(val6); ApplyMikuTextureSafe(val2, val6); } else if ((Object)(object)mikuTexture2 != (Object)null) { OptimizeTextureSampling(mikuTexture2); ApplyMikuTextureSafe(val2, mikuTexture2); } Color val7 = ResolveMaterialTint(template); val7.a = 1f; if (val2.HasProperty("_Tint")) { val2.SetColor("_Tint", val7); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val7); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", val7); } DisableOptionalSurfaceTextures(val2); if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 0f); } if (val2.HasProperty("_Blend")) { val2.SetFloat("_Blend", 0f); } if (val2.HasProperty("_ZWrite")) { val2.SetFloat("_ZWrite", 1f); } if (val2.HasProperty("_SrcBlend")) { val2.SetFloat("_SrcBlend", 1f); } if (val2.HasProperty("_DstBlend")) { val2.SetFloat("_DstBlend", 0f); } if (val2.HasProperty("_Cull")) { val2.SetFloat("_Cull", 0f); } if (val2.HasProperty("_AlphaClip")) { val2.SetFloat("_AlphaClip", 0f); } if (val2.HasProperty("_Cutoff")) { val2.SetFloat("_Cutoff", 0f); } if (val2.HasProperty("_LOD")) { val2.SetFloat("_LOD", 600f); } val2.renderQueue = 2000; val2.SetOverrideTag("RenderType", "Opaque"); val2.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); val2.EnableKeyword("_SURFACE_TYPE_OPAQUE"); val2.DisableKeyword("_ALPHATEST_ON"); val2.DisableKeyword("_ALPHABLEND_ON"); val2.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val2.DisableKeyword("LOD_FADE_CROSSFADE"); ApplyRealisticMaterialTuning(val2); return val2; } private static Material[] BuildMaterialArray(Material[] sourceMaterials, int subMeshCount) { int num = Mathf.Max(1, subMeshCount); Material[] array = (Material[])(object)new Material[num]; for (int i = 0; i < num; i++) { Material val = CreateRendererMaterialInstance((sourceMaterials != null && i < sourceMaterials.Length) ? sourceMaterials[i] : null); if ((Object)(object)val == (Object)null) { val = CreateFallbackMaterial(); } if ((Object)(object)val != (Object)null) { Texture val2 = TryGetTexture(val); if ((Object)(object)val2 == (Object)null) { Texture mikuTexture = GetMikuTexture(); if ((Object)(object)mikuTexture != (Object)null) { OptimizeTextureSampling(mikuTexture); ApplyMikuTextureSafe(val, mikuTexture); } } else { OptimizeTextureSampling(val2); } DisableOptionalSurfaceTextures(val); ApplyRealisticMaterialTuning(val); } array[i] = val; } return array; } private static Material ResolveRendererMaterialSlot(Material[] sourceMaterials, Material[] runtimeTemplateMaterials, int index, Material lastResolvedMaterial) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown Material val = ((sourceMaterials != null && index < sourceMaterials.Length) ? sourceMaterials[index] : null); if ((Object)(object)val != (Object)null) { return val; } Material val2 = ((runtimeTemplateMaterials.Length != 0) ? runtimeTemplateMaterials[Mathf.Min(index, runtimeTemplateMaterials.Length - 1)] : null); Material val3 = CreateRendererMaterialInstance(val2); if ((Object)(object)val3 == (Object)null && (Object)(object)val2 != (Object)null) { val3 = new Material(val2); } if ((Object)(object)val3 != (Object)null) { return val3; } if ((Object)(object)lastResolvedMaterial != (Object)null) { return lastResolvedMaterial; } Material val4 = Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial; if ((Object)(object)val4 != (Object)null) { val3 = CreateRendererMaterialInstance(val4); if ((Object)(object)val3 == (Object)null) { val3 = new Material(val4); } } return val3 ?? CreateFallbackMaterial(); } private static Material[] NormalizeRuntimeMaterialArray(Material[] sourceMaterials, int subMeshCount) { int num = Mathf.Max(1, subMeshCount); Material[] array = (Material[])(object)new Material[num]; Material[] runtimeTemplateMaterials = ((Plugin.RuntimeReplacementModel != null) ? Plugin.RuntimeReplacementModel.Materials : Array.Empty()); Material lastResolvedMaterial = null; for (int i = 0; i < num; i++) { Material val = (array[i] = ResolveRendererMaterialSlot(sourceMaterials, runtimeTemplateMaterials, i, lastResolvedMaterial)); if ((Object)(object)val != (Object)null) { lastResolvedMaterial = val; } } return array; } private static int GetRendererSubMeshCount(Renderer renderer) { MeshRenderer val = (MeshRenderer)(object)((renderer is MeshRenderer) ? renderer : null); if (val != null) { MeshFilter component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) { return Mathf.Max(1, component.sharedMesh.subMeshCount); } } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val2 != null && (Object)(object)val2.sharedMesh != (Object)null) { return Mathf.Max(1, val2.sharedMesh.subMeshCount); } return 0; } private static string GetTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return ""; } List list = new List(); Transform val = transform; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list.ToArray()); } private static bool ShouldNormalizeRuntimeMaterialArray(Material[] materials, int subMeshCount) { if (subMeshCount <= 0) { return false; } if (materials == null || materials.Length != subMeshCount) { return true; } for (int i = 0; i < materials.Length; i++) { if ((Object)(object)materials[i] == (Object)null) { return true; } } return false; } internal static bool NormalizeRuntimeRendererMaterials(Renderer renderer, string context) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return false; } int rendererSubMeshCount = GetRendererSubMeshCount(renderer); if (rendererSubMeshCount <= 0) { return false; } Material[] sharedMaterials; try { sharedMaterials = renderer.sharedMaterials; } catch (Exception ex) { Plugin.VerboseLog("[ItemPatch] Failed to inspect renderer materials at " + context + ": " + ex.Message); return false; } if (!ShouldNormalizeRuntimeMaterialArray(sharedMaterials, rendererSubMeshCount)) { return false; } int num = ((sharedMaterials != null) ? sharedMaterials.Length : 0); try { renderer.sharedMaterials = NormalizeRuntimeMaterialArray(sharedMaterials, rendererSubMeshCount); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[ItemPatch] Failed to correct renderer material layout at " + context + ": path=" + GetTransformPath(((Component)renderer).transform) + ", error=" + ex2.Message)); return false; } SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val != null && (Object)(object)val.sharedMesh != (Object)null) { Bounds bounds = val.sharedMesh.bounds; ((Bounds)(ref bounds)).Expand(0.5f); ((Renderer)val).localBounds = bounds; } int instanceID = ((Object)renderer).GetInstanceID(); if (!LoggedRuntimeRendererMaterialWarnings.Contains(instanceID) && Plugin.Log != null) { LoggedRuntimeRendererMaterialWarnings.Add(instanceID); Plugin.VerboseLog("[ItemPatch] Corrected runtime renderer material layout at " + context + ": path=" + GetTransformPath(((Component)renderer).transform) + ", type=" + ((object)renderer).GetType().Name + ", subMeshes=" + rendererSubMeshCount + ", sharedMaterials(before)=" + num + ", sharedMaterials(after)=" + renderer.sharedMaterials.Length); } return true; } internal static int NormalizeRuntimeRendererMaterials(Renderer[] renderers, string context) { if (renderers == null || renderers.Length == 0) { return 0; } int num = 0; for (int i = 0; i < renderers.Length; i++) { if (NormalizeRuntimeRendererMaterials(renderers[i], context)) { num++; } } return num; } internal static void SanitizeLoadedPrefabRendererMaterials(GameObject prefabRoot, string context) { if (!((Object)(object)prefabRoot == (Object)null)) { int num = NormalizeRuntimeRendererMaterials(prefabRoot.GetComponentsInChildren(true), context); if (num > 0) { Plugin.VerboseLog("[ItemPatch] Corrected " + num.ToString(CultureInfo.InvariantCulture) + " prefab renderer material layouts at " + context + " for " + ((Object)prefabRoot).name); } } } private static void ApplyMaterialToMeshRenderer(MeshRenderer renderer) { if (Plugin.RuntimeReplacementModel != null) { NormalizeRuntimeRendererMaterials((Renderer)(object)renderer, "ApplyMaterialToMeshRenderer"); return; } int subMeshCount = 1; MeshFilter component = ((Component)renderer).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) { subMeshCount = Mathf.Max(1, component.sharedMesh.subMeshCount); } ((Renderer)renderer).sharedMaterials = BuildMaterialArray(((Renderer)renderer).sharedMaterials, subMeshCount); } private static void ApplyMaterialToSkinnedRenderer(SkinnedMeshRenderer renderer) { //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_0070: Unknown result type (might be due to invalid IL or missing references) if (Plugin.RuntimeReplacementModel != null) { NormalizeRuntimeRendererMaterials((Renderer)(object)renderer, "ApplyMaterialToSkinnedRenderer"); } else { int subMeshCount = 1; if ((Object)(object)renderer.sharedMesh != (Object)null) { subMeshCount = Mathf.Max(1, renderer.sharedMesh.subMeshCount); } ((Renderer)renderer).sharedMaterials = BuildMaterialArray(((Renderer)renderer).sharedMaterials, subMeshCount); } if ((Object)(object)renderer.sharedMesh != (Object)null) { Bounds bounds = renderer.sharedMesh.bounds; ((Bounds)(ref bounds)).Expand(0.5f); ((Renderer)renderer).localBounds = bounds; } } private static bool HasVisibleReplacementRenderers(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return false; } Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { continue; } for (int j = 0; j < sharedMaterials.Length; j++) { if ((Object)(object)sharedMaterials[j] != (Object)null) { return true; } } } return false; } private static void DisableOriginalRenderers(Item item) { Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.forceRenderingOff = true; val.enabled = false; } } } private static void EnableOriginalRenderers(Item item) { Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.forceRenderingOff = false; val.enabled = true; } } } private static void EnableOriginalColliders(Item item) { Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); List list = new List(); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.enabled = true; list.Add(val); } } if ((Object)(object)item != (Object)null) { item.colliders = list.ToArray(); } } private static void DisableOriginalColliders(Item item) { Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.enabled = false; } } } private static Collider FindColliderTemplate(Item item) { if ((Object)(object)item == (Object)null) { return null; } Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null && !IsMikuTransform(((Component)val).transform)) { return val; } } return null; } private static Vector3 ClampColliderSize(Vector3 size) { //IL_0000: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) return new Vector3(Mathf.Max(size.x, 0.02f), Mathf.Max(size.y, 0.02f), Mathf.Max(size.z, 0.02f)); } private static bool HasNegativeScaleInHierarchy(Transform transform) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0025: Unknown result type (might be due to invalid IL or missing references) Transform val = transform; while ((Object)(object)val != (Object)null) { Vector3 localScale = val.localScale; if (localScale.x < 0f || localScale.y < 0f || localScale.z < 0f) { return true; } val = val.parent; } return false; } private static void CopyColliderSettings(Collider source, Collider target) { if (!((Object)(object)target == (Object)null)) { if ((Object)(object)source != (Object)null) { target.isTrigger = source.isTrigger; target.sharedMaterial = source.sharedMaterial; target.contactOffset = source.contactOffset; } target.enabled = true; } } private static Collider AddConvexMeshColliderForMeshRenderer(MeshRenderer renderer, Collider templateCollider) { if ((Object)(object)renderer == (Object)null) { return null; } MeshFilter component = ((Component)renderer).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { return null; } MeshCollider val = ((Component)renderer).gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)renderer).gameObject.AddComponent(); } val.sharedMesh = null; val.convex = true; val.sharedMesh = component.sharedMesh; CopyColliderSettings(templateCollider, (Collider)(object)val); return (Collider)(object)val; } private static Collider AddBoxColliderForMeshRenderer(MeshRenderer renderer, Collider templateCollider) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return null; } if (HasNegativeScaleInHierarchy(((Component)renderer).transform)) { return null; } MeshFilter component = ((Component)renderer).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { return null; } Bounds bounds = component.sharedMesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude <= 0f) { return null; } BoxCollider val = ((Component)renderer).gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)renderer).gameObject.AddComponent(); } val.center = ((Bounds)(ref bounds)).center; val.size = ClampColliderSize(((Bounds)(ref bounds)).size); CopyColliderSettings(templateCollider, (Collider)(object)val); return (Collider)(object)val; } private static Collider AddBoxColliderForSkinnedRenderer(SkinnedMeshRenderer renderer, Collider templateCollider) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return null; } if (HasNegativeScaleInHierarchy(((Component)renderer).transform)) { return null; } Bounds val = ((Renderer)renderer).localBounds; Vector3 size = ((Bounds)(ref val)).size; if (((Vector3)(ref size)).sqrMagnitude <= 0f && (Object)(object)renderer.sharedMesh != (Object)null) { val = renderer.sharedMesh.bounds; } size = ((Bounds)(ref val)).size; if (((Vector3)(ref size)).sqrMagnitude <= 0f) { return null; } BoxCollider val2 = ((Component)renderer).gameObject.GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)renderer).gameObject.AddComponent(); } val2.center = ((Bounds)(ref val)).center; val2.size = ClampColliderSize(((Bounds)(ref val)).size); CopyColliderSettings(templateCollider, (Collider)(object)val2); return (Collider)(object)val2; } private static void EncapsulateBoundsCorners(ref Bounds aggregateBounds, ref bool hasBounds, Transform root, Bounds rendererBounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) Vector3 center = ((Bounds)(ref rendererBounds)).center; Vector3 extents = ((Bounds)(ref rendererBounds)).extents; Vector3[] array = (Vector3[])(object)new Vector3[8] { center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z), center + new Vector3(0f - extents.x, 0f - extents.y, extents.z), center + new Vector3(0f - extents.x, extents.y, 0f - extents.z), center + new Vector3(0f - extents.x, extents.y, extents.z), center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z), center + new Vector3(extents.x, 0f - extents.y, extents.z), center + new Vector3(extents.x, extents.y, 0f - extents.z), center + new Vector3(extents.x, extents.y, extents.z) }; for (int i = 0; i < array.Length; i++) { Vector3 val = root.InverseTransformPoint(array[i]); if (!hasBounds) { aggregateBounds = new Bounds(val, Vector3.zero); hasBounds = true; } else { ((Bounds)(ref aggregateBounds)).Encapsulate(val); } } } private static Collider AddFallbackRootCollider(Transform mikuRoot, Collider templateCollider) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mikuRoot == (Object)null) { return null; } Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); Bounds aggregateBounds = default(Bounds); bool hasBounds = false; foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { EncapsulateBoundsCorners(ref aggregateBounds, ref hasBounds, mikuRoot, val.bounds); } } if (!hasBounds) { return null; } BoxCollider val2 = ((Component)mikuRoot).gameObject.GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)mikuRoot).gameObject.AddComponent(); } val2.center = ((Bounds)(ref aggregateBounds)).center; val2.size = ClampColliderSize(((Bounds)(ref aggregateBounds)).size); CopyColliderSettings(templateCollider, (Collider)(object)val2); return (Collider)(object)val2; } private static Collider AddFallbackProxyBoundsCollider(Transform proxyRoot, Collider templateCollider, Bounds localBounds) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)proxyRoot == (Object)null) { return null; } BoxCollider val = ((Component)proxyRoot).gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)proxyRoot).gameObject.AddComponent(); } val.center = ((Bounds)(ref localBounds)).center; val.size = ClampColliderSize(((Bounds)(ref localBounds)).size); CopyColliderSettings(templateCollider, (Collider)(object)val); return (Collider)(object)val; } private static Transform EnsureCollisionProxyRoot(Item item, Transform mikuRoot) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || (Object)(object)mikuRoot == (Object)null) { return null; } Transform val = FindMikuCollisionRoot(item); if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject("MikuCollisionProxy"); val = val2.transform; val.SetParent(((Component)item).transform, false); val2.AddComponent(); } SyncCollisionProxyRootTransform(val, item, mikuRoot); return val; } private static void SyncCollisionProxyRootTransform(Transform proxyRoot, Item item, Transform mikuRoot) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)proxyRoot == (Object)null || (Object)(object)item == (Object)null || (Object)(object)mikuRoot == (Object)null) { return; } int layer = DetermineTargetLayer(item); ((Component)proxyRoot).gameObject.layer = layer; proxyRoot.localPosition = mikuRoot.localPosition; proxyRoot.localRotation = mikuRoot.localRotation; Vector3 localScale = mikuRoot.localScale; proxyRoot.localScale = new Vector3(Mathf.Abs(localScale.x), Mathf.Abs(localScale.y), Mathf.Abs(localScale.z)); Transform[] componentsInChildren = ((Component)proxyRoot).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.layer = layer; } } if (!((Component)proxyRoot).gameObject.activeSelf) { ((Component)proxyRoot).gameObject.SetActive(true); } } private static Transform GetOrCreateCollisionShape(Transform root, string name) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(name)) { return null; } Transform val = root.Find(name); if ((Object)(object)val != (Object)null) { return val; } val = new GameObject(name).transform; val.SetParent(root, false); ((Component)val).gameObject.layer = ((Component)root).gameObject.layer; return val; } private static T GetOrAddCollider(GameObject gameObject) where T : Collider { if ((Object)(object)gameObject == (Object)null) { return default(T); } T val = gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = gameObject.AddComponent(); } return val; } private static void RemoveUnexpectedColliders(GameObject gameObject) where T : Collider { if ((Object)(object)gameObject == (Object)null) { return; } Collider[] components = gameObject.GetComponents(); foreach (Collider val in components) { if ((Object)(object)val != (Object)null && !(val is T)) { Object.Destroy((Object)(object)val); } } } private static Transform FindBoneTransform(Transform mikuRoot, params string[] names) { if ((Object)(object)mikuRoot == (Object)null || names == null || names.Length == 0) { return null; } Transform[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); foreach (string text in names) { if (string.IsNullOrEmpty(text)) { continue; } foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, text, StringComparison.OrdinalIgnoreCase)) { return val; } } } return null; } private static Vector3 GetProxyLocalPoint(Transform proxyRoot, Transform target, Vector3 fallback) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)proxyRoot != (Object)null) || !((Object)(object)target != (Object)null)) { return fallback; } return proxyRoot.InverseTransformPoint(target.position); } private static void SetCollisionShapeActive(Transform shape, bool active) { if ((Object)(object)shape != (Object)null && ((Component)shape).gameObject.activeSelf != active) { ((Component)shape).gameObject.SetActive(active); } } private static void DisableCollisionShape(Transform proxyRoot, string shapeName) { if (!((Object)(object)proxyRoot == (Object)null) && !string.IsNullOrEmpty(shapeName)) { Transform val = proxyRoot.Find(shapeName); if ((Object)(object)val != (Object)null) { SetCollisionShapeActive(val, active: false); } } } private static void UpdateHeadCollision(Transform proxyRoot, Collider templateCollider, Vector3 headLocal, Vector3 neckLocal, float shoulderWidth) { //IL_0016: 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_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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Transform orCreateCollisionShape = GetOrCreateCollisionShape(proxyRoot, "Head"); if (!((Object)(object)orCreateCollisionShape == (Object)null)) { Vector3 val = headLocal - neckLocal; if (((Vector3)(ref val)).sqrMagnitude <= 1E-06f) { val = Vector3.up; } float num = Mathf.Max(new float[3] { Vector3.Distance(headLocal, neckLocal) * 0.72f, shoulderWidth * 0.2f, 0.05f }); orCreateCollisionShape.localPosition = Vector3.Lerp(neckLocal, headLocal, 0.56f) + ((Vector3)(ref val)).normalized * (num * 0.06f); orCreateCollisionShape.localRotation = Quaternion.identity; orCreateCollisionShape.localScale = Vector3.one; RemoveUnexpectedColliders(((Component)orCreateCollisionShape).gameObject); SphereCollider orAddCollider = GetOrAddCollider(((Component)orCreateCollisionShape).gameObject); orAddCollider.center = Vector3.zero; orAddCollider.radius = num; CopyColliderSettings(templateCollider, (Collider)(object)orAddCollider); SetCollisionShapeActive(orCreateCollisionShape, active: true); } } private static void UpdateSphereCollision(Transform proxyRoot, Collider templateCollider, string shapeName, Vector3 centerLocal, float radius) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Transform orCreateCollisionShape = GetOrCreateCollisionShape(proxyRoot, shapeName); if (!((Object)(object)orCreateCollisionShape == (Object)null)) { orCreateCollisionShape.localPosition = centerLocal; orCreateCollisionShape.localRotation = Quaternion.identity; orCreateCollisionShape.localScale = Vector3.one; RemoveUnexpectedColliders(((Component)orCreateCollisionShape).gameObject); SphereCollider orAddCollider = GetOrAddCollider(((Component)orCreateCollisionShape).gameObject); orAddCollider.center = Vector3.zero; orAddCollider.radius = Mathf.Max(radius, 0.02f); CopyColliderSettings(templateCollider, (Collider)(object)orAddCollider); SetCollisionShapeActive(orCreateCollisionShape, active: true); } } private static void UpdateCapsuleCollision(Transform proxyRoot, Collider templateCollider, string shapeName, Vector3 startLocal, Vector3 endLocal, float radius) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) Transform orCreateCollisionShape = GetOrCreateCollisionShape(proxyRoot, shapeName); if (!((Object)(object)orCreateCollisionShape == (Object)null)) { Vector3 val = endLocal - startLocal; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude <= 0.0001f) { SetCollisionShapeActive(orCreateCollisionShape, active: false); return; } orCreateCollisionShape.localPosition = (startLocal + endLocal) * 0.5f; orCreateCollisionShape.localRotation = Quaternion.FromToRotation(Vector3.up, ((Vector3)(ref val)).normalized); orCreateCollisionShape.localScale = Vector3.one; RemoveUnexpectedColliders(((Component)orCreateCollisionShape).gameObject); CapsuleCollider orAddCollider = GetOrAddCollider(((Component)orCreateCollisionShape).gameObject); orAddCollider.center = Vector3.zero; orAddCollider.direction = 1; orAddCollider.radius = Mathf.Max(radius, 0.02f); orAddCollider.height = Mathf.Max(magnitude + orAddCollider.radius * 2f, orAddCollider.radius * 2f); CopyColliderSettings(templateCollider, (Collider)(object)orAddCollider); SetCollisionShapeActive(orCreateCollisionShape, active: true); } } private static void UpdateBodyCollision(Transform proxyRoot, Collider templateCollider, Vector3 neckLocal, Vector3 chestLocal, Vector3 hipLocal, Vector3 thighMidLocal, float shoulderWidth, float hipWidth, float bodyDepth) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) Transform orCreateCollisionShape = GetOrCreateCollisionShape(proxyRoot, "Torso"); if (!((Object)(object)orCreateCollisionShape == (Object)null)) { float radius = Mathf.Max(new float[4] { shoulderWidth * 0.13f, hipWidth * 0.12f, bodyDepth * 0.2f, 0.035f }); Vector3 startLocal = Vector3.Lerp(neckLocal, chestLocal, 0.28f); Vector3 endLocal = Vector3.Lerp(chestLocal, hipLocal, 0.24f); UpdateCapsuleCollision(proxyRoot, templateCollider, ((Object)orCreateCollisionShape).name, startLocal, endLocal, radius); float radius2 = Mathf.Max(new float[3] { hipWidth * 0.15f, bodyDepth * 0.16f, 0.03f }); Vector3 centerLocal = Vector3.Lerp(hipLocal, thighMidLocal, 0.12f); UpdateSphereCollision(proxyRoot, templateCollider, "LowerBody", centerLocal, radius2); } } private static void UpdateLimbCollision(Transform proxyRoot, Collider templateCollider, string shapeName, Vector3 startLocal, Vector3 endLocal, float radius) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) Transform orCreateCollisionShape = GetOrCreateCollisionShape(proxyRoot, shapeName); if (!((Object)(object)orCreateCollisionShape == (Object)null)) { Vector3 val = endLocal - startLocal; if (((Vector3)(ref val)).magnitude <= 0.0001f) { SetCollisionShapeActive(orCreateCollisionShape, active: false); return; } Vector3 startLocal2 = Vector3.Lerp(startLocal, endLocal, 0.08f); Vector3 endLocal2 = Vector3.Lerp(endLocal, startLocal, 0.08f); UpdateCapsuleCollision(proxyRoot, templateCollider, shapeName, startLocal2, endLocal2, radius); } } private static bool RendererMatchesAnyKeyword(Renderer renderer, string[] keywords) { if ((Object)(object)renderer == (Object)null || keywords == null || keywords.Length == 0) { return false; } Transform val = ((Component)renderer).transform; while ((Object)(object)val != (Object)null) { if (ContainsKeyword(((Object)val).name, keywords)) { return true; } val = val.parent; } return false; } private static bool ShouldUseRendererForCollisionBounds(Renderer renderer) { if ((Object)(object)renderer == (Object)null) { return false; } if ((Object)(object)((Component)renderer).GetComponent() != (Object)null) { return false; } return !RendererMatchesAnyKeyword(renderer, CollisionExcludedRendererKeywords); } private static bool TryGetAggregateRendererBoundsLocal(Transform sourceRoot, Transform targetSpace, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); if ((Object)(object)sourceRoot == (Object)null || (Object)(object)targetSpace == (Object)null) { return false; } Renderer[] componentsInChildren = ((Component)sourceRoot).GetComponentsInChildren(true); bool hasBounds = false; foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { EncapsulateBoundsCorners(ref bounds, ref hasBounds, targetSpace, val.bounds); } } return hasBounds; } private static bool TryGetBodyRendererBoundsLocal(Transform sourceRoot, Transform targetSpace, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); if ((Object)(object)sourceRoot == (Object)null || (Object)(object)targetSpace == (Object)null) { return false; } Renderer[] componentsInChildren = ((Component)sourceRoot).GetComponentsInChildren(true); bool hasBounds = false; foreach (Renderer val in componentsInChildren) { if (ShouldUseRendererForCollisionBounds(val)) { EncapsulateBoundsCorners(ref bounds, ref hasBounds, targetSpace, val.bounds); } } if (!hasBounds) { return TryGetAggregateRendererBoundsLocal(sourceRoot, targetSpace, out bounds); } return true; } private static bool IsFiniteVector3(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsNaN(value.y) && !float.IsNaN(value.z) && !float.IsInfinity(value.x) && !float.IsInfinity(value.y)) { return !float.IsInfinity(value.z); } return false; } private static Vector3 ResolveValidatedLocalPoint(Transform proxyRoot, Transform bone, Vector3 fallback, Bounds bodyBounds) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)proxyRoot == (Object)null || (Object)(object)bone == (Object)null) { return fallback; } Vector3 val = proxyRoot.InverseTransformPoint(bone.position); if (!IsFiniteVector3(val)) { return fallback; } Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Mathf.Max(((Bounds)(ref bodyBounds)).size.x * 0.55f, 0.08f), Mathf.Max(((Bounds)(ref bodyBounds)).size.y * 0.3f, 0.08f), Mathf.Max(((Bounds)(ref bodyBounds)).size.z * 0.8f, 0.08f)); Vector3 val3 = ((Bounds)(ref bodyBounds)).min - val2; Vector3 val4 = ((Bounds)(ref bodyBounds)).max + val2; if (val.x < val3.x || val.x > val4.x || val.y < val3.y || val.y > val4.y || val.z < val3.z || val.z > val4.z) { return fallback; } return val; } private static void ResolveLimbEndpoints(Transform proxyRoot, Transform startBone, Transform endBone, Bounds bodyBounds, Vector3 fallbackStart, Vector3 fallbackEnd, bool expectDownward, float sideSign, out Vector3 startLocal, out Vector3 endLocal) { //IL_0004: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) startLocal = ResolveValidatedLocalPoint(proxyRoot, startBone, fallbackStart, bodyBounds); endLocal = ResolveValidatedLocalPoint(proxyRoot, endBone, fallbackEnd, bodyBounds); Vector3 val = endLocal - startLocal; float magnitude = ((Vector3)(ref val)).magnitude; float num = Mathf.Max(((Bounds)(ref bodyBounds)).size.y * 0.04f, 0.035f); float num2 = Mathf.Max(((Bounds)(ref bodyBounds)).size.y * 0.42f, 0.18f); float num3 = Mathf.Max(((Bounds)(ref bodyBounds)).size.x * 0.08f, 0.025f); bool flag = !IsFiniteVector3(startLocal) || !IsFiniteVector3(endLocal) || magnitude < num || magnitude > num2; if (!flag && expectDownward) { flag = endLocal.y > startLocal.y; } if (!flag && Mathf.Abs(sideSign) > 0.5f) { flag = ((!(sideSign < 0f)) ? (startLocal.x < 0f - num3 || endLocal.x < 0f - num3) : (startLocal.x > num3 || endLocal.x > num3)); } if (flag) { startLocal = fallbackStart; endLocal = fallbackEnd; } } private static Collider[] BuildCollisionProxy(Item item, Transform mikuRoot) { //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03f4: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0455: 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_0495: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_0519: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Unknown result type (might be due to invalid IL or missing references) //IL_052c: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_0548: Unknown result type (might be due to invalid IL or missing references) //IL_054a: Unknown result type (might be due to invalid IL or missing references) //IL_054c: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_0556: Unknown result type (might be due to invalid IL or missing references) //IL_0558: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_0566: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Unknown result type (might be due to invalid IL or missing references) //IL_056d: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Unknown result type (might be due to invalid IL or missing references) //IL_0574: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_057b: Unknown result type (might be due to invalid IL or missing references) //IL_0580: Unknown result type (might be due to invalid IL or missing references) //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_0597: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05a3: Unknown result type (might be due to invalid IL or missing references) //IL_05cd: Unknown result type (might be due to invalid IL or missing references) //IL_05cf: Unknown result type (might be due to invalid IL or missing references) //IL_061c: Unknown result type (might be due to invalid IL or missing references) //IL_061e: Unknown result type (might be due to invalid IL or missing references) //IL_0620: 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_062f: Unknown result type (might be due to invalid IL or missing references) //IL_0633: Unknown result type (might be due to invalid IL or missing references) //IL_0635: Unknown result type (might be due to invalid IL or missing references) //IL_0640: Unknown result type (might be due to invalid IL or missing references) //IL_0642: Unknown result type (might be due to invalid IL or missing references) //IL_0644: Unknown result type (might be due to invalid IL or missing references) //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_06d1: Unknown result type (might be due to invalid IL or missing references) //IL_06fe: Unknown result type (might be due to invalid IL or missing references) //IL_0703: Unknown result type (might be due to invalid IL or missing references) //IL_0708: Unknown result type (might be due to invalid IL or missing references) //IL_070a: Unknown result type (might be due to invalid IL or missing references) //IL_0736: Unknown result type (might be due to invalid IL or missing references) //IL_073b: Unknown result type (might be due to invalid IL or missing references) //IL_0740: Unknown result type (might be due to invalid IL or missing references) //IL_0742: Unknown result type (might be due to invalid IL or missing references) //IL_0772: Unknown result type (might be due to invalid IL or missing references) //IL_0777: 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_077e: Unknown result type (might be due to invalid IL or missing references) //IL_07ad: Unknown result type (might be due to invalid IL or missing references) //IL_07b2: Unknown result type (might be due to invalid IL or missing references) //IL_07b7: Unknown result type (might be due to invalid IL or missing references) //IL_07be: Unknown result type (might be due to invalid IL or missing references) //IL_07c0: Unknown result type (might be due to invalid IL or missing references) //IL_07c2: Unknown result type (might be due to invalid IL or missing references) //IL_07d8: Unknown result type (might be due to invalid IL or missing references) //IL_07da: Unknown result type (might be due to invalid IL or missing references) //IL_07dc: Unknown result type (might be due to invalid IL or missing references) //IL_07f2: Unknown result type (might be due to invalid IL or missing references) //IL_07f4: Unknown result type (might be due to invalid IL or missing references) //IL_07f6: Unknown result type (might be due to invalid IL or missing references) //IL_080c: Unknown result type (might be due to invalid IL or missing references) //IL_080e: Unknown result type (might be due to invalid IL or missing references) //IL_0810: Unknown result type (might be due to invalid IL or missing references) //IL_0826: Unknown result type (might be due to invalid IL or missing references) //IL_0828: Unknown result type (might be due to invalid IL or missing references) //IL_082a: Unknown result type (might be due to invalid IL or missing references) //IL_0840: Unknown result type (might be due to invalid IL or missing references) //IL_0842: Unknown result type (might be due to invalid IL or missing references) //IL_0844: Unknown result type (might be due to invalid IL or missing references) //IL_085a: Unknown result type (might be due to invalid IL or missing references) //IL_085c: Unknown result type (might be due to invalid IL or missing references) //IL_085e: Unknown result type (might be due to invalid IL or missing references) //IL_0874: Unknown result type (might be due to invalid IL or missing references) //IL_0876: Unknown result type (might be due to invalid IL or missing references) //IL_0878: Unknown result type (might be due to invalid IL or missing references) //IL_0890: Unknown result type (might be due to invalid IL or missing references) //IL_0892: Unknown result type (might be due to invalid IL or missing references) //IL_08a2: Unknown result type (might be due to invalid IL or missing references) //IL_08a4: Unknown result type (might be due to invalid IL or missing references) //IL_08b4: Unknown result type (might be due to invalid IL or missing references) //IL_08b6: Unknown result type (might be due to invalid IL or missing references) //IL_08c6: Unknown result type (might be due to invalid IL or missing references) //IL_08c8: Unknown result type (might be due to invalid IL or missing references) //IL_08d8: Unknown result type (might be due to invalid IL or missing references) //IL_08da: Unknown result type (might be due to invalid IL or missing references) //IL_08ea: Unknown result type (might be due to invalid IL or missing references) //IL_08ec: Unknown result type (might be due to invalid IL or missing references) //IL_08fc: Unknown result type (might be due to invalid IL or missing references) //IL_08fe: Unknown result type (might be due to invalid IL or missing references) //IL_090e: Unknown result type (might be due to invalid IL or missing references) //IL_0910: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_097b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || (Object)(object)mikuRoot == (Object)null) { return Array.Empty(); } Transform val = EnsureCollisionProxyRoot(item, mikuRoot); if ((Object)(object)val == (Object)null) { return Array.Empty(); } Collider templateCollider = FindColliderTemplate(item); Transform bone = FindBoneTransform(mikuRoot, "頭", "Head"); Transform bone2 = FindBoneTransform(mikuRoot, "首", "Neck"); Transform bone3 = FindBoneTransform(mikuRoot, "上半身2", "上半身", "Chest", "Spine", "UpperChest"); Transform bone4 = FindBoneTransform(mikuRoot, "下半身", "センター", "Hips", "Pelvis", "Center"); Transform val2 = FindBoneTransform(mikuRoot, "左肩", "LeftShoulder"); Transform val3 = FindBoneTransform(mikuRoot, "右肩", "RightShoulder"); Transform val4 = FindBoneTransform(mikuRoot, "左ひじ", "LeftElbow"); Transform val5 = FindBoneTransform(mikuRoot, "右ひじ", "RightElbow"); Transform endBone = FindBoneTransform(mikuRoot, "左手首", "LeftHand", "LeftWrist"); Transform endBone2 = FindBoneTransform(mikuRoot, "右手首", "RightHand", "RightWrist"); Transform val6 = FindBoneTransform(mikuRoot, "左足", "LeftLeg", "LeftUpperLeg"); Transform val7 = FindBoneTransform(mikuRoot, "右足", "RightLeg", "RightUpperLeg"); Transform val8 = FindBoneTransform(mikuRoot, "左ひざ", "LeftKnee"); Transform val9 = FindBoneTransform(mikuRoot, "右ひざ", "RightKnee"); Transform val10 = FindBoneTransform(mikuRoot, "左足首", "LeftFoot", "LeftAnkle"); Transform val11 = FindBoneTransform(mikuRoot, "右足首", "RightFoot", "RightAnkle"); if (!TryGetBodyRendererBoundsLocal(mikuRoot, val, out var bounds)) { ((Bounds)(ref bounds))..ctor(new Vector3(0f, 0.02f, 0f), new Vector3(0.24f, 0.42f, 0.18f)); } Vector3 center = ((Bounds)(ref bounds)).center; float num = Mathf.Max(((Bounds)(ref bounds)).size.y, 0.28f); float num2 = Mathf.Max(((Bounds)(ref bounds)).size.x, 0.16f); float num3 = Mathf.Max(((Bounds)(ref bounds)).size.z, 0.12f); float y = ((Bounds)(ref bounds)).min.y; float y2 = ((Bounds)(ref bounds)).max.y; Vector3 fallback = default(Vector3); ((Vector3)(ref fallback))..ctor(center.x, y2 - num * 0.08f, center.z + num3 * 0.04f); Vector3 fallback2 = default(Vector3); ((Vector3)(ref fallback2))..ctor(center.x, y2 - num * 0.18f, center.z); Vector3 val12 = default(Vector3); ((Vector3)(ref val12))..ctor(center.x, center.y + num * 0.16f, center.z + num3 * 0.02f); Vector3 val13 = default(Vector3); ((Vector3)(ref val13))..ctor(center.x, center.y - num * 0.12f, center.z); float num4 = Mathf.Max(num2 * 0.26f, 0.05f); float num5 = Mathf.Max(num2 * 0.15f, 0.035f); Vector3 fallback3 = default(Vector3); ((Vector3)(ref fallback3))..ctor(0f - num4, val12.y + num * 0.08f, center.z); Vector3 fallback4 = default(Vector3); ((Vector3)(ref fallback4))..ctor(num4, val12.y + num * 0.08f, center.z); Vector3 fallback5 = default(Vector3); ((Vector3)(ref fallback5))..ctor(0f - num5, val13.y - num * 0.08f, center.z); Vector3 fallback6 = default(Vector3); ((Vector3)(ref fallback6))..ctor(num5, val13.y - num * 0.08f, center.z); Vector3 fallback7 = default(Vector3); ((Vector3)(ref fallback7))..ctor(0f - num5, y + num * 0.2f, center.z + num3 * 0.03f); Vector3 fallback8 = default(Vector3); ((Vector3)(ref fallback8))..ctor(num5, y + num * 0.2f, center.z + num3 * 0.03f); Vector3 fallback9 = default(Vector3); ((Vector3)(ref fallback9))..ctor(0f - num5, y + num * 0.05f, center.z + num3 * 0.12f); Vector3 fallback10 = default(Vector3); ((Vector3)(ref fallback10))..ctor(num5, y + num * 0.05f, center.z + num3 * 0.12f); Vector3 headLocal = ResolveValidatedLocalPoint(val, bone, fallback, bounds); Vector3 neckLocal = ResolveValidatedLocalPoint(val, bone2, fallback2, bounds); Vector3 chestLocal = ResolveValidatedLocalPoint(val, bone3, val12, bounds); Vector3 hipLocal = ResolveValidatedLocalPoint(val, bone4, val13, bounds); Vector3 val14 = ResolveValidatedLocalPoint(val, val2, fallback3, bounds); Vector3 val15 = ResolveValidatedLocalPoint(val, val3, fallback4, bounds); Vector3 val16 = ResolveValidatedLocalPoint(val, val6, fallback5, bounds); Vector3 val17 = ResolveValidatedLocalPoint(val, val7, fallback6, bounds); Vector3 val18 = ResolveValidatedLocalPoint(val, val8, fallback7, bounds); Vector3 val19 = ResolveValidatedLocalPoint(val, val9, fallback8, bounds); Vector3 fallbackEnd = ResolveValidatedLocalPoint(val, val10, fallback9, bounds); Vector3 fallbackEnd2 = ResolveValidatedLocalPoint(val, val11, fallback10, bounds); float num6 = Mathf.Max(new float[3] { Vector3.Distance(val14, val15), num2 * 0.4f, 0.12f }); float num7 = Mathf.Max(new float[3] { Vector3.Distance(val16, val17), num6 * 0.58f, 0.08f }); float num8 = Mathf.Max(new float[3] { num3 * 0.28f, num6 * 0.18f, 0.05f }); Vector3 thighMidLocal = (val16 + val17) * 0.5f; UpdateHeadCollision(val, templateCollider, headLocal, neckLocal, num6); UpdateBodyCollision(val, templateCollider, neckLocal, chestLocal, hipLocal, thighMidLocal, num6, num7, num8); float num9 = Mathf.Max(new float[3] { num8 * 0.08f, num6 * 0.038f, 0.015f }); float radius = Mathf.Max(num9 * 0.84f, 0.014f); float num10 = Mathf.Max(new float[3] { num7 * 0.085f, num8 * 0.12f, 0.022f }); float radius2 = Mathf.Max(num10 * 0.8f, 0.02f); Vector3 val20 = val14 + new Vector3(0f - Mathf.Max(num6 * 0.18f, 0.035f), 0f - Mathf.Max(num * 0.11f, 0.035f), 0f); Vector3 val21 = val15 + new Vector3(Mathf.Max(num6 * 0.18f, 0.035f), 0f - Mathf.Max(num * 0.11f, 0.035f), 0f); Vector3 fallbackEnd3 = val20 + new Vector3(0f - Mathf.Max(num6 * 0.14f, 0.028f), 0f - Mathf.Max(num * 0.08f, 0.025f), num8 * 0.12f); Vector3 fallbackEnd4 = val21 + new Vector3(Mathf.Max(num6 * 0.14f, 0.028f), 0f - Mathf.Max(num * 0.08f, 0.025f), num8 * 0.12f); ResolveLimbEndpoints(val, val2, val4, bounds, val14, val20, expectDownward: false, -1f, out var startLocal, out var endLocal); ResolveLimbEndpoints(val, val4, endBone, bounds, val20, fallbackEnd3, expectDownward: false, -1f, out var startLocal2, out var endLocal2); ResolveLimbEndpoints(val, val3, val5, bounds, val15, val21, expectDownward: false, 1f, out var startLocal3, out var endLocal3); ResolveLimbEndpoints(val, val5, endBone2, bounds, val21, fallbackEnd4, expectDownward: false, 1f, out var startLocal4, out var endLocal4); ResolveLimbEndpoints(val, val6, val8, bounds, val16, val18, expectDownward: true, -1f, out var startLocal5, out var endLocal5); ResolveLimbEndpoints(val, val8, val10, bounds, val18, fallbackEnd, expectDownward: true, -1f, out var startLocal6, out var endLocal6); ResolveLimbEndpoints(val, val7, val9, bounds, val17, val19, expectDownward: true, 1f, out var startLocal7, out var endLocal7); ResolveLimbEndpoints(val, val9, val11, bounds, val19, fallbackEnd2, expectDownward: true, 1f, out var startLocal8, out var endLocal8); UpdateLimbCollision(val, templateCollider, "LeftArm", startLocal, endLocal, num9); UpdateLimbCollision(val, templateCollider, "LeftForearm", startLocal2, endLocal2, radius); UpdateLimbCollision(val, templateCollider, "RightArm", startLocal3, endLocal3, num9); UpdateLimbCollision(val, templateCollider, "RightForearm", startLocal4, endLocal4, radius); UpdateLimbCollision(val, templateCollider, "LeftUpperLeg", startLocal5, endLocal5, num10); UpdateLimbCollision(val, templateCollider, "LeftLowerLeg", startLocal6, endLocal6, radius2); UpdateLimbCollision(val, templateCollider, "RightUpperLeg", startLocal7, endLocal7, num10); UpdateLimbCollision(val, templateCollider, "RightLowerLeg", startLocal8, endLocal8, radius2); Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); List list = new List(componentsInChildren.Length); foreach (Collider val22 in componentsInChildren) { if (!((Object)(object)val22 == (Object)null) && ((Component)val22).gameObject.activeInHierarchy) { val22.enabled = true; list.Add(val22); } } if (list.Count == 0) { Collider val23 = AddFallbackProxyBoundsCollider(val, templateCollider, bounds); if ((Object)(object)val23 != (Object)null) { list.Add(val23); } } if (list.Count <= 0) { return Array.Empty(); } return list.ToArray(); } private static void EnsureTwinTailCloth(Transform mikuRoot) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0177: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mikuRoot == (Object)null) { return; } SkinnedMeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null) { continue; } Mesh sharedMesh = val.sharedMesh; Cloth val2 = ((Component)val).GetComponent(); MikuTwinTailClothState mikuTwinTailClothState = ((Component)val).GetComponent(); if ((Object)(object)mikuTwinTailClothState == (Object)null) { mikuTwinTailClothState = ((Component)val).gameObject.AddComponent(); } if (Plugin.RuntimeReplacementModel == null && (Object)(object)val2 != (Object)null) { mikuTwinTailClothState.MeshInstanceId = ((Object)sharedMesh).GetInstanceID(); mikuTwinTailClothState.MovableVertexCount = CountMovableClothVertices(val2.coefficients); val2.enabled = true; Bounds localBounds = ((Renderer)val).localBounds; ((Bounds)(ref localBounds)).Expand(new Vector3(0.2f, 0.25f, 0.2f)); ((Renderer)val).localBounds = localBounds; Plugin.VerboseLog("[ItemPatch] Bundled Cloth active on renderer '" + ((Object)val).name + "' with movableVertices=" + mikuTwinTailClothState.MovableVertexCount); } else { if (!((Object)(object)val2 == (Object)null) && mikuTwinTailClothState.MeshInstanceId == ((Object)sharedMesh).GetInstanceID() && mikuTwinTailClothState.MovableVertexCount > 0) { continue; } int movableVertexCount; ClothSkinningCoefficient[] array = BuildTwinTailClothCoefficients(val, out movableVertexCount); if (array == null || movableVertexCount <= 0) { if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } continue; } if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } val2.coefficients = array; ApplyTwinTailClothTuning(val2); Bounds localBounds2 = ((Renderer)val).localBounds; ((Bounds)(ref localBounds2)).Expand(new Vector3(0.2f, 0.25f, 0.2f)); ((Renderer)val).localBounds = localBounds2; mikuTwinTailClothState.MeshInstanceId = ((Object)sharedMesh).GetInstanceID(); mikuTwinTailClothState.MovableVertexCount = movableVertexCount; } } } private static void ApplyTwinTailClothTuning(Cloth cloth) { //IL_0078: 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) if (!((Object)(object)cloth == (Object)null)) { cloth.enabled = true; cloth.useGravity = true; cloth.useTethers = true; cloth.stretchingStiffness = 0.98f; cloth.bendingStiffness = 0.9f; cloth.damping = 0.2f; cloth.friction = 0.2f; cloth.collisionMassScale = 0.06f; cloth.clothSolverFrequency = 36f; cloth.worldVelocityScale = 0.2f; cloth.worldAccelerationScale = 0.75f; cloth.externalAcceleration = Vector3.zero; cloth.randomAcceleration = Vector3.zero; cloth.sleepThreshold = 0f; cloth.selfCollisionDistance = 0.01f; cloth.selfCollisionStiffness = 0.1f; } } private static int CountMovableClothVertices(ClothSkinningCoefficient[] coefficients) { if (coefficients == null || coefficients.Length == 0) { return 0; } int num = 0; for (int i = 0; i < coefficients.Length; i++) { if (coefficients[i].maxDistance > 0.0001f) { num++; } } return num; } private static ClothSkinningCoefficient[] BuildTwinTailClothCoefficients(SkinnedMeshRenderer renderer, out int movableVertexCount) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) movableVertexCount = 0; if ((Object)(object)renderer == (Object)null || (Object)(object)renderer.sharedMesh == (Object)null) { return null; } Mesh sharedMesh = renderer.sharedMesh; if (!sharedMesh.isReadable) { return null; } BoneWeight[] boneWeights = sharedMesh.boneWeights; Transform[] bones = renderer.bones; int vertexCount = sharedMesh.vertexCount; if (vertexCount == 0 || boneWeights == null || boneWeights.Length != vertexCount || bones == null || bones.Length == 0) { return null; } ClothSkinningCoefficient[] array = (ClothSkinningCoefficient[])(object)new ClothSkinningCoefficient[vertexCount]; for (int i = 0; i < vertexCount; i++) { BoneWeight val = boneWeights[i]; float tailInfluence = 0f; float weightedDistance = 0f; float anchorInfluence = 0f; AccumulateTwinTailBoneInfluence(bones, ((BoneWeight)(ref val)).boneIndex0, ((BoneWeight)(ref val)).weight0, ref tailInfluence, ref weightedDistance, ref anchorInfluence); AccumulateTwinTailBoneInfluence(bones, ((BoneWeight)(ref val)).boneIndex1, ((BoneWeight)(ref val)).weight1, ref tailInfluence, ref weightedDistance, ref anchorInfluence); AccumulateTwinTailBoneInfluence(bones, ((BoneWeight)(ref val)).boneIndex2, ((BoneWeight)(ref val)).weight2, ref tailInfluence, ref weightedDistance, ref anchorInfluence); AccumulateTwinTailBoneInfluence(bones, ((BoneWeight)(ref val)).boneIndex3, ((BoneWeight)(ref val)).weight3, ref tailInfluence, ref weightedDistance, ref anchorInfluence); ClothSkinningCoefficient val2 = default(ClothSkinningCoefficient); val2.maxDistance = 0f; val2.collisionSphereDistance = float.MaxValue; ClothSkinningCoefficient val3 = val2; if (tailInfluence >= 0.12f) { float num = weightedDistance / Mathf.Max(tailInfluence, 0.0001f); float num2 = Mathf.Clamp01((tailInfluence - 0.12f) / 0.88f); float num3 = 1f - Mathf.Clamp01(anchorInfluence * 0.85f); float num4 = num * Mathf.Lerp(0.35f, 1f, num2) * num3; if (num4 >= 0.015f) { val3.maxDistance = Mathf.Clamp(num4, 0.02f, 0.78f); movableVertexCount++; } } array[i] = val3; } return array; } private static void AccumulateTwinTailBoneInfluence(Transform[] bones, int boneIndex, float boneWeight, ref float tailInfluence, ref float weightedDistance, ref float anchorInfluence) { if (bones == null || boneWeight <= 0f || boneIndex < 0 || boneIndex >= bones.Length) { return; } Transform val = bones[boneIndex]; if (!((Object)(object)val == (Object)null) && TryParseTwinTailBoneName(((Object)val).name, out var chainIndex)) { switch (chainIndex) { case 2: anchorInfluence += boneWeight; break; case 3: case 4: case 5: case 6: case 7: case 8: case 9: tailInfluence += boneWeight; weightedDistance += boneWeight * ResolveTwinTailDistance(chainIndex); break; } } } private static bool TryParseTwinTailBoneName(string boneName, out int chainIndex) { chainIndex = -1; if (string.IsNullOrEmpty(boneName)) { return false; } string[] array = boneName.Split(new char[1] { '.' }); if (array.Length != 3 || !string.Equals(array[0], "hair", StringComparison.OrdinalIgnoreCase)) { return false; } if (!int.TryParse(array[1], out chainIndex)) { return false; } if (array[2].Length == 1) { if (array[2][0] != 'L' && array[2][0] != 'l' && array[2][0] != 'R') { return array[2][0] == 'r'; } return true; } return false; } private static float ResolveTwinTailDistance(int chainIndex) { return chainIndex switch { 3 => 0.05f, 4 => 0.1f, 5 => 0.18f, 6 => 0.3f, 7 => 0.45f, 8 => 0.6f, 9 => 0.78f, _ => 0f, }; } private static void BindTwinTailClothCollisionSources(Transform mikuRoot, Transform collisionRoot) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mikuRoot == (Object)null || Plugin.RuntimeReplacementModel == null) { return; } Cloth[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); foreach (Cloth val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } if ((Object)(object)collisionRoot == (Object)null) { val.sphereColliders = Array.Empty(); val.capsuleColliders = Array.Empty(); continue; } SphereCollider[] componentsInChildren2 = ((Component)collisionRoot).GetComponentsInChildren(true); List list = new List(componentsInChildren2.Length); foreach (SphereCollider val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null && ((Collider)val2).enabled) { list.Add(new ClothSphereColliderPair(val2)); } } CapsuleCollider[] componentsInChildren3 = ((Component)collisionRoot).GetComponentsInChildren(true); List list2 = new List(componentsInChildren3.Length); foreach (CapsuleCollider val3 in componentsInChildren3) { if ((Object)(object)val3 != (Object)null && ((Collider)val3).enabled) { list2.Add(val3); } } val.sphereColliders = ((list.Count > 0) ? list.ToArray() : Array.Empty()); val.capsuleColliders = ((list2.Count > 0) ? list2.ToArray() : Array.Empty()); } } private static void RebuildModelColliders(Item item, Transform mikuRoot) { if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null)) { Transform val = FindMikuCollisionRoot(item); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } Collider[] array = BuildCollisionProxy(item, mikuRoot); if (array.Length != 0) { item.colliders = array; DisableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, FindMikuCollisionRoot(item)); } else { EnableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, null); } } } private static Collider[] GetUsableProxyColliders(Transform proxyRoot) { if ((Object)(object)proxyRoot == (Object)null) { return Array.Empty(); } Collider[] componentsInChildren = ((Component)proxyRoot).GetComponentsInChildren(true); List list = new List(componentsInChildren.Length); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { list.Add(val); } } if (list.Count <= 0) { return Array.Empty(); } return list.ToArray(); } private static void EnsureModelColliders(Item item, Transform mikuRoot) { if ((Object)(object)item == (Object)null || (Object)(object)mikuRoot == (Object)null) { return; } Transform val = FindMikuCollisionRoot(item); if ((Object)(object)val != (Object)null) { SyncCollisionProxyRootTransform(val, item, mikuRoot); Collider[] usableProxyColliders = GetUsableProxyColliders(val); if (usableProxyColliders.Length != 0) { SetColliderArrayEnabled(usableProxyColliders, enabled: true); item.colliders = usableProxyColliders; DisableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, val); return; } } Collider[] array = BuildCollisionProxy(item, mikuRoot); if (array.Length != 0) { item.colliders = array; DisableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, FindMikuCollisionRoot(item)); } else { EnableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, null); } } private static void SetColliderArrayEnabled(Collider[] colliders, bool enabled) { if (colliders == null) { return; } foreach (Collider val in colliders) { if (!((Object)(object)val == (Object)null)) { val.enabled = enabled; } } } private static void SyncCollidersByState(Item item, Transform mikuRoot) { if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null)) { Transform val = FindMikuCollisionRoot(item); Collider[] colliders = (((Object)(object)val != (Object)null) ? GetUsableProxyColliders(val) : Array.Empty()); if ((Object)(object)val != (Object)null) { SyncCollisionProxyRootTransform(val, item, mikuRoot); } if (IsHeld(item)) { SetColliderArrayEnabled(colliders, enabled: false); EnableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, null); } else if (IsInBackpack(item)) { SetColliderArrayEnabled(colliders, enabled: false); DisableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, null); } else { SetColliderArrayEnabled(colliders, enabled: false); EnableOriginalColliders(item); BindTwinTailClothCollisionSources(mikuRoot, null); } } } private static int DetermineTargetLayer(Item item) { if ((Object)(object)item == (Object)null) { return 0; } Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { return ((Component)val).gameObject.layer; } } return ((Component)item).gameObject.layer; } private static void ConfigureMikuRenderer(Renderer renderer, int targetLayer) { ((Component)renderer).gameObject.layer = targetLayer; renderer.allowOcclusionWhenDynamic = false; renderer.shadowCastingMode = (ShadowCastingMode)1; renderer.receiveShadows = true; renderer.forceRenderingOff = false; renderer.enabled = true; renderer.SetPropertyBlock((MaterialPropertyBlock)null); if (!((Component)renderer).gameObject.activeSelf) { ((Component)renderer).gameObject.SetActive(true); } NormalizeRuntimeRendererMaterials(renderer, "ConfigureMikuRenderer"); } private static bool RendererHasMainTexSlot(Renderer renderer) { if ((Object)(object)renderer == (Object)null) { return false; } Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { return false; } foreach (Material val in sharedMaterials) { if ((Object)(object)val != (Object)null && val.HasProperty("_MainTex")) { return true; } } return false; } private static Material CreateMainTexCompatMaterial(Texture texture) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown Shader val = Shader.Find("Standard") ?? Shader.Find("Unlit/Texture") ?? Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("W/Peak_Standard"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { name = "Miku_MainTexCompat", color = Color.white, renderQueue = 2000 }; if ((Object)(object)texture != (Object)null) { ApplyMikuTextureSafe(val2, texture); } ApplyRealisticMaterialTuning(val2); return val2; } private static void EnsureRendererMainTexCompatibility(Renderer renderer) { if ((Object)(object)renderer == (Object)null || Plugin.RuntimeReplacementModel != null) { return; } Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { Material val = CreateMainTexCompatMaterial(GetMikuTexture()) ?? CreateRendererMaterialInstance(); if ((Object)(object)val != (Object)null) { renderer.sharedMaterial = val; } return; } for (int i = 0; i < sharedMaterials.Length; i++) { if ((Object)(object)sharedMaterials[i] != (Object)null && sharedMaterials[i].HasProperty("_MainTex")) { return; } } Material val2 = CreateMainTexCompatMaterial(GetMikuTexture()); if (!((Object)(object)val2 == (Object)null)) { sharedMaterials[0] = val2; renderer.sharedMaterials = sharedMaterials; } } private static Renderer[] BuildAdditionalRenderers(Renderer primaryRenderer, Renderer[] renderers) { if (renderers == null || renderers.Length == 0) { return Array.Empty(); } List list = new List(); foreach (Renderer val in renderers) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)primaryRenderer)) { list.Add(val); } } if (list.Count != 0) { return list.ToArray(); } return Array.Empty(); } private static bool TryGetOriginalItemRenderers(Item item, out Renderer primaryRenderer, out Renderer[] additionalRenderers) { primaryRenderer = null; additionalRenderers = Array.Empty(); if ((Object)(object)item == (Object)null) { return false; } Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); List list = new List(); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { NormalizeRuntimeRendererMaterials(val, "TryGetOriginalItemRenderers"); list.Add(val); } } if (list.Count == 0) { return false; } for (int j = 0; j < list.Count; j++) { Renderer val2 = list[j]; if ((Object)(object)primaryRenderer == (Object)null) { primaryRenderer = val2; } if (RendererHasMainTexSlot(val2)) { primaryRenderer = val2; break; } } if ((Object)(object)primaryRenderer == (Object)null) { return false; } additionalRenderers = BuildAdditionalRenderers(primaryRenderer, list.ToArray()); return true; } private static void EnsureItemRendererRefs(Item item, Transform mikuRoot) { if (Plugin.KeepOriginalRendererRefs && TryGetOriginalItemRenderers(item, out var primaryRenderer, out var additionalRenderers)) { item.mainRenderer = primaryRenderer; item.addtlRenderers = additionalRenderers; return; } Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return; } Renderer val = null; foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { if ((Object)(object)val == (Object)null) { val = val2; } if (RendererHasMainTexSlot(val2)) { val = val2; break; } } } if (!((Object)(object)val == (Object)null)) { EnsureRendererMainTexCompatibility(val); item.mainRenderer = val; item.addtlRenderers = BuildAdditionalRenderers(val, componentsInChildren); } } private static void RestoreOriginalItemRendererRefs(Item item) { if (!((Object)(object)item == (Object)null) && TryGetOriginalItemRenderers(item, out var primaryRenderer, out var additionalRenderers)) { item.mainRenderer = primaryRenderer; item.addtlRenderers = additionalRenderers; } } private static void RemoveReplacement(Item item, Transform mikuRoot) { EnableOriginalRenderers(item); EnableOriginalColliders(item); RestoreOriginalItemRendererRefs(item); Transform val = FindMikuCollisionRoot(item); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } if ((Object)(object)mikuRoot != (Object)null) { Object.Destroy((Object)(object)((Component)mikuRoot).gameObject); } } private static void ApplyInitialMikuRendererSetup(Item item, Transform mikuRoot) { int num = DetermineTargetLayer(item); ((Component)mikuRoot).gameObject.layer = num; MeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); SkinnedMeshRenderer[] componentsInChildren2 = ((Component)mikuRoot).GetComponentsInChildren(true); Plugin.VerboseLog("[ItemPatch] Renderer layout for " + ((Object)item).name + ": MeshRenderers=" + componentsInChildren.Length + ", SkinnedMeshRenderers=" + componentsInChildren2.Length); foreach (MeshRenderer renderer in componentsInChildren) { ConfigureMikuRenderer((Renderer)(object)renderer, num); ApplyMaterialToMeshRenderer(renderer); } foreach (SkinnedMeshRenderer obj in componentsInChildren2) { obj.updateWhenOffscreen = true; ConfigureMikuRenderer((Renderer)(object)obj, num); ApplyMaterialToSkinnedRenderer(obj); } EnsureItemRendererRefs(item, mikuRoot); } private static bool IsWhitelistedBehaviour(MonoBehaviour behaviour) { if (!(behaviour is MikuMarker) && !(behaviour is MikuRendererGuard) && !(behaviour is MikuDeformGuard) && !(behaviour is MikuScaleRefreshGuard)) { return behaviour is MikuExpressionController; } return true; } private static void SanitizeVisualObject(GameObject visualRoot, int targetLayer) { Collider[] componentsInChildren = visualRoot.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.enabled = false; Object.Destroy((Object)(object)val); } } Rigidbody[] componentsInChildren2 = visualRoot.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { if ((Object)(object)componentsInChildren2[j] != (Object)null) { Object.Destroy((Object)(object)componentsInChildren2[j]); } } Joint[] componentsInChildren3 = visualRoot.GetComponentsInChildren(true); for (int k = 0; k < componentsInChildren3.Length; k++) { if ((Object)(object)componentsInChildren3[k] != (Object)null) { Object.Destroy((Object)(object)componentsInChildren3[k]); } } LODGroup[] componentsInChildren4 = visualRoot.GetComponentsInChildren(true); foreach (LODGroup val2 in componentsInChildren4) { if (!((Object)(object)val2 == (Object)null)) { val2.enabled = false; Object.Destroy((Object)(object)val2); } } MonoBehaviour[] componentsInChildren5 = visualRoot.GetComponentsInChildren(true); foreach (MonoBehaviour val3 in componentsInChildren5) { if (!((Object)(object)val3 == (Object)null) && !IsWhitelistedBehaviour(val3)) { ((Behaviour)val3).enabled = false; Object.Destroy((Object)(object)val3); } } Transform[] componentsInChildren6 = visualRoot.GetComponentsInChildren(true); foreach (Transform val4 in componentsInChildren6) { if (!((Object)(object)val4 == (Object)null)) { ((Component)val4).gameObject.tag = "Untagged"; ((Component)val4).gameObject.layer = targetLayer; } } } private static bool ContainsKeyword(string value, string[] keywords) { if (string.IsNullOrEmpty(value)) { return false; } string text = value.ToLowerInvariant(); for (int i = 0; i < keywords.Length; i++) { if (text.Contains(keywords[i])) { return true; } } return false; } private static void RemoveUnwantedFootAttachments(Transform mikuRoot) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); int num = 0; foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ContainsKeyword(((Object)((Component)val).gameObject).name, UnwantedFootKeywords)) { Bounds bounds = val.bounds; if (!(mikuRoot.InverseTransformPoint(((Bounds)(ref bounds)).center).y > 0.2f)) { Object.Destroy((Object)(object)((Component)val).gameObject); num++; } } } if (num > 0) { Plugin.VerboseLog("[ItemPatch] Removed unwanted foot attachments: " + num); } } private static void SanitizeOriginalItemRendererMaterials(Item item, string context) { if ((Object)(object)item == (Object)null) { return; } Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { NormalizeRuntimeRendererMaterials(val, context); } } } private static double GetElapsedMilliseconds(long startTimestamp, long endTimestamp) { return (double)(endTimestamp - startTimestamp) * 1000.0 / (double)Stopwatch.Frequency; } private static string FormatMilliseconds(double value) { return value.ToString("F2", CultureInfo.InvariantCulture); } private static bool ShouldLogSlowCreateProfile(double totalMilliseconds, params double[] stageMilliseconds) { if (SlowCreateProfileLogged) { return false; } if (totalMilliseconds >= 12.0) { return true; } if (stageMilliseconds == null) { return false; } for (int i = 0; i < stageMilliseconds.Length; i++) { if (stageMilliseconds[i] >= 4.0) { return true; } } return false; } private static void MaybeLogSlowCreateProfile(Item item, GameObject mikuObject, double originalRendererFixMs, double instantiateMs, double prepareMs, double sanitizeMs, double behaviourInitMs, double rendererSetupMs, double clothMs, double colliderRebuildMs, double syncMs, double totalMs) { if (Plugin.Log != null && ShouldLogSlowCreateProfile(totalMs, originalRendererFixMs, instantiateMs, prepareMs, sanitizeMs, behaviourInitMs, rendererSetupMs, clothMs, colliderRebuildMs, syncMs)) { SlowCreateProfileLogged = true; int num = (((Object)(object)mikuObject != (Object)null) ? mikuObject.GetComponentsInChildren(true).Length : 0); int num2 = (((Object)(object)mikuObject != (Object)null) ? mikuObject.GetComponentsInChildren(true).Length : 0); int num3 = (((Object)(object)item != (Object)null && item.colliders != null) ? item.colliders.Length : 0); string text = ((Plugin.RuntimeReplacementModel != null) ? "runtime-pmx" : "bundle"); Plugin.VerboseLog("[ItemPatch] Slow ScallionMiku create profile: route=" + text + ", item=" + (((Object)(object)item != (Object)null) ? ((Object)item).name : "") + ", total=" + FormatMilliseconds(totalMs) + "ms, originalRendererFix=" + FormatMilliseconds(originalRendererFixMs) + "ms, instantiate=" + FormatMilliseconds(instantiateMs) + "ms, prepare=" + FormatMilliseconds(prepareMs) + "ms, sanitize=" + FormatMilliseconds(sanitizeMs) + "ms, behaviourInit=" + FormatMilliseconds(behaviourInitMs) + "ms, rendererSetup=" + FormatMilliseconds(rendererSetupMs) + "ms, cloth=" + FormatMilliseconds(clothMs) + "ms, colliderRebuild=" + FormatMilliseconds(colliderRebuildMs) + "ms, sync=" + FormatMilliseconds(syncMs) + "ms, renderers=" + num.ToString(CultureInfo.InvariantCulture) + ", clothComponents=" + num2.ToString(CultureInfo.InvariantCulture) + ", itemColliders=" + num3.ToString(CultureInfo.InvariantCulture)); } } private static bool ShouldSkipVisibilitySync(MikuMarker marker, Item item, Transform mikuRoot, int targetLayer, Vector3 targetPosition, Quaternion targetRotation, Vector3 targetScale, bool shouldShow) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item != (Object)null && !IsHeld(item) && !IsInBackpack(item)) { return false; } if ((Object)(object)marker != (Object)null && marker.HasAppliedState && marker.LastRefreshRevision == Plugin.ReplacementRefreshRevision && marker.LastLayer == targetLayer && marker.LastItemState == item.itemState && marker.LastShouldShow == shouldShow && marker.LastLocalPosition == targetPosition && marker.LastLocalRotation == targetRotation && marker.LastLocalScale == targetScale) { return ((Component)mikuRoot).gameObject.activeSelf == shouldShow; } return false; } private static void CacheAppliedVisibilityState(MikuMarker marker, Item item, int targetLayer, Vector3 targetPosition, Quaternion targetRotation, Vector3 targetScale, bool shouldShow) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)marker == (Object)null) && !((Object)(object)item == (Object)null)) { marker.HasAppliedState = true; marker.LastRefreshRevision = Plugin.ReplacementRefreshRevision; marker.LastLayer = targetLayer; marker.LastItemState = item.itemState; marker.LastShouldShow = shouldShow; marker.LastLocalPosition = targetPosition; marker.LastLocalRotation = targetRotation; marker.LastLocalScale = targetScale; } } private static bool ShouldRunPerFrameReplacementValidation(Item item) { if ((Object)(object)item == (Object)null || !IsBingBong(item)) { return false; } if ((Object)(object)FindMikuRoot(item) == (Object)null) { return true; } int num = Mathf.Abs(((Object)item).GetInstanceID()); if (IsHeld(item)) { return (Time.frameCount + num) % 8 == 0; } if (IsInBackpack(item)) { return (Time.frameCount + num) % 20 == 0; } return true; } private static void SyncVisibilityState(Item item) { //IL_004d: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0139: 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_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) Transform val = FindMikuRoot(item); if ((Object)(object)val == (Object)null) { return; } int num = DetermineTargetLayer(item); ((Component)val).gameObject.layer = num; ResolvePoseByState(item, out var localPosition, out var localRotation, out var localScale); bool flag = IsReplacementHiddenByOriginal(val); bool flag2 = ShouldShowReplacement(item); MikuMarker component = ((Component)val).GetComponent(); if (ShouldSkipVisibilitySync(component, item, val, num, localPosition, localRotation, localScale, flag2)) { return; } if (val.localPosition != localPosition) { val.localPosition = localPosition; } if (val.localRotation != localRotation) { val.localRotation = localRotation; } bool flag3 = val.localScale != localScale; if (val.localScale != localScale) { val.localScale = localScale; } MikuDeformGuard component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.SetRootTarget(localPosition, localRotation, localScale); if (flag3) { component2.Capture(); } } if (flag3) { QueueScaleSensitiveRefresh(val, forceHardReset: false); } if (((Component)val).gameObject.activeSelf != flag2) { ((Component)val).gameObject.SetActive(flag2); } if (!flag2) { if (flag) { Transform val2 = FindMikuCollisionRoot(item); SetColliderArrayEnabled(((Object)(object)val2 != (Object)null) ? GetUsableProxyColliders(val2) : Array.Empty(), enabled: false); DisableOriginalColliders(item); RestoreOriginalItemRendererRefs(item); CacheAppliedVisibilityState(component, item, num, localPosition, localRotation, localScale, flag2); } else { EnableOriginalRenderers(item); EnableOriginalColliders(item); RestoreOriginalItemRendererRefs(item); } return; } SyncCollidersByState(item, val); if (HasVisibleReplacementRenderers(val)) { DisableOriginalRenderers(item); } else { EnableOriginalRenderers(item); } Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Renderer val3 in componentsInChildren) { if ((Object)(object)val3 != (Object)null) { ConfigureMikuRenderer(val3, num); } } EnsureItemRendererRefs(item, val); CacheAppliedVisibilityState(component, item, num, localPosition, localRotation, localScale, flag2); } private static Transform EnsureMikuModel(Item item, bool createIfMissing) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) Transform val = FindMikuRoot(item); if ((Object)(object)val != (Object)null) { return val; } if (!createIfMissing) { return null; } long timestamp = Stopwatch.GetTimestamp(); long timestamp2 = Stopwatch.GetTimestamp(); SanitizeOriginalItemRendererMaterials(item, "EnsureMikuModel.PreCreate"); double elapsedMilliseconds = GetElapsedMilliseconds(timestamp2, Stopwatch.GetTimestamp()); long timestamp3 = Stopwatch.GetTimestamp(); GameObject val2 = Plugin.CreateReplacementVisualInstance("MikuFumo_Visual"); double elapsedMilliseconds2 = GetElapsedMilliseconds(timestamp3, Stopwatch.GetTimestamp()); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"[ItemPatch] Replacement visual is unavailable, cannot create model yet."); return null; } long timestamp4 = Stopwatch.GetTimestamp(); val2.transform.SetParent(((Component)item).transform, false); ((Object)val2).name = "MikuFumo_Visual"; val2.SetActive(false); int targetLayer = (val2.layer = DetermineTargetLayer(item)); ResolvePoseByState(item, out var localPosition, out var localRotation, out var localScale); val2.transform.localPosition = localPosition; val2.transform.localRotation = localRotation; val2.transform.localScale = localScale; if ((Object)(object)val2.GetComponent() == (Object)null) { val2.AddComponent(); } double elapsedMilliseconds3 = GetElapsedMilliseconds(timestamp4, Stopwatch.GetTimestamp()); long timestamp5 = Stopwatch.GetTimestamp(); RemoveUnwantedFootAttachments(val2.transform); SanitizeVisualObject(val2, targetLayer); double elapsedMilliseconds4 = GetElapsedMilliseconds(timestamp5, Stopwatch.GetTimestamp()); long timestamp6 = Stopwatch.GetTimestamp(); MikuRendererGuard mikuRendererGuard = val2.GetComponent(); if ((Object)(object)mikuRendererGuard == (Object)null) { mikuRendererGuard = val2.AddComponent(); } mikuRendererGuard.Bind(item); MikuDeformGuard mikuDeformGuard = val2.GetComponent(); if ((Object)(object)mikuDeformGuard == (Object)null) { mikuDeformGuard = val2.AddComponent(); } mikuDeformGuard.Bind(item); mikuDeformGuard.Initialize(localPosition, localRotation, localScale); MikuExpressionController mikuExpressionController = EnsureExpressionController(val2.transform); if ((Object)(object)mikuExpressionController != (Object)null) { mikuExpressionController.Bind(item); } double elapsedMilliseconds5 = GetElapsedMilliseconds(timestamp6, Stopwatch.GetTimestamp()); long timestamp7 = Stopwatch.GetTimestamp(); ApplyInitialMikuRendererSetup(item, val2.transform); double elapsedMilliseconds6 = GetElapsedMilliseconds(timestamp7, Stopwatch.GetTimestamp()); long timestamp8 = Stopwatch.GetTimestamp(); EnsureTwinTailCloth(val2.transform); QueueScaleSensitiveRefresh(val2.transform, forceHardReset: true); double elapsedMilliseconds7 = GetElapsedMilliseconds(timestamp8, Stopwatch.GetTimestamp()); long timestamp9 = Stopwatch.GetTimestamp(); RebuildModelColliders(item, val2.transform); double elapsedMilliseconds8 = GetElapsedMilliseconds(timestamp9, Stopwatch.GetTimestamp()); long timestamp10 = Stopwatch.GetTimestamp(); SyncVisibilityState(item); double elapsedMilliseconds9 = GetElapsedMilliseconds(timestamp10, Stopwatch.GetTimestamp()); double elapsedMilliseconds10 = GetElapsedMilliseconds(timestamp, Stopwatch.GetTimestamp()); MaybeLogSlowCreateProfile(item, val2, elapsedMilliseconds, elapsedMilliseconds2, elapsedMilliseconds3, elapsedMilliseconds4, elapsedMilliseconds5, elapsedMilliseconds6, elapsedMilliseconds7, elapsedMilliseconds8, elapsedMilliseconds9, elapsedMilliseconds10); Plugin.VerboseLog("[ItemPatch] Created Miku replacement model under item: " + ((Object)item).name); return val2.transform; } private static void EnsureReplacementAndVisibility(Item item, bool createIfMissing) { if (!IsBingBong(item)) { return; } Transform val = FindMikuRoot(item); if (!Plugin.ModEnabled) { if ((Object)(object)val != (Object)null) { RemoveReplacement(item, val); } return; } if ((Object)(object)val == (Object)null) { val = EnsureMikuModel(item, createIfMissing); } if (!((Object)(object)val == (Object)null)) { if (!IsInBackpack(item)) { SetReplacementHiddenByOriginal(val, hidden: false); } MikuRendererGuard component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.Bind(item); } MikuDeformGuard component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.Bind(item); } MikuExpressionController mikuExpressionController = FindExpressionController(val); if ((Object)(object)mikuExpressionController != (Object)null) { mikuExpressionController.Bind(item); } SyncVisibilityState(item); } } private static bool IsRuntimeRefreshCandidate(Item item) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null) { return false; } Scene scene = ((Component)item).gameObject.scene; if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded) { return true; } if ((Object)(object)FindMikuRoot(item) != (Object)null) { return true; } if ((int)item.itemState != 1) { return (int)item.itemState == 2; } return true; } private static void TryRefreshTrackedItem(Item item, HashSet refreshedItemIds, bool createIfMissing) { if (!((Object)(object)item == (Object)null) && !((Object)(object)((Component)item).gameObject == (Object)null) && IsBingBong(item)) { int instanceID = ((Object)item).GetInstanceID(); if (refreshedItemIds == null || !refreshedItemIds.Contains(instanceID)) { EnsureReplacementAndVisibility(item, createIfMissing); refreshedItemIds?.Add(instanceID); } } } private static void RefreshCharacterHeldItems(HashSet refreshedItemIds) { List allCharacters = Character.AllCharacters; if (allCharacters == null || allCharacters.Count == 0) { return; } for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if (!((Object)(object)val == (Object)null)) { CharacterData val2 = CharacterDataRef.Invoke(val); if (!((Object)(object)val2 == (Object)null)) { TryRefreshTrackedItem(CharacterCurrentItemRef.Invoke(val2), refreshedItemIds, createIfMissing: true); } } } } private static void RefreshBoundReplacementRoots(HashSet refreshedItemIds) { MikuMarker[] array = Resources.FindObjectsOfTypeAll(); foreach (MikuMarker mikuMarker in array) { if (!((Object)(object)mikuMarker == (Object)null)) { Item val = FindBoundItemFromMikuRoot(((Component)mikuMarker).transform); if (!((Object)(object)val == (Object)null)) { TryRefreshTrackedItem(val, refreshedItemIds, createIfMissing: false); } } } } internal static void RefreshAllReplacementInstances() { HashSet refreshedItemIds = new HashSet(); Item[] array = Resources.FindObjectsOfTypeAll(); foreach (Item item in array) { if (IsRuntimeRefreshCandidate(item)) { TryRefreshTrackedItem(item, refreshedItemIds, createIfMissing: true); } } RefreshCharacterHeldItems(refreshedItemIds); RefreshBoundReplacementRoots(refreshedItemIds); } [HarmonyPatch("Start")] [HarmonyPostfix] public static void Item_Start(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); if (IsBingBong(__instance)) { Plugin.VerboseLog("[ItemPatch] Model replacement complete for: " + ((Object)__instance).name); } } [HarmonyPatch("OnEnable")] [HarmonyPostfix] public static void Item_OnEnable(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("SetState")] [HarmonyPrefix] public static void Item_SetState_Prefix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("SetState")] [HarmonyPostfix] public static void Item_SetState_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("Update")] [HarmonyPostfix] public static void Item_Update_Postfix(Item __instance) { if (ShouldRunPerFrameReplacementValidation(__instance)) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } } [HarmonyPatch("RequestPickup")] [HarmonyPrefix] public static void Item_RequestPickup_Prefix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("RequestPickup")] [HarmonyPostfix] public static void Item_RequestPickup_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("HideRenderers")] [HarmonyPostfix] public static void Item_HideRenderers_Postfix(Item __instance) { if (Plugin.ModEnabled && IsBingBong(__instance)) { Transform val = EnsureMikuModel(__instance, createIfMissing: true); if (!((Object)(object)val == (Object)null)) { HideReplacementForOriginalRule(__instance, val); } } } [HarmonyPatch("PutInBackpackRPC")] [HarmonyPostfix] public static void Item_PutInBackpackRPC_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: false); } [HarmonyPatch("ClearDataFromBackpack")] [HarmonyPostfix] public static void Item_ClearDataFromBackpack_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: false); } [HarmonyPatch(typeof(ItemUIData), "GetIcon")] [HarmonyPostfix] public static void Item_GetIcon(ItemUIData __instance, ref Texture2D __result) { if (Plugin.ModEnabled && __instance.itemName == "Bing Bong" && (Object)(object)Plugin.MochiTexture != (Object)null) { __result = Plugin.MochiTexture; } } [HarmonyPatch("GetName")] [HarmonyPostfix] public static void Item_GetName_Postfix(Item __instance, ref string __result) { if (Plugin.ModEnabled && IsBingBong(__instance)) { __result = Plugin.ReplacementDisplayName; } } [HarmonyPatch("GetItemName")] [HarmonyPostfix] public static void Item_GetItemName_Postfix(Item __instance, ref string __result) { if (Plugin.ModEnabled && IsBingBong(__instance)) { __result = Plugin.ReplacementDisplayName; } } } [HarmonyPatch] public static class MikuTintCompatibilityPatch { private delegate void ItemCookingIntMethod(ItemCooking instance, int value); private static readonly FieldRef BackpackRenderersRef = AccessTools.FieldRefAccess("renderers"); private static readonly FieldRef BackpackDefaultTintsRef = AccessTools.FieldRefAccess("defaultTints"); private static readonly FieldRef ItemCookingRenderersRef = AccessTools.FieldRefAccess("renderers"); private static readonly FieldRef ItemCookingDefaultTintsRef = AccessTools.FieldRefAccess("defaultTints"); private static readonly FieldRef ItemCookingSetupRef = AccessTools.FieldRefAccess("setup"); private static readonly FieldRef ItemCookingPreCookedRef = AccessTools.FieldRefAccess("preCooked"); private static readonly FieldRef ItemCookingIgnoreDefaultCookBehaviorRef = AccessTools.FieldRefAccess("ignoreDefaultCookBehavior"); private static readonly FieldRef ItemCookingTimesCookedLocalRef = AccessTools.FieldRefAccess("k__BackingField"); private static readonly ItemCookingIntMethod RunAdditionalCookingBehaviorsDelegate = AccessTools.MethodDelegate(AccessTools.Method(typeof(ItemCooking), "RunAdditionalCookingBehaviors", (Type[])null, (Type[])null), (object)null, true); private static readonly ItemCookingIntMethod ChangeStatsCookedDelegate = AccessTools.MethodDelegate(AccessTools.Method(typeof(ItemCooking), "ChangeStatsCooked", (Type[])null, (Type[])null), (object)null, true); private static readonly ItemCookingIntMethod CookVisuallyDelegate = AccessTools.MethodDelegate(AccessTools.Method(typeof(ItemCooking), "CookVisually", (Type[])null, (Type[])null), (object)null, true); private static Color GetSafeTint(Material material) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null) { return Color.white; } if (material.HasProperty("_Tint")) { return material.GetColor("_Tint"); } if (material.HasProperty("_BaseColor")) { return material.GetColor("_BaseColor"); } if (material.HasProperty("_Color")) { return material.GetColor("_Color"); } return Color.white; } private static void TryApplyTint(Material material, Color color) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material != (Object)null && material.HasProperty("_Tint")) { material.SetColor("_Tint", color); } } private static Color[] CaptureDefaultTints(Renderer[] renderers) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[renderers.Length]; for (int i = 0; i < renderers.Length; i++) { Renderer val = renderers[i]; array[i] = (((Object)(object)val == (Object)null) ? Color.white : GetSafeTint(val.material)); } return array; } private static MeshRenderer[] GetBackpackSafeRenderers(BackpackOnBackVisuals instance) { MeshRenderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren(); List list = new List(); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !ItemPatch.IsMikuTransform(((Component)val).transform)) { list.Add(val); } } return list.ToArray(); } private static Renderer[] GetItemCookingSafeRenderers(ItemCooking instance) { List list = new List(); MeshRenderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren(); SkinnedMeshRenderer[] componentsInChildren2 = ((Component)instance).GetComponentsInChildren(true); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !ItemPatch.IsMikuTransform(((Component)val).transform)) { list.Add((Renderer)(object)val); } } foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !ItemPatch.IsMikuTransform(((Component)val2).transform)) { list.Add((Renderer)(object)val2); } } return list.ToArray(); } private static void EnsureBackpackRendererCache(BackpackOnBackVisuals instance) { MeshRenderer[] array = BackpackRenderersRef.Invoke(instance); Color[] array2 = BackpackDefaultTintsRef.Invoke(instance); bool flag = array == null || array2 == null || array2.Length != array.Length; if (!flag && array.Length != 0) { for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && ItemPatch.IsMikuTransform(((Component)array[i]).transform)) { flag = true; break; } } } if (flag) { array = GetBackpackSafeRenderers(instance); BackpackRenderersRef.Invoke(instance) = array; ref Color[] reference = ref BackpackDefaultTintsRef.Invoke(instance); Renderer[] renderers = (Renderer[])(object)array; reference = CaptureDefaultTints(renderers); } } private static void EnsureItemCookingRendererCache(ItemCooking instance) { Renderer[] array = ItemCookingRenderersRef.Invoke(instance); Color[] array2 = ItemCookingDefaultTintsRef.Invoke(instance); bool flag = !ItemCookingSetupRef.Invoke(instance) || array == null || array2 == null || array2.Length != array.Length; if (!flag && array.Length != 0) { for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && ItemPatch.IsMikuTransform(((Component)array[i]).transform)) { flag = true; break; } } } if (flag) { array = GetItemCookingSafeRenderers(instance); ItemCookingRenderersRef.Invoke(instance) = array; ItemCookingDefaultTintsRef.Invoke(instance) = CaptureDefaultTints(array); ItemCookingSetupRef.Invoke(instance) = true; } } [HarmonyPatch(typeof(BackpackOnBackVisuals), "InitRenderers")] [HarmonyPrefix] public static bool BackpackOnBackVisuals_InitRenderers_Prefix(BackpackOnBackVisuals __instance) { MeshRenderer[] backpackSafeRenderers = GetBackpackSafeRenderers(__instance); BackpackRenderersRef.Invoke(__instance) = backpackSafeRenderers; ref Color[] reference = ref BackpackDefaultTintsRef.Invoke(__instance); Renderer[] renderers = (Renderer[])(object)backpackSafeRenderers; reference = CaptureDefaultTints(renderers); return false; } [HarmonyPatch(typeof(BackpackOnBackVisuals), "CookVisually")] [HarmonyPrefix] public static bool BackpackOnBackVisuals_CookVisually_Prefix(BackpackOnBackVisuals __instance, int __0) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) EnsureBackpackRendererCache(__instance); if (__0 <= 0) { return false; } MeshRenderer[] array = BackpackRenderersRef.Invoke(__instance) ?? Array.Empty(); Color[] array2 = BackpackDefaultTintsRef.Invoke(__instance) ?? Array.Empty(); Color cookColor = ItemCooking.GetCookColor(__0); for (int i = 0; i < array.Length; i++) { MeshRenderer val = array[i]; if (!((Object)(object)val == (Object)null)) { Color val2 = ((i < array2.Length) ? array2[i] : Color.white); TryApplyTint(((Renderer)val).material, val2 * cookColor); } } return false; } [HarmonyPatch(typeof(ItemCooking), "UpdateCookedBehavior")] [HarmonyPrefix] public static bool ItemCooking_UpdateCookedBehavior_Prefix(ItemCooking __instance) { Item component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } IntItemData data = component.GetData((DataEntryKey)1); if (data == null) { return true; } if (data.Value == 0) { data.Value += ItemCookingPreCookedRef.Invoke(__instance); } EnsureItemCookingRendererCache(__instance); int num = data.Value - ItemCookingTimesCookedLocalRef.Invoke(__instance); CookVisuallyDelegate(__instance, data.Value); if (!ItemCookingIgnoreDefaultCookBehaviorRef.Invoke(__instance) && num > 0) { for (int i = 1 + ItemCookingTimesCookedLocalRef.Invoke(__instance); i <= data.Value; i++) { ChangeStatsCookedDelegate(__instance, i); } } RunAdditionalCookingBehaviorsDelegate(__instance, data.Value); ItemCookingTimesCookedLocalRef.Invoke(__instance) = data.Value; return false; } [HarmonyPatch(typeof(ItemCooking), "CookVisually")] [HarmonyPrefix] public static bool ItemCooking_CookVisually_Prefix(ItemCooking __instance, int __0) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) EnsureItemCookingRendererCache(__instance); if (__0 <= 0) { return false; } Renderer[] array = ItemCookingRenderersRef.Invoke(__instance) ?? Array.Empty(); Color[] array2 = ItemCookingDefaultTintsRef.Invoke(__instance) ?? Array.Empty(); Color cookColor = ItemCooking.GetCookColor(__0); for (int i = 0; i < array.Length; i++) { Renderer val = array[i]; if (!((Object)(object)val == (Object)null)) { Material[] materials = val.materials; Color color = ((i < array2.Length) ? array2[i] : Color.white) * cookColor; for (int j = 0; j < materials.Length; j++) { TryApplyTint(materials[j], color); } } } return false; } } internal sealed class RuntimeReplacementModel { internal string DisplayName { get; private set; } internal Mesh Mesh { get; private set; } internal Material[] Materials { get; private set; } internal RuntimeBoneInfo[] Bones { get; private set; } internal RuntimeTwinTailPhysicsChain[] TwinTailChains { get; private set; } internal int RootBoneIndex { get; private set; } internal Vector3 MeshLocalOffset { get; private set; } internal Vector3 RecommendedBaseScale { get; private set; } internal Texture2D PrimaryTexture { get; private set; } internal Texture2D IconTexture { get; private set; } internal bool HasSkinning { get { if ((Object)(object)Mesh != (Object)null && Bones != null && Bones.Length != 0 && Mesh.bindposes != null && Mesh.bindposes.Length == Bones.Length && Mesh.boneWeights != null) { return Mesh.boneWeights.Length == Mesh.vertexCount; } return false; } } internal Material PrimaryMaterial { get { if (Materials == null || Materials.Length == 0) { return null; } return Materials[0]; } } internal RuntimeReplacementModel(string displayName, Mesh mesh, Material[] materials, RuntimeBoneInfo[] bones, RuntimeTwinTailPhysicsChain[] twinTailChains, int rootBoneIndex, Vector3 meshLocalOffset, Vector3 recommendedBaseScale, Texture2D primaryTexture, Texture2D iconTexture) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) DisplayName = (string.IsNullOrEmpty(displayName) ? "Miku" : displayName); Mesh = mesh; Materials = materials ?? Array.Empty(); Bones = bones ?? Array.Empty(); TwinTailChains = twinTailChains ?? Array.Empty(); RootBoneIndex = rootBoneIndex; MeshLocalOffset = meshLocalOffset; RecommendedBaseScale = recommendedBaseScale; PrimaryTexture = primaryTexture; IconTexture = iconTexture; } internal GameObject Instantiate(string rootName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(string.IsNullOrEmpty(rootName) ? "Fufu_Visual" : rootName); if (HasSkinning) { InstantiateSkinned(val); return val; } GameObject val2 = new GameObject("RuntimeMesh"); val2.transform.SetParent(val.transform, false); val2.transform.localPosition = MeshLocalOffset; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; val2.AddComponent().sharedMesh = Mesh; ((Renderer)val2.AddComponent()).sharedMaterials = CloneMaterials(); return val; } private void InstantiateSkinned(GameObject root) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0106: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Skeleton"); val.transform.SetParent(root.transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; Transform[] array = BuildBoneHierarchy(val.transform); ApplyStaticRestPoseCorrections(array); GameObject val2 = new GameObject("RuntimeSkinnedMesh"); val2.transform.SetParent(root.transform, false); val2.transform.localPosition = MeshLocalOffset; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; SkinnedMeshRenderer val3 = val2.AddComponent(); val3.sharedMesh = Mesh; ((Renderer)val3).sharedMaterials = CloneMaterials(); val3.bones = array; val3.rootBone = ResolveRootBone(array, val.transform); val3.updateWhenOffscreen = true; Bounds bounds = Mesh.bounds; ((Bounds)(ref bounds)).Expand(0.5f); ((Renderer)val3).localBounds = bounds; val2.AddComponent().Initialize(val3); } private Transform[] BuildBoneHierarchy(Transform skeletonRoot) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) Transform[] array = (Transform[])(object)new Transform[Bones.Length]; for (int i = 0; i < Bones.Length; i++) { RuntimeBoneInfo runtimeBoneInfo = Bones[i]; GameObject val = new GameObject(string.IsNullOrEmpty(runtimeBoneInfo.Name) ? ("Bone_" + i) : runtimeBoneInfo.Name); array[i] = val.transform; } for (int j = 0; j < Bones.Length; j++) { RuntimeBoneInfo runtimeBoneInfo2 = Bones[j]; Transform val2 = ((runtimeBoneInfo2.ParentIndex >= 0 && runtimeBoneInfo2.ParentIndex < array.Length) ? array[runtimeBoneInfo2.ParentIndex] : skeletonRoot); array[j].SetParent(val2, false); array[j].localPosition = runtimeBoneInfo2.LocalPosition; array[j].localRotation = Quaternion.identity; array[j].localScale = Vector3.one; } return array; } private static void ApplyStaticRestPoseCorrections(Transform[] boneTransforms) { _ = boneTransforms?.LongLength; } private static void ApplyBoneLocalRotation(Transform[] boneTransforms, string boneName, Quaternion localRotation) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (boneTransforms == null || string.IsNullOrEmpty(boneName)) { return; } foreach (Transform val in boneTransforms) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, boneName, StringComparison.OrdinalIgnoreCase)) { val.localRotation = localRotation; break; } } } private Transform ResolveRootBone(Transform[] boneTransforms, Transform fallback) { if (boneTransforms == null || boneTransforms.Length == 0) { return fallback; } if (RootBoneIndex >= 0 && RootBoneIndex < boneTransforms.Length && (Object)(object)boneTransforms[RootBoneIndex] != (Object)null) { return boneTransforms[RootBoneIndex]; } return boneTransforms[0] ?? fallback; } private Material[] CloneMaterials() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (Materials == null || Materials.Length == 0) { return Array.Empty(); } Material[] array = (Material[])(object)new Material[Materials.Length]; for (int i = 0; i < Materials.Length; i++) { Material val = Materials[i]; object obj = array; int num = i; obj = (object)(((Object)(object)val != (Object)null) ? new Material(val) : ((Material)null)); ((object[])obj)[num] = obj; } return array; } } internal sealed class RuntimeBoneInfo { internal string Name; internal int ParentIndex; internal Vector3 AbsolutePosition; internal Vector3 LocalPosition; internal int TailBoneIndex; internal Vector3 TailLocalOffset; } internal sealed class RuntimeTwinTailPhysicsChain { internal string Name; internal int AnchorBoneIndex; internal int[] BoneIndices = Array.Empty(); internal Vector3[] NodeLocalPositions = Array.Empty(); internal Vector3[] ChildLocalOffsets = Array.Empty(); internal Vector3[] RestDirections = Array.Empty(); internal float[] SegmentLengths = Array.Empty(); internal float[] MaxAnglesRadians = Array.Empty(); internal float[] SegmentDamping = Array.Empty(); internal Vector3 LastTailLocalOffset; } internal sealed class MikuExpressionController : MonoBehaviour { private struct BlendShapeBinding { internal SkinnedMeshRenderer Renderer; internal int BlendShapeIndex; } private static readonly string[] HeldExpressionCandidates = new string[8] { "笑い", "ウィンク", "ウィンク右", "まばたき", "口角上げ", "あ", "え", "お" }; private readonly List _renderers = new List(); private readonly Dictionary> _blendShapeBindings = new Dictionary>(StringComparer.OrdinalIgnoreCase); private Item _boundItem; private string _lastExpressionName = string.Empty; private float _lastExpressionWeight = -1f; private bool _initializedState; private bool _wasHeld; private string _transientExpressionName = string.Empty; private float _transientExpressionUntil; internal Item BoundItem => _boundItem; internal void Initialize(SkinnedMeshRenderer renderer) { if ((Object)(object)renderer == (Object)null) { Initialize((IEnumerable)Array.Empty()); return; } Initialize((IEnumerable)(object)new SkinnedMeshRenderer[1] { renderer }); } internal void Initialize(IEnumerable renderers) { _renderers.Clear(); _blendShapeBindings.Clear(); if (renderers == null) { ((Behaviour)this).enabled = false; return; } foreach (SkinnedMeshRenderer renderer in renderers) { Mesh val = (((Object)(object)renderer != (Object)null) ? renderer.sharedMesh : null); if ((Object)(object)val == (Object)null || val.blendShapeCount <= 0) { continue; } _renderers.Add(renderer); for (int i = 0; i < val.blendShapeCount; i++) { string blendShapeName = val.GetBlendShapeName(i); if (!string.IsNullOrEmpty(blendShapeName)) { BlendShapeBinding blendShapeBinding = default(BlendShapeBinding); blendShapeBinding.Renderer = renderer; blendShapeBinding.BlendShapeIndex = i; BlendShapeBinding binding = blendShapeBinding; RegisterBlendShapeBinding(blendShapeName, binding); string text = NormalizeBlendShapeAlias(blendShapeName); if (!string.Equals(text, blendShapeName, StringComparison.OrdinalIgnoreCase)) { RegisterBlendShapeBinding(text, binding); } } } } if (_blendShapeBindings.Count == 0 || _renderers.Count == 0) { ((Behaviour)this).enabled = false; return; } Plugin.VerboseLog("[MikuExpressionController] Initialized with aliases: " + string.Join(", ", _blendShapeBindings.Keys)); ((Behaviour)this).enabled = true; } internal void Bind(Item item) { _boundItem = item; } private void LateUpdate() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 if (_renderers.Count == 0 || _blendShapeBindings.Count == 0) { return; } bool flag = (Object)(object)_boundItem != (Object)null && (int)_boundItem.itemState == 1; bool isUsing = flag && (_boundItem.isUsingPrimary || _boundItem.isUsingSecondary); if (!_initializedState) { _initializedState = true; _wasHeld = flag; if (flag) { TriggerHeldExpression(); } } else if (flag && !_wasHeld) { TriggerHeldExpression(); } _wasHeld = flag; string text = ResolveCurrentExpressionName(flag, isUsing); float num = (string.Equals(text, "None", StringComparison.OrdinalIgnoreCase) ? 0f : (Plugin.ExpressionWeight * 100f)); if (string.Equals(text, _lastExpressionName, StringComparison.OrdinalIgnoreCase) && Mathf.Abs(num - _lastExpressionWeight) <= 0.001f) { return; } ResetAllBlendShapeWeights(); if (!string.Equals(text, "None", StringComparison.OrdinalIgnoreCase) && _blendShapeBindings.TryGetValue(text, out var value)) { for (int i = 0; i < value.Count; i++) { BlendShapeBinding blendShapeBinding = value[i]; if ((Object)(object)blendShapeBinding.Renderer != (Object)null) { blendShapeBinding.Renderer.SetBlendShapeWeight(blendShapeBinding.BlendShapeIndex, num); } } } _lastExpressionName = text; _lastExpressionWeight = num; } private string ResolveCurrentExpressionName(bool isHeld, bool isUsing) { if (isUsing && HasBlendShape("はぅ")) { return "はぅ"; } if (isHeld && !string.IsNullOrEmpty(_transientExpressionName) && Time.time < _transientExpressionUntil && HasBlendShape(_transientExpressionName)) { return _transientExpressionName; } string expressionName = Plugin.ExpressionName; if (!HasBlendShape(expressionName)) { return "None"; } return expressionName; } private void TriggerHeldExpression() { _transientExpressionName = PickHeldExpression(); _transientExpressionUntil = Time.time + Random.Range(2f, 3f); } private string PickHeldExpression() { string expressionName = Plugin.ExpressionName; string[] array = (string[])HeldExpressionCandidates.Clone(); for (int i = 0; i < array.Length; i++) { int num = Random.Range(i, array.Length); string text = array[i]; array[i] = array[num]; array[num] = text; } foreach (string text2 in array) { if (!string.Equals(text2, expressionName, StringComparison.OrdinalIgnoreCase) && HasBlendShape(text2)) { return text2; } } return "None"; } private void ResetAllBlendShapeWeights() { for (int i = 0; i < _renderers.Count; i++) { SkinnedMeshRenderer val = _renderers[i]; Mesh val2 = (((Object)(object)val != (Object)null) ? val.sharedMesh : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null)) { for (int j = 0; j < val2.blendShapeCount; j++) { val.SetBlendShapeWeight(j, 0f); } } } } private void RegisterBlendShapeBinding(string alias, BlendShapeBinding binding) { if (string.IsNullOrWhiteSpace(alias)) { return; } alias = alias.Trim(); if (!_blendShapeBindings.TryGetValue(alias, out var value)) { value = new List(); _blendShapeBindings.Add(alias, value); } for (int i = 0; i < value.Count; i++) { BlendShapeBinding blendShapeBinding = value[i]; if ((Object)(object)blendShapeBinding.Renderer == (Object)(object)binding.Renderer && blendShapeBinding.BlendShapeIndex == binding.BlendShapeIndex) { return; } } value.Add(binding); } private static string NormalizeBlendShapeAlias(string alias) { if (string.IsNullOrWhiteSpace(alias)) { return string.Empty; } string text = alias.Trim(); int i; for (i = 0; i < text.Length && char.IsDigit(text[i]); i++) { } for (; i < text.Length; i++) { char c = text[i]; if (c != '.' && c != '_' && c != '-' && c != ' ' && c != '\t') { break; } } if (i <= 0) { return text; } return text.Substring(i).Trim(); } private bool HasBlendShape(string expressionName) { if (!string.IsNullOrEmpty(expressionName) && !string.Equals(expressionName, "None", StringComparison.OrdinalIgnoreCase)) { return _blendShapeBindings.ContainsKey(expressionName); } return false; } } internal sealed class MikuTwinTailPhysics : MonoBehaviour { private sealed class ChainState { internal RuntimeTwinTailPhysicsChain Chain; internal Vector3[] CurrentPositions; internal Vector3[] PreviousPositions; internal Quaternion[] RestLocalRotations; internal Vector3[] RestParentDirections; internal Vector3[] RestHorizontalDirectionsLocal; internal Quaternion LastAnchorWorldRotation; internal float TotalLength; } private const float GravityScale = 1.6f; private const int SolverIterations = 5; private const int WarmupSteps = 18; private const float WarmupDeltaTime = 1f / 60f; private const float MaxVelocityMultiplier = 1.15f; private const float RotationSmoothing = 0.32f; private const float FirstSegmentRestBlend = 0.2f; private const float RootRestPull = 0.32f; private const float TipRestPull = 0.08f; private const float AnchorTravelResetFactor = 0.72f; private const float MinimumAnchorTravelResetDistance = 0.12f; private const float AnchorRotationResetDegrees = 70f; private Transform _skeletonRoot; private Transform[] _boneTransforms = Array.Empty(); private ChainState[] _chainStates = Array.Empty(); private bool _initialized; private Item _boundItem; private bool _hasTrackedItemState; private ItemState _lastTrackedItemState; internal void Initialize(Transform skeletonRoot, Transform[] boneTransforms, RuntimeTwinTailPhysicsChain[] chains) { //IL_00bc: 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_00c6: Unknown result type (might be due to invalid IL or missing references) _skeletonRoot = skeletonRoot; _boneTransforms = boneTransforms ?? Array.Empty(); if ((Object)(object)_skeletonRoot == (Object)null || chains == null || chains.Length == 0) { ((Behaviour)this).enabled = false; return; } List list = new List(); foreach (RuntimeTwinTailPhysicsChain runtimeTwinTailPhysicsChain in chains) { if (runtimeTwinTailPhysicsChain != null && runtimeTwinTailPhysicsChain.BoneIndices != null && runtimeTwinTailPhysicsChain.BoneIndices.Length >= 2) { list.Add(new ChainState { Chain = runtimeTwinTailPhysicsChain, CurrentPositions = CaptureCurrentChainWorldPositions(runtimeTwinTailPhysicsChain), PreviousPositions = CaptureCurrentChainWorldPositions(runtimeTwinTailPhysicsChain), RestLocalRotations = CaptureRestLocalRotations(runtimeTwinTailPhysicsChain.BoneIndices), RestParentDirections = CaptureRestParentDirections(runtimeTwinTailPhysicsChain), RestHorizontalDirectionsLocal = CaptureRestHorizontalDirectionsLocal(runtimeTwinTailPhysicsChain), LastAnchorWorldRotation = GetCurrentBoneWorldRotation(runtimeTwinTailPhysicsChain.AnchorBoneIndex, Quaternion.identity), TotalLength = ComputeTotalLength(runtimeTwinTailPhysicsChain) }); } } _chainStates = list.ToArray(); _initialized = _chainStates.Length != 0; ((Behaviour)this).enabled = _initialized; if (_initialized) { WarmupChains(); } } internal void Bind(Item item) { _boundItem = item; } private void LateUpdate() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (_initialized && !((Object)(object)_skeletonRoot == (Object)null) && _chainStates.Length != 0) { float deltaTime = Mathf.Clamp(Time.deltaTime, 0.0001f, 0.033f); Vector3 stableGravityWorld = GetStableGravityWorld(); bool forceReset = ConsumeItemStateReset(); for (int i = 0; i < _chainStates.Length; i++) { SimulateChain(_chainStates[i], deltaTime, stableGravityWorld, forceReset); ApplyChainToBones(_chainStates[i]); } } } private void SimulateChain(ChainState state, float deltaTime, Vector3 gravityWorld, bool forceReset) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: 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) //IL_0227: 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_022e: 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_0262: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) RuntimeTwinTailPhysicsChain chain = state.Chain; if (chain == null || state.CurrentPositions == null || state.CurrentPositions.Length < 2) { return; } Vector3 val = GetCurrentBoneWorldPosition(chain.BoneIndices[0], state.CurrentPositions[0]); Quaternion currentBoneWorldRotation = GetCurrentBoneWorldRotation(chain.AnchorBoneIndex, state.LastAnchorWorldRotation); if (forceReset || ShouldHardResetChain(state, val, currentBoneWorldRotation)) { ResetChainToCurrentPose(state, currentBoneWorldRotation); val = state.CurrentPositions[0]; } else { ApplyAnchorMotion(state, val, currentBoneWorldRotation); } float num = deltaTime * deltaTime; for (int i = 1; i < state.CurrentPositions.Length; i++) { Vector3 val2 = state.CurrentPositions[i]; Vector3 val3 = state.PreviousPositions[i]; float num2 = ((chain.SegmentDamping != null && i - 1 < chain.SegmentDamping.Length) ? Mathf.Clamp(chain.SegmentDamping[i - 1], 0.82f, 0.995f) : 0.93f); Vector3 val4 = (val2 - val3) * num2; float num3 = ((chain.SegmentLengths != null && i - 1 < chain.SegmentLengths.Length) ? (chain.SegmentLengths[i - 1] * 1.15f) : 1.15f); if (((Vector3)(ref val4)).sqrMagnitude > num3 * num3) { val4 = ((Vector3)(ref val4)).normalized * num3; } state.PreviousPositions[i] = val2; state.CurrentPositions[i] = val2 + val4 + gravityWorld * num; } Vector3[] array = BuildDesiredWorldPositions(state, gravityWorld, val); for (int j = 0; j < 5; j++) { state.CurrentPositions[0] = val; for (int k = 1; k < state.CurrentPositions.Length; k++) { float num4 = ((state.CurrentPositions.Length > 2) ? ((float)(k - 1) / (float)(state.CurrentPositions.Length - 2)) : 0f); float num5 = Mathf.Lerp(0.32f, 0.08f, num4); state.CurrentPositions[k] = Vector3.Lerp(state.CurrentPositions[k], array[k], num5); Vector3 val5 = state.CurrentPositions[k - 1]; Vector3 val6 = state.CurrentPositions[k] - val5; if (((Vector3)(ref val6)).sqrMagnitude <= 1E-06f) { val6 = array[k] - array[k - 1]; } Vector3 val7 = array[k] - array[k - 1]; if (((Vector3)(ref val7)).sqrMagnitude <= 1E-06f) { val7 = ((((Vector3)(ref gravityWorld)).sqrMagnitude > 1E-06f) ? gravityWorld : Vector3.down); } val6 = ((Vector3)(ref val6)).normalized; val7 = ((Vector3)(ref val7)).normalized; val6 = ClampDirectionToRestCone(val6, val7, chain.MaxAnglesRadians[k - 1]); if (k == 1) { Vector3 val8 = Vector3.Slerp(val6, val7, 0.2f); val6 = ((Vector3)(ref val8)).normalized; } state.CurrentPositions[k] = val5 + val6 * chain.SegmentLengths[k - 1]; } } } private void WarmupChains() { //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_003d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_skeletonRoot == (Object)null || _chainStates == null || _chainStates.Length == 0) { return; } Vector3 stableGravityWorld = GetStableGravityWorld(); for (int i = 0; i < 18; i++) { for (int j = 0; j < _chainStates.Length; j++) { SimulateChain(_chainStates[j], 1f / 60f, stableGravityWorld, forceReset: false); } } for (int k = 0; k < _chainStates.Length; k++) { ChainState chainState = _chainStates[k]; if (chainState != null && chainState.CurrentPositions != null && chainState.PreviousPositions != null) { Array.Copy(chainState.CurrentPositions, chainState.PreviousPositions, Mathf.Min(chainState.CurrentPositions.Length, chainState.PreviousPositions.Length)); ApplyChainToBones(chainState); } } } private Vector3[] BuildDesiredWorldPositions(ChainState state, Vector3 gravityWorld, Vector3 anchorWorldPosition) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: 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_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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016e: 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_017e: 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_018d: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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) RuntimeTwinTailPhysicsChain runtimeTwinTailPhysicsChain = state?.Chain; int num = ((runtimeTwinTailPhysicsChain != null && runtimeTwinTailPhysicsChain.SegmentLengths != null) ? runtimeTwinTailPhysicsChain.SegmentLengths.Length : 0); Vector3[] array = (Vector3[])(object)new Vector3[num + 1]; array[0] = anchorWorldPosition; Vector3 val = ((((Vector3)(ref gravityWorld)).sqrMagnitude > 1E-06f) ? ((Vector3)(ref gravityWorld)).normalized : Vector3.down); Vector3 val2 = val; for (int i = 0; i < num; i++) { float num2 = ((num > 1) ? ((float)i / (float)(num - 1)) : 0f); Vector3 localDirection = ((state != null && state.RestHorizontalDirectionsLocal != null && i < state.RestHorizontalDirectionsLocal.Length) ? state.RestHorizontalDirectionsLocal[i] : ResolveFallbackLateralDirection(runtimeTwinTailPhysicsChain, i)); Vector3 val3 = TransformDirectionWithoutScale(localDirection); val3 = Vector3.ProjectOnPlane(val3, val); if (((Vector3)(ref val3)).sqrMagnitude <= 1E-06f) { val3 = Vector3.ProjectOnPlane(val2, val); } if (((Vector3)(ref val3)).sqrMagnitude <= 1E-06f) { Vector3 localDirection2 = ResolveFallbackLateralDirection(runtimeTwinTailPhysicsChain, i); val3 = TransformDirectionWithoutScale(localDirection2); } float num3 = Mathf.Lerp(0.56f, 0.08f, num2); float num4 = Mathf.Lerp(0.78f, 1.2f, num2); Vector3 val4 = ((Vector3)(ref val3)).normalized * num3 + val * num4; Vector3 val5 = ((Vector3)(ref val4)).normalized; if (((Vector3)(ref val5)).sqrMagnitude <= 1E-06f) { val5 = val; } val4 = Vector3.Slerp(val2, val5, 0.72f); val5 = ((Vector3)(ref val4)).normalized; array[i + 1] = array[i] + val5 * runtimeTwinTailPhysicsChain.SegmentLengths[i]; val2 = val5; } return array; } private Vector3 GetStableGravityWorld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Vector3 gravity = Physics.gravity; if (((Vector3)(ref gravity)).sqrMagnitude <= 1E-06f) { return Vector3.down * 1.6f; } return gravity * 1.6f; } private void ApplyChainToBones(ChainState state) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_014e: 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_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_017e: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: 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) RuntimeTwinTailPhysicsChain chain = state.Chain; if (chain == null) { return; } for (int i = 0; i < chain.BoneIndices.Length; i++) { int num = chain.BoneIndices[i]; if (num < 0 || num >= _boneTransforms.Length) { continue; } Transform val = _boneTransforms[num]; if ((Object)(object)val == (Object)null) { continue; } Vector3 val2 = ((i + 1 < state.CurrentPositions.Length) ? (state.CurrentPositions[i + 1] - val.position) : (state.CurrentPositions[i] - val.position)); if (((Vector3)(ref val2)).sqrMagnitude <= 1E-06f) { continue; } Quaternion val3 = ((state.RestLocalRotations != null && i < state.RestLocalRotations.Length) ? state.RestLocalRotations[i] : val.localRotation); Vector3 val4 = ((state.RestParentDirections != null && i < state.RestParentDirections.Length) ? state.RestParentDirections[i] : Vector3.down); if (((Vector3)(ref val4)).sqrMagnitude <= 1E-06f) { continue; } if (i == 0) { val.localRotation = val3; continue; } Vector3 val5 = (((Object)(object)val.parent != (Object)null) ? (Quaternion.Inverse(val.parent.rotation) * ((Vector3)(ref val2)).normalized) : ((Vector3)(ref val2)).normalized); if (!(((Vector3)(ref val5)).sqrMagnitude <= 1E-06f)) { Quaternion val6 = Quaternion.FromToRotation(((Vector3)(ref val4)).normalized, ((Vector3)(ref val5)).normalized) * val3; if (i == 1) { val6 = Quaternion.Slerp(val6, val3, 0.2f); } val.localRotation = Quaternion.Slerp(val.localRotation, val6, 0.32f); } } } private Quaternion[] CaptureRestLocalRotations(int[] boneIndices) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (boneIndices == null || boneIndices.Length == 0) { return Array.Empty(); } Quaternion[] array = (Quaternion[])(object)new Quaternion[boneIndices.Length]; for (int i = 0; i < boneIndices.Length; i++) { int num = boneIndices[i]; array[i] = ((num >= 0 && num < _boneTransforms.Length && (Object)(object)_boneTransforms[num] != (Object)null) ? _boneTransforms[num].localRotation : Quaternion.identity); } return array; } private Vector3[] CaptureRestParentDirections(RuntimeTwinTailPhysicsChain chain) { //IL_0049: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if (chain == null || chain.BoneIndices == null || chain.BoneIndices.Length == 0) { return Array.Empty(); } Vector3[] array = (Vector3[])(object)new Vector3[chain.BoneIndices.Length]; for (int i = 0; i < chain.BoneIndices.Length; i++) { int num = chain.BoneIndices[i]; if (num < 0 || num >= _boneTransforms.Length) { array[i] = Vector3.down; continue; } Transform val = _boneTransforms[num]; if ((Object)(object)val == (Object)null) { array[i] = Vector3.down; continue; } Vector3 val3; if (i + 1 < chain.BoneIndices.Length) { int num2 = chain.BoneIndices[i + 1]; Transform val2 = ((num2 >= 0 && num2 < _boneTransforms.Length) ? _boneTransforms[num2] : null); val3 = (((Object)(object)val2 != (Object)null) ? val2.position : val.TransformPoint(chain.LastTailLocalOffset)); } else { Vector3 val4 = ((((Vector3)(ref chain.LastTailLocalOffset)).sqrMagnitude > 1E-06f) ? chain.LastTailLocalOffset : (Vector3.down * 0.01f)); val3 = val.TransformPoint(val4); } Vector3 val5 = (((Object)(object)val.parent != (Object)null) ? (Quaternion.Inverse(val.parent.rotation) * (val3 - val.position)) : (val3 - val.position)); array[i] = ((((Vector3)(ref val5)).sqrMagnitude > 1E-06f) ? ((Vector3)(ref val5)).normalized : Vector3.down); } return array; } private Vector3[] CaptureCurrentChainWorldPositions(RuntimeTwinTailPhysicsChain chain) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if (chain == null || chain.BoneIndices == null || chain.BoneIndices.Length == 0) { return Array.Empty(); } Vector3[] array = (Vector3[])(object)new Vector3[chain.BoneIndices.Length + 1]; for (int i = 0; i < chain.BoneIndices.Length; i++) { array[i] = GetCurrentBoneWorldPosition(chain.BoneIndices[i], ((Object)(object)_skeletonRoot != (Object)null) ? _skeletonRoot.TransformPoint(chain.NodeLocalPositions[i]) : chain.NodeLocalPositions[i]); } int num = chain.BoneIndices[chain.BoneIndices.Length - 1]; Transform val = ((num >= 0 && num < _boneTransforms.Length) ? _boneTransforms[num] : null); array[^1] = (((Object)(object)val != (Object)null) ? val.TransformPoint(chain.LastTailLocalOffset) : (((Object)(object)_skeletonRoot != (Object)null) ? _skeletonRoot.TransformPoint(chain.NodeLocalPositions[chain.NodeLocalPositions.Length - 1]) : chain.NodeLocalPositions[chain.NodeLocalPositions.Length - 1])); return array; } private Vector3 GetCurrentBoneWorldPosition(int boneIndex, Vector3 fallback) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (boneIndex < 0 || boneIndex >= _boneTransforms.Length || (Object)(object)_boneTransforms[boneIndex] == (Object)null) { return fallback; } return _boneTransforms[boneIndex].position; } private Quaternion GetCurrentBoneWorldRotation(int boneIndex, Quaternion fallback) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (boneIndex < 0 || boneIndex >= _boneTransforms.Length || (Object)(object)_boneTransforms[boneIndex] == (Object)null) { return fallback; } return _boneTransforms[boneIndex].rotation; } private Vector3[] CaptureRestHorizontalDirectionsLocal(RuntimeTwinTailPhysicsChain chain) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (chain == null || chain.RestDirections == null || chain.RestDirections.Length == 0) { return Array.Empty(); } Vector3[] array = (Vector3[])(object)new Vector3[chain.RestDirections.Length]; for (int i = 0; i < chain.RestDirections.Length; i++) { Vector3 val = Vector3.ProjectOnPlane(chain.RestDirections[i], Vector3.up); if (((Vector3)(ref val)).sqrMagnitude <= 1E-06f && i > 0) { val = array[i - 1]; } if (((Vector3)(ref val)).sqrMagnitude <= 1E-06f) { val = ResolveFallbackLateralDirection(chain, i); } array[i] = ((Vector3)(ref val)).normalized; } return array; } private static Vector3 ResolveFallbackLateralDirection(RuntimeTwinTailPhysicsChain chain, int segmentIndex) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) bool num = chain != null && !string.IsNullOrEmpty(chain.Name) && chain.Name.IndexOf(".L", StringComparison.OrdinalIgnoreCase) >= 0; bool flag = chain != null && !string.IsNullOrEmpty(chain.Name) && chain.Name.IndexOf(".R", StringComparison.OrdinalIgnoreCase) >= 0; if (num) { return Vector3.left; } if (flag) { return Vector3.right; } if (segmentIndex % 2 != 0) { return Vector3.left; } return Vector3.right; } private Vector3 TransformDirectionWithoutScale(Vector3 localDirection) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) if (!((Object)(object)_skeletonRoot != (Object)null)) { return localDirection; } return _skeletonRoot.rotation * localDirection; } private bool ConsumeItemStateReset() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_boundItem == (Object)null) { return false; } ItemState itemState = _boundItem.itemState; if (!_hasTrackedItemState) { _lastTrackedItemState = itemState; _hasTrackedItemState = true; return true; } if (itemState == _lastTrackedItemState) { return false; } _lastTrackedItemState = itemState; return true; } private bool ShouldHardResetChain(ChainState state, Vector3 anchorWorldPosition, Quaternion anchorWorldRotation) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (state == null || state.CurrentPositions == null || state.CurrentPositions.Length == 0) { return true; } float num = Mathf.Max(state.TotalLength * 0.72f, 0.12f); if (Vector3.Distance(state.CurrentPositions[0], anchorWorldPosition) > num) { return true; } return Quaternion.Angle(state.LastAnchorWorldRotation, anchorWorldRotation) > 70f; } private void ApplyAnchorMotion(ChainState state, Vector3 anchorWorldPosition, Quaternion anchorWorldRotation) { //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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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) if (state != null && state.CurrentPositions != null && state.CurrentPositions.Length != 0) { Vector3 val = state.CurrentPositions[0]; Quaternion lastAnchorWorldRotation = state.LastAnchorWorldRotation; Quaternion val2 = anchorWorldRotation * Quaternion.Inverse(lastAnchorWorldRotation); for (int i = 1; i < state.CurrentPositions.Length; i++) { Vector3 val3 = state.CurrentPositions[i] - val; Vector3 val4 = state.PreviousPositions[i] - val; state.CurrentPositions[i] = anchorWorldPosition + val2 * val3; state.PreviousPositions[i] = anchorWorldPosition + val2 * val4; } state.CurrentPositions[0] = anchorWorldPosition; state.PreviousPositions[0] = anchorWorldPosition; state.LastAnchorWorldRotation = anchorWorldRotation; } } private void ResetChainToCurrentPose(ChainState state, Quaternion anchorWorldRotation) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (state == null || state.Chain == null) { return; } Vector3[] array = CaptureCurrentChainWorldPositions(state.Chain); if (array != null && array.Length != 0) { if (state.CurrentPositions == null || state.CurrentPositions.Length != array.Length) { state.CurrentPositions = (Vector3[])(object)new Vector3[array.Length]; } if (state.PreviousPositions == null || state.PreviousPositions.Length != array.Length) { state.PreviousPositions = (Vector3[])(object)new Vector3[array.Length]; } Array.Copy(array, state.CurrentPositions, array.Length); Array.Copy(array, state.PreviousPositions, array.Length); state.LastAnchorWorldRotation = anchorWorldRotation; } } private static float ComputeTotalLength(RuntimeTwinTailPhysicsChain chain) { if (chain == null || chain.SegmentLengths == null || chain.SegmentLengths.Length == 0) { return 0.1f; } float num = 0f; for (int i = 0; i < chain.SegmentLengths.Length; i++) { num += Mathf.Max(chain.SegmentLengths[i], 0.01f); } return num; } private static Vector3 ClampDirectionToRestCone(Vector3 currentDirection, Vector3 restDirection, float maxAngleRadians) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref currentDirection)).sqrMagnitude <= 1E-06f || ((Vector3)(ref restDirection)).sqrMagnitude <= 1E-06f || maxAngleRadians <= 0.0001f) { if (!(((Vector3)(ref restDirection)).sqrMagnitude > 1E-06f)) { return ((Vector3)(ref currentDirection)).normalized; } return ((Vector3)(ref restDirection)).normalized; } Vector3 normalized = ((Vector3)(ref restDirection)).normalized; Vector3 normalized2 = ((Vector3)(ref currentDirection)).normalized; float num = Vector3.Angle(normalized, normalized2) * ((float)Math.PI / 180f); if (num <= maxAngleRadians) { return normalized2; } float num2 = maxAngleRadians / Mathf.Max(num, 0.0001f); Vector3 val = Vector3.Slerp(normalized, normalized2, num2); return ((Vector3)(ref val)).normalized; } } internal static class RuntimePmxLoader { private sealed class PmxMaterialInfo { internal string Name; internal string MainTexturePath; internal string ToonTexturePath; internal Color DiffuseColor; internal int SurfaceIndexCount; } private struct PmxVertexWeight { internal int BoneIndex0; internal int BoneIndex1; internal int BoneIndex2; internal int BoneIndex3; internal float Weight0; internal float Weight1; internal float Weight2; internal float Weight3; } private sealed class PmxMorphInfo { internal string Name; internal Dictionary VertexOffsets = new Dictionary(); } private sealed class PmxRigidBodyInfo { internal int Index; internal string Name; internal int BoneIndex; internal Vector3 Position; internal Vector3 Rotation; internal Vector3 Size; internal float Mass; internal float LinearDamping; internal float AngularDamping; internal int Mode; } private sealed class PmxJointInfo { internal string Name; internal int RigidBodyAIndex; internal int RigidBodyBIndex; internal Vector3 AngularLowerLimit; internal Vector3 AngularUpperLimit; } private sealed class PmxHeader { internal Encoding TextEncoding; internal int AdditionalUvCount; internal int VertexIndexSize; internal int TextureIndexSize; internal int MaterialIndexSize; internal int BoneIndexSize; internal int MorphIndexSize; internal int RigidBodyIndexSize; } private const string PreferredModelFileName = "fufummd.pmx"; private static readonly Vector3 ReferenceVisibleSizeAtBaseScale = new Vector3(1.5852638f, 1.2168914f, 0.8999324f); private static readonly Vector3 ReferenceVisibleCenterAtBaseScale = new Vector3(0.0330699f, 0.06277876f, 0.09902591f); private static readonly float DefaultRootTwinTailMaxAngleRadians = 0.08726646f; private static readonly float DefaultTwinTailMaxAngleRadians = 0.34906584f; private const string LeftTwinTailAnchorBoneName = "hair.002.L"; private const string RightTwinTailAnchorBoneName = "hair.002.R"; private static readonly string[] LeftTwinTailRigidBodyNames = new string[7] { "hair.003.L", "hair.004.L", "hair.005.L", "hair.006.L", "hair.007.L", "hair.008.L", "hair.009.L" }; private static readonly string[] RightTwinTailRigidBodyNames = new string[7] { "hair.003.R", "hair.004.R", "hair.005.R", "hair.006.R", "hair.007.R", "hair.008.R", "hair.009.R" }; internal static RuntimeReplacementModel Load(string replacementRoot, ManualLogSource log) { try { if (string.IsNullOrEmpty(replacementRoot) || !Directory.Exists(replacementRoot)) { return null; } string text = FindPmxPath(replacementRoot); if (string.IsNullOrEmpty(text)) { return null; } return BuildRuntimeModel(text, log); } catch (Exception ex) { if (log != null) { log.LogError((object)("Failed to load runtime PMX replacement: " + ex)); } return null; } } private static string FindPmxPath(string replacementRoot) { string text = Path.Combine(replacementRoot, "fufummd.pmx"); if (File.Exists(text)) { return text; } string[] files = Directory.GetFiles(replacementRoot, "*.pmx", SearchOption.TopDirectoryOnly); if (files.Length == 0) { return null; } return files[0]; } private static RuntimeReplacementModel BuildRuntimeModel(string pmxPath, ManualLogSource log) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: 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_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) using FileStream input = File.OpenRead(pmxPath); using BinaryReader binaryReader = new BinaryReader(input); PmxHeader pmxHeader = ReadHeader(binaryReader); ReadText(binaryReader, pmxHeader.TextEncoding); ReadText(binaryReader, pmxHeader.TextEncoding); ReadText(binaryReader, pmxHeader.TextEncoding); ReadText(binaryReader, pmxHeader.TextEncoding); int num = binaryReader.ReadInt32(); Vector3[] array = (Vector3[])(object)new Vector3[num]; Vector3[] array2 = (Vector3[])(object)new Vector3[num]; Vector2[] array3 = (Vector2[])(object)new Vector2[num]; PmxVertexWeight[] array4 = new PmxVertexWeight[num]; for (int i = 0; i < num; i++) { array[i] = ConvertPosition(ReadVector3(binaryReader)); array2[i] = ConvertNormal(ReadVector3(binaryReader)); array3[i] = ConvertUv(ReadVector2(binaryReader)); SkipAdditionalUv(binaryReader, pmxHeader.AdditionalUvCount); array4[i] = ReadVertexWeight(binaryReader, pmxHeader.BoneIndexSize); binaryReader.ReadSingle(); } int num2 = binaryReader.ReadInt32(); int[] array5 = new int[num2]; for (int j = 0; j < num2; j++) { array5[j] = ReadUnsignedIndex(binaryReader, pmxHeader.VertexIndexSize); } List texturePaths = ReadTexturePaths(binaryReader, pmxHeader.TextEncoding, pmxPath); List materials = ReadMaterials(binaryReader, pmxHeader, texturePaths); Dictionary textureCache = new Dictionary(StringComparer.OrdinalIgnoreCase); Texture2D primaryTexture; Texture2D iconTexture; Material[] array6 = BuildMaterials(materials, textureCache, log, out primaryTexture, out iconTexture); Mesh val = BuildMesh(Path.GetFileNameWithoutExtension(pmxPath), array, array2, array3, array5, materials); RuntimeBoneInfo[] array7 = ReadBones(binaryReader, pmxHeader); List morphs = ReadMorphs(binaryReader, pmxHeader); SkipDisplayFrames(binaryReader, pmxHeader); RuntimeTwinTailPhysicsChain[] array8 = Array.Empty(); Bounds bounds = val.bounds; Vector3 recommendedBaseScale = CalculateRecommendedBaseScale(((Bounds)(ref bounds)).size.y); Vector3 meshLocalOffset = CalculateMeshOffset(val.bounds, recommendedBaseScale); int num3 = DetermineRootBoneIndex(array7); bool flag = TryApplySkinning(val, array7, array4, meshLocalOffset, num3, log); int num4 = ApplyExpressionBlendShapes(val, morphs, log); if (log != null) { string[] obj = new string[18] { "[RuntimePmxLoader] PMX mesh ready: subMeshes=", val.subMeshCount.ToString(), ", materials=", array6.Length.ToString(), ", bones=", array7.Length.ToString(), ", skinned=", flag.ToString(), ", twinTailChains=", array8.Length.ToString(), ", expressionShapes=", num4.ToString(), ", boundsSize=", null, null, null, null, null }; bounds = val.bounds; Vector3 size = ((Bounds)(ref bounds)).size; obj[13] = ((Vector3)(ref size)).ToString("F4"); obj[14] = ", baseScale="; obj[15] = ((Vector3)(ref recommendedBaseScale)).ToString("F4"); obj[16] = ", meshOffset="; obj[17] = ((Vector3)(ref meshLocalOffset)).ToString("F4"); log.LogInfo((object)string.Concat(obj)); } return new RuntimeReplacementModel("Miku", val, array6, flag ? array7 : Array.Empty(), flag ? array8 : Array.Empty(), flag ? num3 : (-1), meshLocalOffset, recommendedBaseScale, primaryTexture, iconTexture); } private static PmxHeader ReadHeader(BinaryReader reader) { string @string = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (!string.Equals(@string, "PMX ", StringComparison.Ordinal)) { throw new InvalidDataException("Unsupported PMX signature: " + @string); } float num = reader.ReadSingle(); if (num < 2f || num >= 3f) { throw new InvalidDataException("Unsupported PMX version: " + num); } byte count = reader.ReadByte(); byte[] array = reader.ReadBytes(count); if (array.Length < 8) { throw new InvalidDataException("PMX header is incomplete."); } return new PmxHeader { TextEncoding = ((array[0] == 0) ? Encoding.Unicode : Encoding.UTF8), AdditionalUvCount = array[1], VertexIndexSize = array[2], TextureIndexSize = array[3], MaterialIndexSize = array[4], BoneIndexSize = array[5], MorphIndexSize = array[6], RigidBodyIndexSize = array[7] }; } private static string ReadText(BinaryReader reader, Encoding encoding) { int num = reader.ReadInt32(); if (num <= 0) { return string.Empty; } byte[] bytes = reader.ReadBytes(num); return encoding.GetString(bytes); } private static void SkipAdditionalUv(BinaryReader reader, int additionalUvCount) { for (int i = 0; i < additionalUvCount; i++) { reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); } } private static PmxVertexWeight ReadVertexWeight(BinaryReader reader, int boneIndexSize) { PmxVertexWeight result = default(PmxVertexWeight); byte b = reader.ReadByte(); switch (b) { case 0: result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = 1f; break; case 1: result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex1 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = reader.ReadSingle(); result.Weight1 = 1f - result.Weight0; break; case 2: case 4: result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex1 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex2 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex3 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = reader.ReadSingle(); result.Weight1 = reader.ReadSingle(); result.Weight2 = reader.ReadSingle(); result.Weight3 = reader.ReadSingle(); break; case 3: { result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex1 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = reader.ReadSingle(); result.Weight1 = 1f - result.Weight0; for (int i = 0; i < 9; i++) { reader.ReadSingle(); } break; } default: throw new InvalidDataException("Unsupported PMX vertex deform type: " + b); } return result; } private static List ReadTexturePaths(BinaryReader reader, Encoding encoding, string pmxPath) { int num = reader.ReadInt32(); List list = new List(num); string baseDirectory = Path.GetDirectoryName(pmxPath) ?? string.Empty; for (int i = 0; i < num; i++) { string relativePath = ReadText(reader, encoding); list.Add(ResolveRelativePath(baseDirectory, relativePath)); } return list; } private static List ReadMaterials(BinaryReader reader, PmxHeader header, List texturePaths) { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) int num = reader.ReadInt32(); List list = new List(num); Color diffuseColor = default(Color); for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); ((Color)(ref diffuseColor))..ctor(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadByte(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); int index = ReadSignedIndex(reader, header.TextureIndexSize); ReadSignedIndex(reader, header.TextureIndexSize); reader.ReadByte(); byte b = reader.ReadByte(); int index2 = ((b == 0) ? ReadSignedIndex(reader, header.TextureIndexSize) : reader.ReadByte()); ReadText(reader, header.TextEncoding); int surfaceIndexCount = reader.ReadInt32(); list.Add(new PmxMaterialInfo { Name = name, MainTexturePath = GetTexturePath(texturePaths, index), ToonTexturePath = ((b == 0) ? GetTexturePath(texturePaths, index2) : null), DiffuseColor = diffuseColor, SurfaceIndexCount = surfaceIndexCount }); _ = 0; } return list; } private static Material[] BuildMaterials(List materials, Dictionary textureCache, ManualLogSource log, out Texture2D primaryTexture, out Texture2D iconTexture) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) primaryTexture = null; iconTexture = null; Shader val = FindCompatibleShader(); Material[] array = (Material[])(object)new Material[Mathf.Max(1, materials.Count)]; for (int i = 0; i < array.Length; i++) { PmxMaterialInfo pmxMaterialInfo = ((i < materials.Count) ? materials[i] : null); Material val2 = (((Object)(object)val != (Object)null) ? new Material(val) : new Material(Shader.Find("Standard"))); ((Object)val2).name = ((pmxMaterialInfo != null && !string.IsNullOrEmpty(pmxMaterialInfo.Name)) ? pmxMaterialInfo.Name : ("FufuMaterial_" + i)); val2.renderQueue = 2000; Texture2D val3 = LoadTexture(pmxMaterialInfo?.MainTexturePath, textureCache, log); if ((Object)(object)val3 == (Object)null && pmxMaterialInfo != null && IsFaceMaterial(pmxMaterialInfo.Name)) { val3 = LoadNamedTexture(textureCache, pmxMaterialInfo, "face", log); } if ((Object)(object)val3 != (Object)null && (Object)(object)primaryTexture == (Object)null) { primaryTexture = val3; } if ((Object)(object)val3 != (Object)null && (Object)(object)iconTexture == (Object)null && IsIconMaterial((pmxMaterialInfo != null) ? pmxMaterialInfo.Name : string.Empty)) { iconTexture = val3; } if (pmxMaterialInfo != null && IsScallionAccessoryMaterial(pmxMaterialInfo.Name)) { ConfigureHiddenSurface(val2); array[i] = val2; continue; } ApplyTexture(val2, val3); ApplyColor(val2, ((Object)(object)val3 != (Object)null) ? Color.white : (pmxMaterialInfo?.DiffuseColor ?? Color.white)); ConfigureOpaqueSurface(val2); array[i] = val2; } if ((Object)(object)primaryTexture == (Object)null) { primaryTexture = FindFirstTexture(textureCache); } if ((Object)(object)iconTexture == (Object)null) { iconTexture = primaryTexture; } return array; } private static Texture2D FindFirstTexture(Dictionary textureCache) { foreach (KeyValuePair item in textureCache) { if ((Object)(object)item.Value != (Object)null) { return item.Value; } } return null; } private static Texture2D LoadNamedTexture(Dictionary textureCache, PmxMaterialInfo info, string nameHint, ManualLogSource log) { if (info == null) { return null; } Texture2D val = LoadTexture(info.MainTexturePath, textureCache, log); if ((Object)(object)val != (Object)null) { return val; } Texture2D val2 = LoadTexture(info.ToonTexturePath, textureCache, log); if ((Object)(object)val2 != (Object)null && info.Name != null && info.Name.IndexOf(nameHint, StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } return null; } private static Texture2D LoadTexture(string fullPath, Dictionary textureCache, ManualLogSource log) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(fullPath)) { return null; } if (textureCache.TryGetValue(fullPath, out var value)) { return value; } if (!File.Exists(fullPath)) { textureCache[fullPath] = null; return null; } try { using FileStream fileStream = File.OpenRead(fullPath); Bitmap val = new Bitmap((Stream)fileStream); try { int width = ((Image)val).Width; int height = ((Image)val).Height; Color32[] array = (Color32[])(object)new Color32[width * height]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Color pixel = val.GetPixel(j, height - 1 - i); array[i * width + j] = new Color32(pixel.R, pixel.G, pixel.B, pixel.A); } } Texture2D val2 = new Texture2D(width, height, (TextureFormat)4, false, false); ((Object)val2).name = Path.GetFileNameWithoutExtension(fullPath); val2.SetPixels32(array); ((Texture)val2).filterMode = (FilterMode)1; ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).anisoLevel = 1; val2.Apply(false, false); textureCache[fullPath] = val2; return val2; } finally { ((IDisposable)val)?.Dispose(); } } catch (Exception ex) { if (log != null) { log.LogWarning((object)("Failed to load PMX texture '" + fullPath + "': " + ex.Message)); } textureCache[fullPath] = null; return null; } } private static Mesh BuildMesh(string meshName, Vector3[] positions, Vector3[] normals, Vector2[] uvs, int[] faceIndices, List materials) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh(); ((Object)val).name = (string.IsNullOrEmpty(meshName) ? "FufuMesh" : meshName); if (positions.Length > 65535) { val.indexFormat = (IndexFormat)1; } val.vertices = positions; val.normals = normals; val.uv = uvs; val.subMeshCount = Mathf.Max(1, materials.Count); int num = 0; int num2 = Mathf.Max(1, materials.Count); bool hasUsedVertices = false; Vector3 minBounds = Vector3.zero; Vector3 maxBounds = Vector3.zero; for (int i = 0; i < num2; i++) { PmxMaterialInfo pmxMaterialInfo = ((i < materials.Count) ? materials[i] : null); int num3 = pmxMaterialInfo?.SurfaceIndexCount ?? (faceIndices.Length - num); bool num4 = pmxMaterialInfo != null && IsScallionAccessoryMaterial(pmxMaterialInfo.Name); num3 = Mathf.Clamp(num3, 0, faceIndices.Length - num); int[] array = (num4 ? Array.Empty() : new int[num3]); if (!num4) { for (int j = 0; j + 2 < num3; j += 3) { int num5 = faceIndices[num + j]; int num6 = faceIndices[num + j + 2]; int num7 = faceIndices[num + j + 1]; array[j] = num5; array[j + 1] = num6; array[j + 2] = num7; ExpandBoundsWithVertex(positions, num5, ref hasUsedVertices, ref minBounds, ref maxBounds); ExpandBoundsWithVertex(positions, num6, ref hasUsedVertices, ref minBounds, ref maxBounds); ExpandBoundsWithVertex(positions, num7, ref hasUsedVertices, ref minBounds, ref maxBounds); } } val.SetTriangles(array, i, true); num += num3; } if (hasUsedVertices) { Bounds bounds = default(Bounds); ((Bounds)(ref bounds))..ctor((minBounds + maxBounds) * 0.5f, maxBounds - minBounds); ((Bounds)(ref bounds)).Expand(0.0001f); val.bounds = bounds; } else { val.RecalculateBounds(); } return val; } private static void ExpandBoundsWithVertex(Vector3[] positions, int vertexIndex, ref bool hasUsedVertices, ref Vector3 minBounds, ref Vector3 maxBounds) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (positions != null && vertexIndex >= 0 && vertexIndex < positions.Length) { Vector3 val = positions[vertexIndex]; if (!hasUsedVertices) { minBounds = val; maxBounds = val; hasUsedVertices = true; } else { minBounds = Vector3.Min(minBounds, val); maxBounds = Vector3.Max(maxBounds, val); } } } private static RuntimeBoneInfo[] ReadBones(BinaryReader reader, PmxHeader header) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) int num = reader.ReadInt32(); RuntimeBoneInfo[] array = new RuntimeBoneInfo[num]; for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); Vector3 val = ConvertPosition(ReadVector3(reader)); int parentIndex = ReadSignedIndex(reader, header.BoneIndexSize); reader.ReadInt32(); ushort num2 = reader.ReadUInt16(); int tailBoneIndex = -1; Vector3 tailLocalOffset = Vector3.zero; if (((uint)num2 & (true ? 1u : 0u)) != 0) { tailBoneIndex = ReadSignedIndex(reader, header.BoneIndexSize); } else { tailLocalOffset = ConvertPosition(ReadVector3(reader)); } if ((num2 & 0x100u) != 0) { ReadSignedIndex(reader, header.BoneIndexSize); reader.ReadSingle(); } if ((num2 & 0x200u) != 0) { ReadSignedIndex(reader, header.BoneIndexSize); reader.ReadSingle(); } if ((num2 & 0x400u) != 0) { ReadVector3(reader); } if ((num2 & 0x800u) != 0) { ReadVector3(reader); ReadVector3(reader); } if ((num2 & 0x2000u) != 0) { reader.ReadInt32(); } if ((num2 & 0x20u) != 0) { SkipIkData(reader, header.BoneIndexSize); } array[i] = new RuntimeBoneInfo { Name = name, ParentIndex = parentIndex, AbsolutePosition = val, LocalPosition = val, TailBoneIndex = tailBoneIndex, TailLocalOffset = tailLocalOffset }; } foreach (RuntimeBoneInfo runtimeBoneInfo in array) { if (runtimeBoneInfo.ParentIndex >= 0 && runtimeBoneInfo.ParentIndex < array.Length) { runtimeBoneInfo.LocalPosition = runtimeBoneInfo.AbsolutePosition - array[runtimeBoneInfo.ParentIndex].AbsolutePosition; } else { runtimeBoneInfo.LocalPosition = runtimeBoneInfo.AbsolutePosition; } if (runtimeBoneInfo.TailBoneIndex >= 0 && runtimeBoneInfo.TailBoneIndex < array.Length) { runtimeBoneInfo.TailLocalOffset = array[runtimeBoneInfo.TailBoneIndex].AbsolutePosition - runtimeBoneInfo.AbsolutePosition; } } return array; } private static void SkipIkData(BinaryReader reader, int boneIndexSize) { //IL_0035: 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) ReadSignedIndex(reader, boneIndexSize); reader.ReadInt32(); reader.ReadSingle(); int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { ReadSignedIndex(reader, boneIndexSize); if (reader.ReadByte() != 0) { ReadVector3(reader); ReadVector3(reader); } } } private static List ReadMorphs(BinaryReader reader, PmxHeader header) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) int num = reader.ReadInt32(); List list = new List(num); for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); reader.ReadByte(); byte b = reader.ReadByte(); int num2 = reader.ReadInt32(); if (b == 1) { PmxMorphInfo pmxMorphInfo = new PmxMorphInfo { Name = name }; for (int j = 0; j < num2; j++) { int key = ReadUnsignedIndex(reader, header.VertexIndexSize); Vector3 value = ConvertPosition(ReadVector3(reader)); pmxMorphInfo.VertexOffsets[key] = value; } list.Add(pmxMorphInfo); } else { SkipMorphOffsets(reader, header, b, num2); } } return list; } private static void SkipDisplayFrames(BinaryReader reader, PmxHeader header) { int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); reader.ReadByte(); int num2 = reader.ReadInt32(); for (int j = 0; j < num2; j++) { if (reader.ReadByte() == 0) { ReadSignedIndex(reader, header.BoneIndexSize); } else { ReadSignedIndex(reader, header.MorphIndexSize); } } } } private static List ReadRigidBodies(BinaryReader reader, PmxHeader header) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) int num = reader.ReadInt32(); List list = new List(num); for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); int boneIndex = ReadSignedIndex(reader, header.BoneIndexSize); reader.ReadByte(); reader.ReadUInt16(); reader.ReadByte(); Vector3 size = ReadVector3(reader); Vector3 position = ConvertPosition(ReadVector3(reader)); Vector3 rotation = ReadVector3(reader); float mass = reader.ReadSingle(); float linearDamping = reader.ReadSingle(); float angularDamping = reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); int mode = reader.ReadByte(); list.Add(new PmxRigidBodyInfo { Index = i, Name = name, BoneIndex = boneIndex, Position = position, Rotation = rotation, Size = size, Mass = mass, LinearDamping = linearDamping, AngularDamping = angularDamping, Mode = mode }); } return list; } private static List ReadJoints(BinaryReader reader, PmxHeader header) { //IL_0053: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) int num = reader.ReadInt32(); List list = new List(num); for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); reader.ReadByte(); int rigidBodyAIndex = ReadSignedIndex(reader, header.RigidBodyIndexSize); int rigidBodyBIndex = ReadSignedIndex(reader, header.RigidBodyIndexSize); ReadVector3(reader); ReadVector3(reader); ReadVector3(reader); ReadVector3(reader); Vector3 angularLowerLimit = ReadVector3(reader); Vector3 angularUpperLimit = ReadVector3(reader); ReadVector3(reader); ReadVector3(reader); list.Add(new PmxJointInfo { Name = name, RigidBodyAIndex = rigidBodyAIndex, RigidBodyBIndex = rigidBodyBIndex, AngularLowerLimit = angularLowerLimit, AngularUpperLimit = angularUpperLimit }); } return list; } private static RuntimeTwinTailPhysicsChain[] BuildTwinTailPhysicsChains(RuntimeBoneInfo[] bones, List rigidBodies, List joints, ManualLogSource log) { if (bones == null || bones.Length == 0 || rigidBodies == null || rigidBodies.Count == 0 || joints == null || joints.Count == 0) { return Array.Empty(); } Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < rigidBodies.Count; i++) { PmxRigidBodyInfo pmxRigidBodyInfo = rigidBodies[i]; if (pmxRigidBodyInfo != null && !string.IsNullOrEmpty(pmxRigidBodyInfo.Name) && !dictionary.ContainsKey(pmxRigidBodyInfo.Name)) { dictionary.Add(pmxRigidBodyInfo.Name, pmxRigidBodyInfo); } } List list = new List(2); RuntimeTwinTailPhysicsChain runtimeTwinTailPhysicsChain = BuildTwinTailPhysicsChain("TwinTail.L", "hair.002.L", LeftTwinTailRigidBodyNames, bones, dictionary, joints, log); if (runtimeTwinTailPhysicsChain != null) { list.Add(runtimeTwinTailPhysicsChain); } RuntimeTwinTailPhysicsChain runtimeTwinTailPhysicsChain2 = BuildTwinTailPhysicsChain("TwinTail.R", "hair.002.R", RightTwinTailRigidBodyNames, bones, dictionary, joints, log); if (runtimeTwinTailPhysicsChain2 != null) { list.Add(runtimeTwinTailPhysicsChain2); } return list.ToArray(); } private static RuntimeTwinTailPhysicsChain BuildTwinTailPhysicsChain(string chainName, string anchorBoneName, string[] rigidBodyNames, RuntimeBoneInfo[] bones, Dictionary rigidBodiesByName, List joints, ManualLogSource log) { //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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0206: 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_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(anchorBoneName) || rigidBodyNames == null || rigidBodyNames.Length == 0 || bones == null || bones.Length == 0) { return null; } int num = FindBoneIndexByName(bones, anchorBoneName); if (num < 0 || num >= bones.Length) { if (log != null) { log.LogWarning((object)("[RuntimePmxLoader] Missing twin tail anchor bone: " + anchorBoneName)); } return null; } PmxRigidBodyInfo[] array = new PmxRigidBodyInfo[rigidBodyNames.Length]; for (int i = 0; i < rigidBodyNames.Length; i++) { string text = rigidBodyNames[i]; if (!rigidBodiesByName.TryGetValue(text, out var value) || value == null || value.BoneIndex < 0 || value.BoneIndex >= bones.Length) { if (log != null) { log.LogWarning((object)("[RuntimePmxLoader] Missing twin tail rigidbody or bone binding: " + text)); } return null; } array[i] = value; } int num2 = array.Length + 1; int[] array2 = new int[num2]; Vector3[] array3 = (Vector3[])(object)new Vector3[num2 + 1]; Vector3[] array4 = (Vector3[])(object)new Vector3[num2]; Vector3[] array5 = (Vector3[])(object)new Vector3[num2]; float[] array6 = new float[num2]; float[] array7 = new float[num2]; float[] array8 = new float[num2]; array2[0] = num; array3[0] = bones[num].AbsolutePosition; Vector3 val = bones[array[0].BoneIndex].AbsolutePosition - bones[num].AbsolutePosition; if (((Vector3)(ref val)).sqrMagnitude <= 1E-06f) { val = ResolveBoneTailOffset(bones, num); } if (((Vector3)(ref val)).sqrMagnitude <= 1E-06f) { val = Vector3.down * 0.01f; } array4[0] = val; array8[0] = ComputeSegmentDamping(array[0]); array7[0] = DefaultRootTwinTailMaxAngleRadians; for (int j = 1; j < num2; j++) { int num3 = j - 1; int num4 = (array2[j] = array[num3].BoneIndex); array3[j] = bones[num4].AbsolutePosition; Vector3 val2 = ResolveBoneTailOffset(bones, num4); if (((Vector3)(ref val2)).sqrMagnitude <= 1E-06f) { val2 = ((num3 + 1 >= array.Length) ? (array3[j] - array3[j - 1]) : (bones[array[num3 + 1].BoneIndex].AbsolutePosition - bones[num4].AbsolutePosition)); } array4[j] = val2; array8[j] = ComputeSegmentDamping(array[num3]); array7[j] = ResolveSegmentLimitRadians(joints, array, num3); } for (int k = 0; k < num2; k++) { Vector3 val3; if (k == 0) { val3 = array4[0]; } else { val3 = ((k + 1 < num2) ? (bones[array2[k + 1]].AbsolutePosition - bones[array2[k]].AbsolutePosition) : array4[k]); int num5 = k - 1; if (((Vector3)(ref val3)).sqrMagnitude <= 1E-06f && num5 > 0) { val3 = array[num5].Position - array[num5 - 1].Position; } if (((Vector3)(ref val3)).sqrMagnitude <= 1E-06f) { val3 = array3[k] - array3[k - 1]; } } float num6 = ((Vector3)(ref val3)).magnitude; if (num6 <= 0.0001f) { val3 = Vector3.down * 0.01f; num6 = 0.01f; } array3[k + 1] = array3[k] + val3; array5[k] = val3 / num6; array6[k] = num6; } RuntimeTwinTailPhysicsChain result = new RuntimeTwinTailPhysicsChain { Name = chainName, AnchorBoneIndex = num, BoneIndices = array2, NodeLocalPositions = array3, ChildLocalOffsets = array4, RestDirections = array5, SegmentLengths = array6, MaxAnglesRadians = array7, SegmentDamping = array8, LastTailLocalOffset = array4[num2 - 1] }; if (log != null) { log.LogInfo((object)("[RuntimePmxLoader] Built twin tail chain " + chainName + ": bones=" + num2 + ", rootBone=" + bones[num].Name + ", tipBone=" + bones[array2[num2 - 1]].Name + ", rootLimitDeg=" + (array7[0] * 57.29578f).ToString("F1") + ", lastLimitDeg=" + (array7[num2 - 1] * 57.29578f).ToString("F1"))); } return result; } private static int FindBoneIndexByName(RuntimeBoneInfo[] bones, string boneName) { if (bones == null || string.IsNullOrEmpty(boneName)) { return -1; } for (int i = 0; i < bones.Length; i++) { RuntimeBoneInfo runtimeBoneInfo = bones[i]; if (runtimeBoneInfo != null && string.Equals(runtimeBoneInfo.Name, boneName, StringComparison.OrdinalIgnoreCase)) { return i; } } return -1; } private static Vector3 ResolveBoneTailOffset(RuntimeBoneInfo[] bones, int boneIndex) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (bones == null || boneIndex < 0 || boneIndex >= bones.Length) { return Vector3.zero; } RuntimeBoneInfo runtimeBoneInfo = bones[boneIndex]; if (runtimeBoneInfo == null) { return Vector3.zero; } if (((Vector3)(ref runtimeBoneInfo.TailLocalOffset)).sqrMagnitude > 1E-06f) { return runtimeBoneInfo.TailLocalOffset; } foreach (RuntimeBoneInfo runtimeBoneInfo2 in bones) { if (runtimeBoneInfo2 != null && runtimeBoneInfo2.ParentIndex == boneIndex) { return runtimeBoneInfo2.AbsolutePosition - runtimeBoneInfo.AbsolutePosition; } } return Vector3.zero; } private static float ResolveSegmentLimitRadians(List joints, PmxRigidBodyInfo[] chainBodies, int segmentIndex) { if (joints == null || chainBodies == null || segmentIndex < 0 || segmentIndex >= chainBodies.Length) { if (segmentIndex != 0) { return DefaultTwinTailMaxAngleRadians; } return DefaultRootTwinTailMaxAngleRadians; } int index = chainBodies[segmentIndex].Index; int num = ((segmentIndex > 0) ? chainBodies[segmentIndex - 1].Index : (-1)); PmxJointInfo pmxJointInfo = null; for (int i = 0; i < joints.Count; i++) { PmxJointInfo pmxJointInfo2 = joints[i]; if (pmxJointInfo2 != null && (pmxJointInfo2.RigidBodyAIndex == index || pmxJointInfo2.RigidBodyBIndex == index)) { if (num < 0) { pmxJointInfo = pmxJointInfo2; break; } if (pmxJointInfo2.RigidBodyAIndex == num || pmxJointInfo2.RigidBodyBIndex == num) { pmxJointInfo = pmxJointInfo2; break; } } } float result = ((segmentIndex == 0) ? DefaultRootTwinTailMaxAngleRadians : DefaultTwinTailMaxAngleRadians); if (pmxJointInfo == null) { return result; } float num2 = Mathf.Max(new float[6] { Mathf.Abs(pmxJointInfo.AngularLowerLimit.x), Mathf.Abs(pmxJointInfo.AngularLowerLimit.y), Mathf.Abs(pmxJointInfo.AngularLowerLimit.z), Mathf.Abs(pmxJointInfo.AngularUpperLimit.x), Mathf.Abs(pmxJointInfo.AngularUpperLimit.y), Mathf.Abs(pmxJointInfo.AngularUpperLimit.z) }); if (!(num2 > 0.0001f)) { return result; } return num2; } private static float ComputeSegmentDamping(PmxRigidBodyInfo rigidBody) { if (rigidBody == null) { return 0.9f; } float num = Mathf.Clamp01((rigidBody.LinearDamping + rigidBody.AngularDamping) * 0.5f); return Mathf.Clamp(0.97f - num * 0.1f, 0.84f, 0.96f); } private static void SkipMorphOffsets(BinaryReader reader, PmxHeader header, byte morphType, int offsetCount) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < offsetCount; i++) { switch (morphType) { case 0: ReadSignedIndex(reader, header.MorphIndexSize); reader.ReadSingle(); break; case 2: ReadSignedIndex(reader, header.BoneIndexSize); ReadVector3(reader); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); break; case 3: case 4: case 5: case 6: case 7: ReadUnsignedIndex(reader, header.VertexIndexSize); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); break; case 8: { ReadSignedIndex(reader, header.MaterialIndexSize); reader.ReadByte(); for (int j = 0; j < 28; j++) { reader.ReadSingle(); } break; } default: throw new InvalidDataException("Unsupported PMX morph type: " + morphType); } } } private static int DetermineRootBoneIndex(RuntimeBoneInfo[] bones) { if (bones == null || bones.Length == 0) { return -1; } for (int i = 0; i < bones.Length; i++) { string text = bones[i].Name ?? string.Empty; if (text.IndexOf("全て", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("root", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("center", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("センター", StringComparison.OrdinalIgnoreCase) >= 0) { return i; } } for (int j = 0; j < bones.Length; j++) { if (bones[j].ParentIndex < 0) { return j; } } return 0; } private static bool TryApplySkinning(Mesh mesh, RuntimeBoneInfo[] bones, PmxVertexWeight[] vertexWeights, Vector3 meshLocalOffset, int rootBoneIndex, ManualLogSource log) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mesh == (Object)null || bones == null || bones.Length == 0 || vertexWeights == null || vertexWeights.Length != mesh.vertexCount) { return false; } try { mesh.boneWeights = BuildBoneWeights(vertexWeights, bones.Length, rootBoneIndex); mesh.bindposes = BuildBindPoses(bones, meshLocalOffset); return true; } catch (Exception ex) { if (log != null) { log.LogWarning((object)("[RuntimePmxLoader] Failed to apply PMX skinning, fallback to static mesh: " + ex.Message)); } return false; } } private static BoneWeight[] BuildBoneWeights(PmxVertexWeight[] sourceWeights, int boneCount, int fallbackBoneIndex) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) BoneWeight[] array = (BoneWeight[])(object)new BoneWeight[sourceWeights.Length]; int num = Mathf.Clamp(fallbackBoneIndex, 0, Mathf.Max(0, boneCount - 1)); for (int i = 0; i < sourceWeights.Length; i++) { PmxVertexWeight pmxVertexWeight = sourceWeights[i]; BoneWeight val = default(BoneWeight); ((BoneWeight)(ref val)).boneIndex0 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex0, boneCount, num); ((BoneWeight)(ref val)).boneIndex1 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex1, boneCount, num); ((BoneWeight)(ref val)).boneIndex2 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex2, boneCount, num); ((BoneWeight)(ref val)).boneIndex3 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex3, boneCount, num); ((BoneWeight)(ref val)).weight0 = Mathf.Max(0f, pmxVertexWeight.Weight0); ((BoneWeight)(ref val)).weight1 = Mathf.Max(0f, pmxVertexWeight.Weight1); ((BoneWeight)(ref val)).weight2 = Mathf.Max(0f, pmxVertexWeight.Weight2); ((BoneWeight)(ref val)).weight3 = Mathf.Max(0f, pmxVertexWeight.Weight3); BoneWeight val2 = val; float num2 = ((BoneWeight)(ref val2)).weight0 + ((BoneWeight)(ref val2)).weight1 + ((BoneWeight)(ref val2)).weight2 + ((BoneWeight)(ref val2)).weight3; if (num2 <= 0.0001f) { ((BoneWeight)(ref val2)).boneIndex0 = num; ((BoneWeight)(ref val2)).weight0 = 1f; ((BoneWeight)(ref val2)).weight1 = 0f; ((BoneWeight)(ref val2)).weight2 = 0f; ((BoneWeight)(ref val2)).weight3 = 0f; } else { float num3 = 1f / num2; ((BoneWeight)(ref val2)).weight0 = ((BoneWeight)(ref val2)).weight0 * num3; ((BoneWeight)(ref val2)).weight1 = ((BoneWeight)(ref val2)).weight1 * num3; ((BoneWeight)(ref val2)).weight2 = ((BoneWeight)(ref val2)).weight2 * num3; ((BoneWeight)(ref val2)).weight3 = ((BoneWeight)(ref val2)).weight3 * num3; } array[i] = val2; } return array; } private static int SanitizeBoneIndex(int boneIndex, int boneCount, int fallbackBoneIndex) { if (boneIndex < 0 || boneIndex >= boneCount) { return fallbackBoneIndex; } return boneIndex; } private static Matrix4x4[] BuildBindPoses(RuntimeBoneInfo[] bones, Vector3 meshLocalOffset) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_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_0022: Unknown result type (might be due to invalid IL or missing references) Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[bones.Length]; for (int i = 0; i < bones.Length; i++) { array[i] = Matrix4x4.Translate(meshLocalOffset - bones[i].AbsolutePosition); } return array; } private static int ApplyExpressionBlendShapes(Mesh mesh, List morphs, ManualLogSource log) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mesh == (Object)null || morphs == null || morphs.Count == 0) { return 0; } int vertexCount = mesh.vertexCount; int num = 0; Vector3[] array = (Vector3[])(object)new Vector3[vertexCount]; for (int i = 0; i < morphs.Count; i++) { PmxMorphInfo pmxMorphInfo = morphs[i]; if (pmxMorphInfo == null || pmxMorphInfo.VertexOffsets.Count == 0 || !IsSupportedExpressionMorphName(pmxMorphInfo.Name)) { continue; } Vector3[] array2 = (Vector3[])(object)new Vector3[vertexCount]; foreach (KeyValuePair vertexOffset in pmxMorphInfo.VertexOffsets) { if (vertexOffset.Key >= 0 && vertexOffset.Key < vertexCount) { array2[vertexOffset.Key] = vertexOffset.Value; } } mesh.AddBlendShapeFrame(pmxMorphInfo.Name, 100f, array2, array, array); num++; } if (num > 0 && log != null) { log.LogInfo((object)("[RuntimePmxLoader] Added expression blend shapes: " + num)); } return num; } private static bool IsSupportedExpressionMorphName(string morphName) { if (!string.IsNullOrEmpty(morphName)) { if (!string.Equals(morphName, "まばたき", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "blink", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "笑い", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク右", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク2", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク2右", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "あ", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "い", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "う", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "え", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "お", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "あ2", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "口角上げ", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "口角下げ", StringComparison.OrdinalIgnoreCase)) { return string.Equals(morphName, "はぅ", StringComparison.OrdinalIgnoreCase); } return true; } return false; } private static Shader FindCompatibleShader() { return Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Texture") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("W/Peak_Standard") ?? Shader.Find("Standard"); } private static void ApplyTexture(Material material, Texture2D texture) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) if (!((Object)(object)material == (Object)null) && !((Object)(object)texture == (Object)null)) { if (material.HasProperty("_BaseMap")) { material.SetTexture("_BaseMap", (Texture)(object)texture); material.SetTextureScale("_BaseMap", Vector2.one); material.SetTextureOffset("_BaseMap", Vector2.zero); } if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", (Texture)(object)texture); material.SetTextureScale("_MainTex", Vector2.one); material.SetTextureOffset("_MainTex", Vector2.zero); } } } private static void ApplyColor(Material material, Color color) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { color.a = 1f; if (material.HasProperty("_Tint")) { material.SetColor("_Tint", color); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } } } private static void ConfigureOpaqueSurface(Material material) { //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 0f); } if (material.HasProperty("_Blend")) { material.SetFloat("_Blend", 0f); } if (material.HasProperty("_ZWrite")) { material.SetFloat("_ZWrite", 1f); } if (material.HasProperty("_SrcBlend")) { material.SetFloat("_SrcBlend", 1f); } if (material.HasProperty("_DstBlend")) { material.SetFloat("_DstBlend", 0f); } if (material.HasProperty("_Cull")) { material.SetFloat("_Cull", 0f); } if (material.HasProperty("_Smoothness")) { material.SetFloat("_Smoothness", 0f); } if (material.HasProperty("_Glossiness")) { material.SetFloat("_Glossiness", 0f); } if (material.HasProperty("_Metallic")) { material.SetFloat("_Metallic", 0f); } if (material.HasProperty("_BumpScale")) { material.SetFloat("_BumpScale", 0f); } if (material.HasProperty("_OcclusionStrength")) { material.SetFloat("_OcclusionStrength", 0f); } if (material.HasProperty("_SpecularHighlights")) { material.SetFloat("_SpecularHighlights", 0f); } if (material.HasProperty("_EnvironmentReflections")) { material.SetFloat("_EnvironmentReflections", 0f); } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.white * 0.03f); material.EnableKeyword("_EMISSION"); } material.renderQueue = 2000; material.SetOverrideTag("RenderType", "Opaque"); material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_SURFACE_TYPE_OPAQUE"); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } } private static void ConfigureHiddenSurface(Material material) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { Color val = default(Color); ((Color)(ref val))..ctor(0f, 0f, 0f, 0f); if (material.HasProperty("_Tint")) { material.SetColor("_Tint", val); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", val); } if (material.HasProperty("_Color")) { material.SetColor("_Color", val); } if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 1f); } if (material.HasProperty("_Blend")) { material.SetFloat("_Blend", 0f); } if (material.HasProperty("_ZWrite")) { material.SetFloat("_ZWrite", 0f); } if (material.HasProperty("_SrcBlend")) { material.SetFloat("_SrcBlend", 5f); } if (material.HasProperty("_DstBlend")) { material.SetFloat("_DstBlend", 10f); } if (material.HasProperty("_Cull")) { material.SetFloat("_Cull", 0f); } if (material.HasProperty("_AlphaClip")) { material.SetFloat("_AlphaClip", 0f); } if (material.HasProperty("_BaseMap")) { material.SetTexture("_BaseMap", (Texture)null); } if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", (Texture)null); } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); material.DisableKeyword("_EMISSION"); } material.renderQueue = 3000; material.SetOverrideTag("RenderType", "Transparent"); material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.DisableKeyword("_SURFACE_TYPE_OPAQUE"); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } } private static string ResolveRelativePath(string baseDirectory, string relativePath) { if (string.IsNullOrEmpty(relativePath)) { return null; } string path = relativePath.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); return Path.GetFullPath(Path.Combine(baseDirectory, path)); } private static string GetTexturePath(List texturePaths, int index) { if (index < 0 || index >= texturePaths.Count) { return null; } return texturePaths[index]; } private static Vector3 ReadVector3(BinaryReader reader) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } private static Vector2 ReadVector2(BinaryReader reader) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector2(reader.ReadSingle(), reader.ReadSingle()); } private static Vector3 ConvertPosition(Vector3 source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return new Vector3(source.x, source.y, 0f - source.z); } private static Vector3 ConvertNormal(Vector3 source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return new Vector3(source.x, source.y, 0f - source.z); } private static Vector2 ConvertUv(Vector2 source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector2(source.x, 1f - source.y); } private static Vector3 CalculateMeshOffset(Bounds bounds, Vector3 recommendedBaseScale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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) float num = ((Mathf.Abs(recommendedBaseScale.y) > 0.0001f) ? recommendedBaseScale.y : 1f); return ReferenceVisibleCenterAtBaseScale / num - ((Bounds)(ref bounds)).center; } private static Vector3 CalculateRecommendedBaseScale(float sourceHeight) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (sourceHeight <= 0.0001f) { return Vector3.one * 0.09f; } float num = Mathf.Clamp(ReferenceVisibleSizeAtBaseScale.y / sourceHeight, 0.04f, 0.2f); return new Vector3(num, num, num); } private static int ReadUnsignedIndex(BinaryReader reader, int size) { return size switch { 1 => reader.ReadByte(), 2 => reader.ReadUInt16(), 4 => reader.ReadInt32(), _ => throw new InvalidDataException("Unsupported PMX unsigned index size: " + size), }; } private static int ReadSignedIndex(BinaryReader reader, int size) { return size switch { 1 => reader.ReadSByte(), 2 => reader.ReadInt16(), 4 => reader.ReadInt32(), _ => throw new InvalidDataException("Unsupported PMX signed index size: " + size), }; } private static bool IsFaceMaterial(string materialName) { if (!string.IsNullOrEmpty(materialName)) { if (materialName.IndexOf("face", StringComparison.OrdinalIgnoreCase) < 0 && materialName.IndexOf("head", StringComparison.OrdinalIgnoreCase) < 0) { return materialName.IndexOf("shy", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } private static bool IsIconMaterial(string materialName) { if (!string.IsNullOrEmpty(materialName)) { if (materialName.IndexOf("face", StringComparison.OrdinalIgnoreCase) < 0) { return materialName.IndexOf("shy", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } private static bool IsScallionAccessoryMaterial(string materialName) { if (string.IsNullOrEmpty(materialName)) { return false; } string text = materialName.Trim(); if (text.IndexOf("sou_onegi", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("onegi", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("negi_accessory", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("scallion accessory", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("green onion accessory", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("leek accessory", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } } [HarmonyPatch(typeof(Action_AskBingBong), "AskRoutine", new Type[] { typeof(int), typeof(bool) })] public static class Patch_AskRoutine { [CompilerGenerated] private sealed class <>c__DisplayClass13_0 { public string fileName; internal void b__0(AudioClip clip) { if ((Object)(object)clip != (Object)null) { CustomClips.Add(clip); ClipNames.Add(fileName); } } } [CompilerGenerated] private sealed class d__13 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (_hasLoadAttempt && !_isLoading) { return false; } if (_isLoading) { goto IL_0052; } _isLoading = true; _hasLoadAttempt = true; CustomClips.Clear(); ClipNames.Clear(); 5__2 = 0; goto IL_0107; case 1: <>1__state = -1; goto IL_0052; case 2: { <>1__state = -1; goto IL_00f7; } IL_00f7: 5__2++; goto IL_0107; IL_0107: if (5__2 < ExpectedFiles.Length) { <>c__DisplayClass13_0 CS$<>8__locals0 = new <>c__DisplayClass13_0 { fileName = ExpectedFiles[5__2] }; string text = Path.Combine(Plugin.directory, CS$<>8__locals0.fileName); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("[AudioPatch] Missing expected clip file: " + text)); goto IL_00f7; } <>2__current = LoadClip(text, delegate(AudioClip clip) { if ((Object)(object)clip != (Object)null) { CustomClips.Add(clip); ClipNames.Add(CS$<>8__locals0.fileName); } }); <>1__state = 2; return true; } Plugin.VerboseLog("[AudioPatch] Loaded custom clip count: " + CustomClips.Count); _isLoading = false; return false; IL_0052: if (_isLoading) { <>2__current = null; <>1__state = 1; return true; } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__14 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string filename; public Action onLoaded; private UnityWebRequest 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; Uri uri = new Uri(filename); 5__2 = UnityWebRequestMultimedia.GetAudioClip(uri.AbsoluteUri, (AudioType)20); <>1__state = -3; <>2__current = 5__2.SendWebRequest(); <>1__state = 1; return true; } case 1: <>1__state = -3; if ((int)5__2.result == 1) { AudioClip content = DownloadHandlerAudioClip.GetContent(5__2); onLoaded(content); Plugin.VerboseLog("[AudioPatch] Loaded custom clip: " + filename); } else { onLoaded(null); Plugin.Log.LogError((object)("[AudioPatch] Failed to load audio clip: " + filename + " - " + 5__2.error)); } <>m__Finally1(); 5__2 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (5__2 != null) { ((IDisposable)5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__9 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Action_AskBingBong instance; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((Object)(object)instance == (Object)null || !Plugin.ModEnabled) { StopCustomPlayback(instance, clearSubtitle: true); return false; } <>2__current = EnsureClipsLoaded(); <>1__state = 1; return true; case 1: { <>1__state = -1; if (!Plugin.ModEnabled) { StopCustomPlayback(instance, clearSubtitle: true); return false; } if (CustomClips.Count == 0) { Plugin.Log.LogWarning((object)"[AudioPatch] No custom clips found. Expected files like response_0.wav in plugin directory."); return false; } int nextClipIndex = _nextClipIndex; _nextClipIndex = (_nextClipIndex + 1) % CustomClips.Count; AudioClip val = CustomClips[nextClipIndex]; string text = ClipNames[nextClipIndex]; if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("[AudioPatch] Missing custom clip index " + nextClipIndex + ".")); return false; } AudioSource orCreatePlaybackSource = GetOrCreatePlaybackSource(instance); if ((Object)(object)orCreatePlaybackSource != (Object)null) { orCreatePlaybackSource.Stop(); orCreatePlaybackSource.clip = val; orCreatePlaybackSource.loop = false; orCreatePlaybackSource.pitch = 1f; orCreatePlaybackSource.Play(); Plugin.VerboseLog("[AudioPatch] Played custom BingBong clip: " + text); } else { Plugin.Log.LogWarning((object)"[AudioPatch] No safe playback AudioSource available."); } if ((Object)(object)instance.subtitles != (Object)null) { ((TMP_Text)instance.subtitles).text = Plugin.ReplacementDisplayName; <>2__current = (object)new WaitForSeconds(Mathf.Clamp(val.length, 0.5f, 4f)); <>1__state = 2; return true; } break; } case 2: <>1__state = -1; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string RuntimeSourceObjectName = "MikuBong_CustomAudio"; private static readonly string[] ExpectedFiles = new string[4] { "response_0.wav", "response_1.wav", "response_2.wav", "response_3.wav" }; private static readonly List CustomClips = new List(); private static readonly List ClipNames = new List(); private static bool _isLoading; private static bool _hasLoadAttempt; private static int _nextClipIndex; [HarmonyPrefix] public static bool Prefix(Action_AskBingBong __instance, int index, bool spamming, ref IEnumerator __result) { if ((Object)(object)__instance == (Object)null) { return true; } if (!Plugin.ModEnabled) { StopCustomPlayback(__instance, clearSubtitle: true); return true; } __result = PlayCustomRoutine(__instance, index); return false; } internal static void HandleModConfigStateChanged() { if (!Plugin.ModEnabled) { Action_AskBingBong[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { StopCustomPlayback(array[i], clearSubtitle: true); } } } [IteratorStateMachine(typeof(d__9))] private static IEnumerator PlayCustomRoutine(Action_AskBingBong instance, int index) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__9(0) { instance = instance }; } private static void StopCustomPlayback(Action_AskBingBong instance, bool clearSubtitle) { if ((Object)(object)instance == (Object)null) { return; } Transform val = ((Component)instance).transform.Find("MikuBong_CustomAudio"); if ((Object)(object)val != (Object)null) { AudioSource component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.Stop(); component.clip = null; } Object.Destroy((Object)(object)((Component)val).gameObject); } if (clearSubtitle && (Object)(object)instance.subtitles != (Object)null && string.Equals(((TMP_Text)instance.subtitles).text, Plugin.ReplacementDisplayName, StringComparison.Ordinal)) { ((TMP_Text)instance.subtitles).text = string.Empty; } } private static AudioSource GetOrCreatePlaybackSource(Action_AskBingBong instance) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null) { return null; } Transform val = ((Component)instance).transform.Find("MikuBong_CustomAudio"); AudioSource val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null); if ((Object)(object)val2 == (Object)null) { GameObject val3 = new GameObject("MikuBong_CustomAudio"); val3.transform.SetParent(((Component)instance).transform, false); val2 = val3.AddComponent(); } ConfigurePlaybackSource(val2, instance.source); return val2; } private static void ConfigurePlaybackSource(AudioSource playbackSource, AudioSource template) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052->IL0052: Incompatible stack types: O vs I4 //IL_004c->IL0052: Incompatible stack types: I4 vs O //IL_004c->IL0052: Incompatible stack types: O vs I4 if (!((Object)(object)playbackSource == (Object)null)) { playbackSource.playOnAwake = false; playbackSource.loop = false; playbackSource.pitch = 1f; playbackSource.spatialBlend = (((Object)(object)template != (Object)null) ? template.spatialBlend : 1f); object obj = playbackSource; int num; if ((Object)(object)template != (Object)null) { obj = template.rolloffMode; num = (int)obj; } else { num = 0; obj = num; num = (int)obj; } ((AudioSource)num).rolloffMode = (AudioRolloffMode)obj; playbackSource.minDistance = (((Object)(object)template != (Object)null) ? template.minDistance : 1f); playbackSource.maxDistance = (((Object)(object)template != (Object)null) ? template.maxDistance : 20f); playbackSource.spread = (((Object)(object)template != (Object)null) ? template.spread : 0f); playbackSource.volume = (((Object)(object)template != (Object)null) ? template.volume : 1f); playbackSource.dopplerLevel = (((Object)(object)template != (Object)null) ? template.dopplerLevel : 0f); playbackSource.priority = (((Object)(object)template != (Object)null) ? template.priority : 128); } } [IteratorStateMachine(typeof(d__13))] private static IEnumerator EnsureClipsLoaded() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0); } [IteratorStateMachine(typeof(d__14))] private static IEnumerator LoadClip(string filename, Action onLoaded) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__14(0) { filename = filename, onLoaded = onLoaded }; } } }