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 VRMCompanions v0.1.0
BepInEx/plugins/VRMCompanions/VRMCompanions.dll
Decompiled 10 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 BepInEx.Logging; using HarmonyLib; using UnityEngine; using ValheimVRM; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("VRMCompanions")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("VRMCompanions")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8aaf6e91-f870-4b1f-a224-b3b681dbbf1f")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("com.vrm.companions", "VRM Companions", "1.0.0")] public class VRMCompanionsPlugin : BaseUnityPlugin { internal static ManualLogSource Log; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Harmony.CreateAndPatchAll(typeof(CompanionPatch), (string)null); Log.LogInfo((object)"VRM Companions loaded"); } } [HarmonyPatch(typeof(Humanoid), "Start")] public class CompanionPatch { private static void Postfix(Humanoid __instance) { if (!((Object)(object)__instance == (Object)null) && ((Object)__instance).name.Contains("HC_Companion")) { LogSafe("✔ Companion detected: " + ((Object)__instance).name); ((MonoBehaviour)__instance).StartCoroutine(ReplaceVRM(__instance)); } } private static IEnumerator ReplaceVRM(Humanoid humanoid) { yield return null; VisEquipment vis = ((Component)humanoid).GetComponent<VisEquipment>(); if ((Object)(object)vis == (Object)null) { LogSafe("❌ VisEquipment missing"); yield break; } if ((Object)(object)vis.m_bodyModel != (Object)null) { ((Renderer)vis.m_bodyModel).enabled = false; LogSafe("✔ Vanilla body hidden"); } string path = Path.Combine(Paths.GameRootPath, "ValheimVRM", "Companion.vrm"); if (!File.Exists(path)) { LogSafe("❌ VRM not found: " + path); yield break; } Dictionary<string, string> cfg = LoadSettingsFile(path); byte[] data = File.ReadAllBytes(path); bool done = false; yield return VRM.ImportVisualAsync(data, path, 1f, (Action<GameObject>)delegate(GameObject loaded) { //IL_00a3: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)loaded == (Object)null) { LogSafe("❌ VRM load failed"); done = true; } else { float result = 1f; float result2 = 1f; float result3 = 1f; if (cfg.TryGetValue("ModelScale", out var value)) { float.TryParse(value, out result); } if (cfg.TryGetValue("SpringBoneStiffness", out var value2)) { float.TryParse(value2, out result2); } if (cfg.TryGetValue("SpringBoneGravityPower", out var value3)) { float.TryParse(value3, out result3); } loaded.transform.localScale = Vector3.one * result; Animator componentInChildren = ((Component)humanoid).GetComponentInChildren<Animator>(); VrmSettingsContainer settings = Settings.GetSettings(((Object)humanoid).name); loaded.transform.SetParent(((Component)componentInChildren).transform.parent, false); loaded.transform.localPosition = Vector3.zero; loaded.transform.localRotation = Quaternion.identity; LogSafe("✔ VRM attached to companion"); VRMAnimationSync val = loaded.GetComponent<VRMAnimationSync>(); if ((Object)(object)val == (Object)null) { val = loaded.AddComponent<VRMAnimationSync>(); } val.Setup(componentInChildren, settings, false); componentInChildren.cullingMode = (AnimatorCullingMode)0; componentInChildren.updateMode = (AnimatorUpdateMode)0; ForceSpringBoneUpdate(loaded, result2, result3); ApplyArmorHide(humanoid); MonoBehaviour[] componentsInChildren = loaded.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val2 in componentsInChildren) { if (((object)val2).GetType().Name.Contains("VRMSpringBone")) { LogSafe("SpringBone found: " + ((Object)val2).name); } } done = true; } }); while (!done) { yield return null; } } private static void ApplyArmorHide(Humanoid humanoid) { VisEquipment component = ((Component)humanoid).GetComponent<VisEquipment>(); if ((Object)(object)component == (Object)null) { return; } if ((Object)(object)component.m_helmet != (Object)null) { ((Component)component.m_helmet).gameObject.SetActive(false); } component.SetHairItem(""); component.SetBeardItem(""); SkinnedMeshRenderer[] componentsInChildren = ((Component)humanoid).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { string text = ((Object)((Component)val).gameObject).name.ToLower(); if (text.Contains("helmet") || text.Contains("helm") || text.Contains("chest") || text.Contains("armor")) { ((Renderer)val).enabled = false; } } } private static void ForceSpringBoneUpdate(GameObject vrmRoot, float springStiffness, float springGravity) { MonoBehaviour[] componentsInChildren = vrmRoot.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { Type type = ((object)val).GetType(); if (type.Name.Contains("VRMSpringBone")) { FieldInfo field = type.GetField("m_stiffnessForce"); FieldInfo field2 = type.GetField("m_gravityPower"); if (field != null) { float num = (float)field.GetValue(val); field.SetValue(val, num * Mathf.Clamp(springStiffness, 0.1f, 5f)); } if (field2 != null) { float num2 = (float)field2.GetValue(val); field2.SetValue(val, num2 * Mathf.Clamp(springGravity, 0.1f, 5f)); } } } } private static Dictionary<string, string> LoadSettingsFile(string vrmPath) { string text = Path.Combine(Path.GetDirectoryName(vrmPath), "settings_" + Path.GetFileNameWithoutExtension(vrmPath) + ".txt"); Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!File.Exists(text)) { return dictionary; } string[] array = File.ReadAllLines(text); foreach (string text2 in array) { if (!string.IsNullOrWhiteSpace(text2) && !text2.StartsWith("//") && text2.Contains("=")) { string[] array2 = text2.Split(new char[1] { '=' }); if (array2.Length == 2) { dictionary[array2[0].Trim()] = array2[1].Trim(); } } } LogSafe("✔ Loaded VRM settings: " + text); return dictionary; } private static void LogSafe(string msg) { if (VRMCompanionsPlugin.Log != null) { VRMCompanionsPlugin.Log.LogInfo((object)msg); } else { Debug.Log((object)msg); } } }