using 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(); 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(); } 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(); 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(); 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 _adultVariants = new List(); private readonly Dictionary _calfPrefabs = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly List _pendingGrowups = new List(); 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(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() == (Object)null) { prefab.AddComponent(); } if ((Object)(object)prefab2.GetComponent() == (Object)null) { prefab2.AddComponent(); } if ((Object)(object)prefab3 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[Lox More] Missing lox_ragdoll prefab."); } else if ((Object)(object)prefab3.GetComponent() == (Object)null) { prefab3.AddComponent(); } } 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 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 list = new List { "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(true); SkinnedMeshRenderer[] componentsInChildren2 = targetObject.GetComponentsInChildren(true); Dictionary dictionary = new Dictionary(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 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 BuildBoneMap(GameObject target) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); Transform[] componentsInChildren = target.GetComponentsInChildren(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 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 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(); 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(); 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(); if (!((Object)(object)component == (Object)null)) { string text = component.GetStoredAppearanceId(); if (string.IsNullOrEmpty(text)) { text = "vanilla"; } LoxRagdollAppearanceController loxRagdollAppearanceController = ((Component)ragdoll).GetComponent(); if ((Object)(object)loxRagdollAppearanceController == (Object)null) { loxRagdollAppearanceController = ((Component)ragdoll).gameObject.AddComponent(); } loxRagdollAppearanceController.SetAppearanceFromSource(text); } } }