Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of UnloxAppearance v1.0.0
BepInEx/plugins/Unlox Appearance/LoxMore.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using HarmonyLib; using Jotunn.Managers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("LoxMore")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("LoxMore")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8509a45a-86cf-4453-ac15-4ec66967a603")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace LoxMore; public sealed class LoxAppearanceController : MonoBehaviour { private const string AppearanceZdoKey = "Moddermother.LoxMore.Appearance"; private const float NetworkCheckInterval = 0.2f; private ZNetView _networkView; private string _appliedAppearanceId = string.Empty; private IEnumerator Start() { _networkView = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)_networkView == (Object)null) { yield break; } while (!_networkView.IsValid() || _networkView.GetZDO() == null) { yield return null; } ZDO zdo = _networkView.GetZDO(); string appearanceId = zdo.GetString("Moddermother.LoxMore.Appearance", string.Empty); if (string.IsNullOrEmpty(appearanceId) && _networkView.IsOwner()) { LoxMorePlugin plugin = LoxMorePlugin.Instance; if ((Object)(object)plugin == (Object)null) { yield break; } if (!plugin.TryConsumePendingGrowup(((Component)this).transform.position, out appearanceId)) { appearanceId = plugin.ChooseInitialAdultAppearance(); } zdo.Set("Moddermother.LoxMore.Appearance", appearanceId); } while (string.IsNullOrEmpty(appearanceId)) { yield return (object)new WaitForSeconds(0.2f); if ((Object)(object)_networkView == (Object)null || !_networkView.IsValid()) { yield break; } zdo = _networkView.GetZDO(); if (zdo != null) { appearanceId = zdo.GetString("Moddermother.LoxMore.Appearance", string.Empty); } } ApplyAppearance(appearanceId); } public string GetStoredAppearanceId() { if ((Object)(object)_networkView == (Object)null) { _networkView = ((Component)this).GetComponent<ZNetView>(); } if ((Object)(object)_networkView == (Object)null || !_networkView.IsValid() || _networkView.GetZDO() == null) { return string.Empty; } return _networkView.GetZDO().GetString("Moddermother.LoxMore.Appearance", string.Empty); } private void ApplyAppearance(string appearanceId) { if (!string.IsNullOrEmpty(appearanceId) && !string.Equals(_appliedAppearanceId, appearanceId, StringComparison.OrdinalIgnoreCase)) { LoxMorePlugin instance = LoxMorePlugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.ApplyAdultAppearance(((Component)this).gameObject, appearanceId)) { _appliedAppearanceId = appearanceId; } } } } public sealed class LoxCalfAppearanceController : MonoBehaviour { private const string FutureAdultZdoKey = "Moddermother.LoxMore.FutureAppearance"; private const string CalfColorZdoKey = "Moddermother.LoxMore.CalfColor"; private const float AssignmentWaitSeconds = 0.8f; private const float NetworkCheckInterval = 0.2f; private const float GrowCheckInterval = 0.5f; private const float RegisterGrowupWhenSecondsLeft = 3f; private ZNetView _networkView; private string _appliedCalfColor = string.Empty; private IEnumerator Start() { _networkView = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)_networkView == (Object)null) { yield break; } while (!_networkView.IsValid() || _networkView.GetZDO() == null) { yield return null; } ZDO zdo = _networkView.GetZDO(); string futureAppearance = zdo.GetString("Moddermother.LoxMore.FutureAppearance", string.Empty); string calfColor = zdo.GetString("Moddermother.LoxMore.CalfColor", string.Empty); if (string.IsNullOrEmpty(futureAppearance) && _networkView.IsOwner()) { yield return (object)new WaitForSeconds(0.8f); LoxMorePlugin plugin = LoxMorePlugin.Instance; if ((Object)(object)plugin == (Object)null) { yield break; } futureAppearance = plugin.ChooseFutureAdultAppearanceForCalf(this); calfColor = plugin.GetCalfColorIdForAdult(futureAppearance); zdo.Set("Moddermother.LoxMore.FutureAppearance", futureAppearance); zdo.Set("Moddermother.LoxMore.CalfColor", calfColor); } while (string.IsNullOrEmpty(futureAppearance) || string.IsNullOrEmpty(calfColor)) { yield return (object)new WaitForSeconds(0.2f); if ((Object)(object)_networkView == (Object)null || !_networkView.IsValid()) { yield break; } zdo = _networkView.GetZDO(); if (zdo != null) { futureAppearance = zdo.GetString("Moddermother.LoxMore.FutureAppearance", string.Empty); calfColor = zdo.GetString("Moddermother.LoxMore.CalfColor", string.Empty); } } ApplyCalfColor(calfColor); ((MonoBehaviour)this).StartCoroutine(WatchForGrowup(futureAppearance)); } private void ApplyCalfColor(string calfColor) { if (!string.IsNullOrEmpty(calfColor) && !string.Equals(_appliedCalfColor, calfColor, StringComparison.OrdinalIgnoreCase)) { LoxMorePlugin instance = LoxMorePlugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.ApplyCalfAppearance(((Component)this).gameObject, calfColor)) { _appliedCalfColor = calfColor; } } } private IEnumerator WatchForGrowup(string futureAppearance) { Growup growup = ((Component)this).GetComponent<Growup>(); if ((Object)(object)growup == (Object)null) { yield break; } while (true) { yield return (object)new WaitForSeconds(0.5f); if ((Object)(object)_networkView == (Object)null || !_networkView.IsValid() || !_networkView.IsOwner()) { continue; } ZDO zdo = _networkView.GetZDO(); if (zdo == null || (Object)(object)ZNet.instance == (Object)null) { continue; } long spawnTicks = zdo.GetLong(ZDOVars.s_spawnTime, 0L); if (spawnTicks <= 0) { continue; } long nowTicks = ZNet.instance.GetTime().Ticks; double ageSeconds = (double)(nowTicks - spawnTicks) / 10000000.0; double secondsLeft = (double)growup.m_growTime - ageSeconds; if (secondsLeft <= 3.0) { LoxMorePlugin plugin = LoxMorePlugin.Instance; if ((Object)(object)plugin != (Object)null) { plugin.RegisterPendingGrowup(((Object)this).GetInstanceID(), ((Component)this).transform.position, futureAppearance); } } } } } [BepInPlugin("Moddermother.LoxMore", "Lox More", "0.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class LoxMorePlugin : BaseUnityPlugin { public enum CalfColor { Vanilla, Black, BlackWhite, White } private sealed class LoxVariantDefinition { public string AppearanceId { get; } public GameObject Prefab { get; } public bool IsHorned { get; } public CalfColor CalfColor { get; } public LoxVariantDefinition(string appearanceId, GameObject prefab, bool isHorned, CalfColor calfColor) { AppearanceId = appearanceId; Prefab = prefab; IsHorned = isHorned; CalfColor = calfColor; } } private sealed class PendingGrowupRecord { public int CalfInstanceId; public Vector3 Position; public string AppearanceId; public float Timestamp; } public const string ModGuid = "Moddermother.LoxMore"; public const string ModName = "Lox More"; public const string ModVersion = "0.3.0"; public const string VanillaAppearanceId = "vanilla"; private const string BundleFileName = "loxmore"; private const string AdultPrefabName = "Lox"; private const string CalfPrefabName = "Lox_Calf"; private const string AdultRagdollPrefabName = "lox_ragdoll"; private const float PendingGrowupMaxAgeSeconds = 8f; private const float PendingGrowupMaxDistance = 3f; private readonly List<LoxVariantDefinition> _adultVariants = new List<LoxVariantDefinition>(); private readonly Dictionary<string, GameObject> _calfPrefabs = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase); private readonly List<PendingGrowupRecord> _pendingGrowups = new List<PendingGrowupRecord>(); private AssetBundle _assetBundle; private Harmony _harmony; private float _baseAdultTamingTime = -1f; public static LoxMorePlugin Instance { get; private set; } private void Awake() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown Instance = this; _harmony = new Harmony("Moddermother.LoxMore"); _harmony.PatchAll(); LoadAssetBundle(); LoadAdultVariants(); LoadCalfVariants(); PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Lox More] Loaded " + _adultVariants.Count + " custom adult variants.")); } private void LoadAdultVariants() { _adultVariants.Clear(); AddAdultVariant("lox2", "lox2.prefab", isHorned: true, CalfColor.Vanilla); AddAdultVariant("lox3", "lox3.prefab", isHorned: true, CalfColor.Vanilla); AddAdultVariant("loxblack", "loxblack.prefab", isHorned: true, CalfColor.Black); AddAdultVariant("loxblack2", "loxblack2.prefab", isHorned: false, CalfColor.Black); AddAdultVariant("loxblack3", "loxblack3.prefab", isHorned: true, CalfColor.Black); AddAdultVariant("loxblackwhite", "loxblackwhite.prefab", isHorned: true, CalfColor.BlackWhite); AddAdultVariant("loxblackwhite2", "loxblackwhite2.prefab", isHorned: true, CalfColor.BlackWhite); AddAdultVariant("loxblackwhite3", "loxblackwhite3.prefab", isHorned: false, CalfColor.BlackWhite); AddAdultVariant("loxwhite", "loxwhite.prefab", isHorned: true, CalfColor.White); AddAdultVariant("loxwhite2", "loxwhite2.prefab", isHorned: false, CalfColor.White); AddAdultVariant("loxwhite3", "loxwhite3.prefab", isHorned: true, CalfColor.White); } private void LoadCalfVariants() { _calfPrefabs.Clear(); AddCalfVariant(CalfColor.Black, "Lox_CalfBlack.prefab"); AddCalfVariant(CalfColor.BlackWhite, "Lox_CalfBlackWhite.prefab"); AddCalfVariant(CalfColor.White, "Lox_CalfWhite.prefab"); } private void AddAdultVariant(string appearanceId, string prefabFileName, bool isHorned, CalfColor calfColor) { GameObject val = LoadPrefabFromBundle(prefabFileName); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Failed to load adult variant: " + prefabFileName)); } else { _adultVariants.Add(new LoxVariantDefinition(appearanceId, val, isHorned, calfColor)); } } private void AddCalfVariant(CalfColor calfColor, string prefabFileName) { GameObject val = LoadPrefabFromBundle(prefabFileName); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Failed to load calf variant: " + prefabFileName)); } else { _calfPrefabs[calfColor.ToString()] = val; } } private void LoadAssetBundle() { string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); if (string.IsNullOrEmpty(directoryName)) { ((BaseUnityPlugin)this).Logger.LogError((object)"[Lox More] DLL folder not found."); return; } string text = Path.Combine(directoryName, "loxmore"); if (!File.Exists(text)) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Missing AssetBundle: " + text)); return; } _assetBundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_assetBundle == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[Lox More] Failed to load AssetBundle."); } } private GameObject LoadPrefabFromBundle(string fileName) { if ((Object)(object)_assetBundle == (Object)null) { return null; } string text = FindAssetPath(fileName); if (string.IsNullOrEmpty(text)) { return null; } return _assetBundle.LoadAsset<GameObject>(text); } private string FindAssetPath(string fileName) { if ((Object)(object)_assetBundle == (Object)null) { return null; } string[] allAssetNames = _assetBundle.GetAllAssetNames(); foreach (string text in allAssetNames) { if (text.EndsWith("/" + fileName, StringComparison.OrdinalIgnoreCase) || string.Equals(text, fileName, StringComparison.OrdinalIgnoreCase)) { return text; } } return null; } private void OnVanillaPrefabsAvailable() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; GameObject prefab = PrefabManager.Instance.GetPrefab("Lox"); GameObject prefab2 = PrefabManager.Instance.GetPrefab("Lox_Calf"); GameObject prefab3 = PrefabManager.Instance.GetPrefab("lox_ragdoll"); if ((Object)(object)prefab == (Object)null || (Object)(object)prefab2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[Lox More] Missing Lox or Lox_Calf prefab."); return; } CacheBaseAdultTamingTime(prefab); EnableLoxFollowCommands(prefab); if ((Object)(object)prefab.GetComponent<LoxAppearanceController>() == (Object)null) { prefab.AddComponent<LoxAppearanceController>(); } if ((Object)(object)prefab2.GetComponent<LoxCalfAppearanceController>() == (Object)null) { prefab2.AddComponent<LoxCalfAppearanceController>(); } if ((Object)(object)prefab3 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[Lox More] Missing lox_ragdoll prefab."); } else if ((Object)(object)prefab3.GetComponent<LoxRagdollAppearanceController>() == (Object)null) { prefab3.AddComponent<LoxRagdollAppearanceController>(); } } public string ChooseInitialAdultAppearance() { return ChooseRandomAnyAppearance(); } public string ChooseFutureAdultAppearanceForCalf(LoxCalfAppearanceController self) { return (Random.value < 0.5f) ? ChooseRandomHornedAppearance() : ChooseRandomNonHornedAppearance(); } private string ChooseRandomAnyAppearance() { int num = _adultVariants.Count + 1; int num2 = Random.Range(0, num); if (num2 == 0) { return "vanilla"; } return _adultVariants[num2 - 1].AppearanceId; } private string ChooseRandomHornedAppearance() { List<LoxVariantDefinition> list = _adultVariants.FindAll((LoxVariantDefinition variant) => variant.IsHorned); if (list.Count == 0) { return "vanilla"; } return list[Random.Range(0, list.Count)].AppearanceId; } private string ChooseRandomNonHornedAppearance() { List<string> list = new List<string> { "vanilla" }; foreach (LoxVariantDefinition adultVariant in _adultVariants) { if (!adultVariant.IsHorned) { list.Add(adultVariant.AppearanceId); } } return list[Random.Range(0, list.Count)]; } public bool ApplyAdultAppearance(GameObject loxInstance, string appearanceId) { if ((Object)(object)loxInstance == (Object)null) { return false; } if (string.IsNullOrEmpty(appearanceId) || string.Equals(appearanceId, "vanilla", StringComparison.OrdinalIgnoreCase)) { ConfigureTamingTime(loxInstance, isHorned: false); return true; } LoxVariantDefinition loxVariantDefinition = FindAdultVariant(appearanceId); if (loxVariantDefinition == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Unknown adult appearance: " + appearanceId)); return false; } if (!ReplaceSkinnedRenderers(loxInstance, loxVariantDefinition.Prefab)) { return false; } ConfigureTamingTime(loxInstance, loxVariantDefinition.IsHorned); return true; } private void CacheBaseAdultTamingTime(GameObject adultPrefab) { Component val = FindComponentByTypeName(adultPrefab, "Tameable"); if ((Object)(object)val == (Object)null) { return; } FieldInfo field = ((object)val).GetType().GetField("m_tamingTime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null)) { object value = field.GetValue(val); if (value is float) { _baseAdultTamingTime = (float)value; } } } private void ConfigureTamingTime(GameObject lox, bool isHorned) { Component val = FindComponentByTypeName(lox, "Tameable"); if ((Object)(object)val == (Object)null) { return; } FieldInfo field = ((object)val).GetType().GetField("m_tamingTime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return; } float num = _baseAdultTamingTime; if (num <= 0f) { object value = field.GetValue(val); if (!(value is float)) { return; } num = (float)value; } field.SetValue(val, isHorned ? (num * 2f) : num); } public bool ApplyAdultRagdollAppearance(GameObject ragdollInstance, string appearanceId) { if ((Object)(object)ragdollInstance == (Object)null) { return false; } if (string.IsNullOrEmpty(appearanceId) || string.Equals(appearanceId, "vanilla", StringComparison.OrdinalIgnoreCase)) { return true; } LoxVariantDefinition loxVariantDefinition = FindAdultVariant(appearanceId); if (loxVariantDefinition == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Unknown ragdoll appearance: " + appearanceId)); return false; } return ReplaceSkinnedRenderers(ragdollInstance, loxVariantDefinition.Prefab); } public string GetCalfColorIdForAdult(string adultAppearanceId) { if (string.IsNullOrEmpty(adultAppearanceId) || string.Equals(adultAppearanceId, "vanilla", StringComparison.OrdinalIgnoreCase)) { return CalfColor.Vanilla.ToString(); } LoxVariantDefinition loxVariantDefinition = FindAdultVariant(adultAppearanceId); return (loxVariantDefinition == null) ? CalfColor.Vanilla.ToString() : loxVariantDefinition.CalfColor.ToString(); } public bool ApplyCalfAppearance(GameObject calfInstance, string calfColorId) { if ((Object)(object)calfInstance == (Object)null) { return false; } if (string.IsNullOrEmpty(calfColorId) || string.Equals(calfColorId, CalfColor.Vanilla.ToString(), StringComparison.OrdinalIgnoreCase)) { return true; } if (!_calfPrefabs.TryGetValue(calfColorId, out var value)) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Unknown calf appearance: " + calfColorId)); return false; } return ReplaceSkinnedRenderers(calfInstance, value); } public void RegisterPendingGrowup(int calfInstanceId, Vector3 position, string futureAdultAppearanceId) { //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_0037: 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) CleanupPendingGrowups(); PendingGrowupRecord pendingGrowupRecord = _pendingGrowups.Find((PendingGrowupRecord record) => record.CalfInstanceId == calfInstanceId); if (pendingGrowupRecord != null) { pendingGrowupRecord.Position = position; pendingGrowupRecord.AppearanceId = futureAdultAppearanceId; pendingGrowupRecord.Timestamp = Time.realtimeSinceStartup; } else { _pendingGrowups.Add(new PendingGrowupRecord { CalfInstanceId = calfInstanceId, Position = position, AppearanceId = futureAdultAppearanceId, Timestamp = Time.realtimeSinceStartup }); } } public bool TryConsumePendingGrowup(Vector3 adultPosition, out string appearanceId) { //IL_002f: 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) CleanupPendingGrowups(); appearanceId = string.Empty; PendingGrowupRecord pendingGrowupRecord = null; float num = float.MaxValue; foreach (PendingGrowupRecord pendingGrowup in _pendingGrowups) { float num2 = Vector3.Distance(adultPosition, pendingGrowup.Position); if (!(num2 > 3f) && num2 < num) { pendingGrowupRecord = pendingGrowup; num = num2; } } if (pendingGrowupRecord == null) { return false; } appearanceId = pendingGrowupRecord.AppearanceId; _pendingGrowups.Remove(pendingGrowupRecord); return true; } private void CleanupPendingGrowups() { float now = Time.realtimeSinceStartup; _pendingGrowups.RemoveAll((PendingGrowupRecord record) => now - record.Timestamp > 8f); } private static string GetRendererRole(string rendererName) { if (string.IsNullOrWhiteSpace(rendererName)) { return string.Empty; } string text = rendererName.Trim(); if (text.StartsWith("Body", StringComparison.OrdinalIgnoreCase)) { return "Body"; } if (text.StartsWith("Furr1", StringComparison.OrdinalIgnoreCase)) { return "Furr1"; } return string.Empty; } private bool ReplaceSkinnedRenderers(GameObject targetObject, GameObject sourcePrefab) { //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_026c: 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_0293: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)targetObject == (Object)null || (Object)(object)sourcePrefab == (Object)null) { return false; } SkinnedMeshRenderer[] componentsInChildren = sourcePrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer[] componentsInChildren2 = targetObject.GetComponentsInChildren<SkinnedMeshRenderer>(true); Dictionary<string, SkinnedMeshRenderer> dictionary = new Dictionary<string, SkinnedMeshRenderer>(StringComparer.OrdinalIgnoreCase); SkinnedMeshRenderer[] array = componentsInChildren2; foreach (SkinnedMeshRenderer val in array) { if (!((Object)(object)val == (Object)null)) { string rendererRole = GetRendererRole(((Object)val).name); if (!string.IsNullOrEmpty(rendererRole) && !dictionary.ContainsKey(rendererRole)) { dictionary.Add(rendererRole, val); } } } Dictionary<string, Transform> targetBones = BuildBoneMap(targetObject); int num = 0; SkinnedMeshRenderer[] array2 = componentsInChildren; foreach (SkinnedMeshRenderer val2 in array2) { if ((Object)(object)val2 == (Object)null) { continue; } string rendererRole2 = GetRendererRole(((Object)val2).name); if (string.IsNullOrEmpty(rendererRole2)) { continue; } if (!dictionary.TryGetValue(rendererRole2, out var value)) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Missing target renderer: " + rendererRole2)); continue; } if ((Object)(object)val2.sharedMesh == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Missing source mesh in " + ((Object)sourcePrefab).name + ": " + ((Object)val2).name)); continue; } Transform[] array3 = MapBones(val2, targetBones); if (array3 == null) { continue; } Transform val3 = FindMappedRootBone(val2, targetBones); if ((Object)(object)val2.rootBone != (Object)null && (Object)(object)val3 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Failed to map root bone: " + ((Object)val2.rootBone).name)); continue; } bool enabled = ((Renderer)value).enabled; value.sharedMesh = val2.sharedMesh; ((Renderer)value).sharedMaterials = CopyMaterialArray(((Renderer)val2).sharedMaterials); value.bones = array3; if ((Object)(object)val3 != (Object)null) { value.rootBone = val3; } ((Component)value).transform.localPosition = ((Component)val2).transform.localPosition; ((Component)value).transform.localRotation = ((Component)val2).transform.localRotation; ((Component)value).transform.localScale = ((Component)val2).transform.localScale; ((Renderer)value).localBounds = ((Renderer)val2).localBounds; value.updateWhenOffscreen = true; ((Renderer)value).shadowCastingMode = ((Renderer)val2).shadowCastingMode; ((Renderer)value).receiveShadows = ((Renderer)val2).receiveShadows; ((Renderer)value).enabled = enabled; num++; } if (num == 0) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] No renderers replaced for: " + ((Object)sourcePrefab).name)); } return num > 0; } private static Material[] CopyMaterialArray(Material[] sourceMaterials) { if (sourceMaterials == null) { return (Material[])(object)new Material[0]; } Material[] array = (Material[])(object)new Material[sourceMaterials.Length]; Array.Copy(sourceMaterials, array, sourceMaterials.Length); return array; } private Dictionary<string, Transform> BuildBoneMap(GameObject target) { Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.Ordinal); Transform[] componentsInChildren = target.GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string text = NormalizeBoneName(((Object)val).name); if (!string.IsNullOrEmpty(text) && !dictionary.ContainsKey(text)) { dictionary.Add(text, val); } } } return dictionary; } private static string NormalizeBoneName(string boneName) { if (string.IsNullOrWhiteSpace(boneName)) { return string.Empty; } string text = boneName.Trim(); if (text.EndsWith("_l", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - 2) + ".l"; } else if (text.EndsWith("_r", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - 2) + ".r"; } if (text.Length > 4) { int num = text.Length - 4; if (text[num] == '_' && char.IsDigit(text[num + 1]) && char.IsDigit(text[num + 2]) && char.IsDigit(text[num + 3])) { text = text.Substring(0, num) + "." + text.Substring(num + 1); } } return text.ToLowerInvariant(); } private Transform[] MapBones(SkinnedMeshRenderer source, Dictionary<string, Transform> targetBones) { Transform[] array = (Transform[])(object)new Transform[source.bones.Length]; for (int i = 0; i < source.bones.Length; i++) { Transform val = source.bones[i]; if ((Object)(object)val == (Object)null) { return null; } string key = NormalizeBoneName(((Object)val).name); if (!targetBones.TryGetValue(key, out var value)) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Lox More] Missing target bone: " + ((Object)val).name)); return null; } array[i] = value; } return array; } private Transform FindMappedRootBone(SkinnedMeshRenderer source, Dictionary<string, Transform> targetBones) { if ((Object)(object)source.rootBone == (Object)null) { return null; } if (targetBones.TryGetValue(NormalizeBoneName(((Object)source.rootBone).name), out var value)) { return value; } return null; } private LoxVariantDefinition FindAdultVariant(string appearanceId) { foreach (LoxVariantDefinition adultVariant in _adultVariants) { if (string.Equals(adultVariant.AppearanceId, appearanceId, StringComparison.OrdinalIgnoreCase)) { return adultVariant; } } return null; } private static Component FindComponentByTypeName(GameObject gameObject, string typeName) { Component[] components = gameObject.GetComponents<Component>(); foreach (Component val in components) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == typeName) { return val; } } return null; } private void EnableLoxFollowCommands(GameObject loxPrefab) { Component val = FindComponentByTypeName(loxPrefab, "Tameable"); if (!((Object)(object)val == (Object)null)) { FieldInfo field = ((object)val).GetType().GetField("m_commandable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(val, true); } } } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; if (_harmony != null) { _harmony.UnpatchSelf(); _harmony = null; } if ((Object)(object)_assetBundle != (Object)null) { _assetBundle.Unload(false); _assetBundle = null; } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } public sealed class LoxRagdollAppearanceController : MonoBehaviour { private const string AppearanceZdoKey = "Moddermother.LoxMore.Appearance"; private const float NetworkCheckInterval = 0.1f; private const int MaxNetworkChecks = 50; private ZNetView _networkView; private string _sourceAppearanceId = string.Empty; private string _appliedAppearanceId = string.Empty; public void SetAppearanceFromSource(string appearanceId) { _sourceAppearanceId = appearanceId ?? string.Empty; } private IEnumerator Start() { _networkView = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)_networkView == (Object)null) { yield break; } while (!_networkView.IsValid() || _networkView.GetZDO() == null) { yield return null; } ZDO zdo = _networkView.GetZDO(); if (_networkView.IsOwner() && !string.IsNullOrEmpty(_sourceAppearanceId)) { zdo.Set("Moddermother.LoxMore.Appearance", _sourceAppearanceId); } string appearanceId = zdo.GetString("Moddermother.LoxMore.Appearance", string.Empty); int checks = 0; while (string.IsNullOrEmpty(appearanceId) && checks < 50) { checks++; if (!string.IsNullOrEmpty(_sourceAppearanceId)) { appearanceId = _sourceAppearanceId; if (_networkView.IsOwner()) { zdo.Set("Moddermother.LoxMore.Appearance", appearanceId); } break; } yield return (object)new WaitForSeconds(0.1f); if ((Object)(object)_networkView == (Object)null || !_networkView.IsValid()) { yield break; } zdo = _networkView.GetZDO(); if (zdo != null) { appearanceId = zdo.GetString("Moddermother.LoxMore.Appearance", string.Empty); } } if (string.IsNullOrEmpty(appearanceId)) { appearanceId = "vanilla"; } ApplyAppearance(appearanceId); } private void ApplyAppearance(string appearanceId) { if (!string.Equals(_appliedAppearanceId, appearanceId, StringComparison.OrdinalIgnoreCase)) { LoxMorePlugin instance = LoxMorePlugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.ApplyAdultRagdollAppearance(((Component)this).gameObject, appearanceId)) { _appliedAppearanceId = appearanceId; } } } } [HarmonyPatch(typeof(Humanoid), "OnRagdollCreated")] internal static class LoxRagdollCreatedPatch { private static void Postfix(Humanoid __instance, Ragdoll ragdoll) { if ((Object)(object)__instance == (Object)null || (Object)(object)ragdoll == (Object)null) { return; } LoxAppearanceController component = ((Component)__instance).GetComponent<LoxAppearanceController>(); if (!((Object)(object)component == (Object)null)) { string text = component.GetStoredAppearanceId(); if (string.IsNullOrEmpty(text)) { text = "vanilla"; } LoxRagdollAppearanceController loxRagdollAppearanceController = ((Component)ragdoll).GetComponent<LoxRagdollAppearanceController>(); if ((Object)(object)loxRagdollAppearanceController == (Object)null) { loxRagdollAppearanceController = ((Component)ragdoll).gameObject.AddComponent<LoxRagdollAppearanceController>(); } loxRagdollAppearanceController.SetAppearanceFromSource(text); } } }