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 CampfireCompanion v0.1.0
CampfireCompanion.dll
Decompiled 6 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("garcipat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A creature of your choice keeps you company at the main menu campfire.")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+53c7c94aea5f3bfc19a86ac81b3657b768fb5468")] [assembly: AssemblyProduct("Campfire Companion")] [assembly: AssemblyTitle("CampfireCompanion")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimCampfireCompanion { public enum Companion { None, Random, Deer, Greydwarf, Troll, Bear, Draugr, Skeleton, Ghost, Wraith, Blob, Oozer, Kvastur, Surtling, Wolf, Fenring, Ulv, Drake, Cultist, Lox, Unbjorn, Fuling, FulingBerserker, FulingShaman, SeekerSoldier, Dvergr, Asksvin, CharredMage, Morgen, FallenValkyrie, Moose, Haldor, Hildir, BogWitch } internal sealed class CompanionSetup { internal readonly string Prefab; internal readonly float Scale; internal readonly float Gap; internal readonly float Turn; internal readonly int Stars; internal CompanionSetup(string prefab, float scale, float gap, float turn = 0f, int stars = 0) { Prefab = prefab; Scale = scale; Gap = gap; Turn = turn; Stars = stars; } } internal static class Companions { private static readonly Random Rng = new Random(); private static readonly Dictionary<Companion, CompanionSetup> Setups = new Dictionary<Companion, CompanionSetup> { { Companion.Deer, new CompanionSetup("Deer", 1f, 3.14f, 0f, 2) }, { Companion.Greydwarf, new CompanionSetup("Greydwarf", 1f, 2.89f) }, { Companion.Troll, new CompanionSetup("Troll", 0.72f, 1.14f) }, { Companion.Bear, new CompanionSetup("Bjorn", 1.05f, 2.64f) }, { Companion.Draugr, new CompanionSetup("Draugr", 1f, 3.64f) }, { Companion.Skeleton, new CompanionSetup("Skeleton", 1.05f, 3.14f) }, { Companion.Ghost, new CompanionSetup("Ghost", 1f, 3.19f) }, { Companion.Wraith, new CompanionSetup("Wraith", 1f, 1.89f) }, { Companion.Blob, new CompanionSetup("Blob", 1f, 3.19f) }, { Companion.Oozer, new CompanionSetup("BlobElite", 1f, 2.94f) }, { Companion.Kvastur, new CompanionSetup("BogWitchKvastur", 1f, 3.19f) }, { Companion.Surtling, new CompanionSetup("Surtling", 1f, 3.19f) }, { Companion.Wolf, new CompanionSetup("Wolf", 1f, 2.64f) }, { Companion.Fenring, new CompanionSetup("Fenring", 0.9f, 1.64f) }, { Companion.Ulv, new CompanionSetup("Ulv", 1.1f, 2.89f) }, { Companion.Drake, new CompanionSetup("Hatchling", 1f, 2.44f) }, { Companion.Cultist, new CompanionSetup("Fenring_Cultist", 0.95f, 2.19f) }, { Companion.Lox, new CompanionSetup("Lox", 0.7f, 3.14f) }, { Companion.Unbjorn, new CompanionSetup("Unbjorn", 0.9f, 2.94f) }, { Companion.Fuling, new CompanionSetup("Goblin", 1f, 3.39f) }, { Companion.FulingBerserker, new CompanionSetup("GoblinBrute", 1f, 1.39f) }, { Companion.FulingShaman, new CompanionSetup("GoblinShaman", 1f, 2.89f) }, { Companion.SeekerSoldier, new CompanionSetup("SeekerBrute", 0.9f, 2.89f) }, { Companion.Dvergr, new CompanionSetup("Dverger", 1f, 2.89f) }, { Companion.Asksvin, new CompanionSetup("Asksvin", 1f, 3.14f) }, { Companion.CharredMage, new CompanionSetup("Charred_Mage", 1f, 2.94f) }, { Companion.Morgen, new CompanionSetup("Morgen", 0.72f, 0.89f) }, { Companion.FallenValkyrie, new CompanionSetup("FallenValkyrie", 0.64f, -2.11f) }, { Companion.Moose, new CompanionSetup("Moose", 0.9f, 2.69f) }, { Companion.Haldor, new CompanionSetup("Haldor", 1f, 3.64f, 180f) }, { Companion.Hildir, new CompanionSetup("Hildir", 1f, 3.14f) }, { Companion.BogWitch, new CompanionSetup("BogWitch", 0.95f, 1.94f) } }; internal static CompanionSetup Get(Companion companion) { if (companion == Companion.Random) { Companion[] array = (Companion[])Enum.GetValues(typeof(Companion)); companion = array[Rng.Next(2, array.Length)]; } if (!Setups.TryGetValue(companion, out var value)) { return null; } return value; } } internal static class CompanionSpawner { private const float DepthOffset = 0.91f; private const float FireLeft = 2.12f; private const float FireTowardCamera = 0.15f; private const float CharacterCameraPullBack = 2f; private static GameObject _current; private static FejdStartup _pulledBackMenu; private static bool _pending; internal static void OnMenuStart(FejdStartup menu) { _pending = true; } internal static void Tick() { if (_pending) { _pending = false; Refresh(); } } internal static void Refresh() { try { if ((Object)(object)FejdStartup.instance != (Object)null) { Show(FejdStartup.instance); } } catch (Exception arg) { Plugin.Log.LogError((object)$"Campfire companion failed: {arg}"); } } private static void Show(FejdStartup menu) { //IL_009a: 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_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) if ((Object)(object)_current != (Object)null) { Object.Destroy((Object)(object)_current); _current = null; } CompanionSetup companionSetup = Companions.Get(Plugin.Choice.Value); if (companionSetup == null) { return; } GameObject val = FindPrefab(companionSetup.Prefab); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("No creature prefab '" + companionSetup.Prefab + "' is loaded in the menu; the menu stays as it is")); return; } _current = Spawn(val, companionSetup, menu.m_characterPreviewPoint, menu.m_cameraMarkerMain); if ((Object)(object)_pulledBackMenu != (Object)(object)menu) { _pulledBackMenu = menu; Transform cameraMarkerCharacter = menu.m_cameraMarkerCharacter; cameraMarkerCharacter.position -= cameraMarkerCharacter.forward * 2f; } } private static GameObject FindPrefab(string name) { //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) GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if (((Object)val).name == name) { Scene scene = val.scene; if (!((Scene)(ref scene)).IsValid() && (Object)(object)val.transform.parent == (Object)null) { return val; } } } string value = "/" + name.ToLowerInvariant() + ".prefab"; foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if ((Object)(object)allLoadedAssetBundle == (Object)null || allLoadedAssetBundle.isStreamedSceneAssetBundle) { continue; } string[] allAssetNames = allLoadedAssetBundle.GetAllAssetNames(); foreach (string text in allAssetNames) { if (text.StartsWith("assets/characters/", StringComparison.Ordinal) && text.EndsWith(value, StringComparison.Ordinal)) { return allLoadedAssetBundle.LoadAsset<GameObject>(text); } } } return null; } private static GameObject Spawn(GameObject prefab, CompanionSetup setup, Transform anchor, Transform cameraMarker) { //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_000b: 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_0025: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0058: 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_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_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_00ce: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_017c: 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_0194: 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_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_01b9: 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_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: 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_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0267: 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_0271: 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_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0211: 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_031d: 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_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = -cameraMarker.right; val.y = 0f; ((Vector3)(ref val)).Normalize(); Vector3 forward = cameraMarker.forward; forward.y = 0f; ((Vector3)(ref forward)).Normalize(); Vector3 position = anchor.position; GameObject val2 = new GameObject("CampfireCompanion"); val2.SetActive(false); val2.transform.position = position; val2.transform.rotation = Quaternion.LookRotation(-val) * Quaternion.Euler(0f, setup.Turn, 0f); Transform val3 = prefab.transform.Find("Visual"); if ((Object)(object)val3 == (Object)null) { val3 = prefab.transform; } GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, val2.transform, false); val4.transform.localPosition = Vector3.zero; val4.transform.localRotation = Quaternion.identity; val4.transform.localScale = val3.lossyScale; ApplyStars(val3, val4, setup.Stars); Strip(val4); Animator[] componentsInChildren = val4.GetComponentsInChildren<Animator>(true); foreach (Animator obj in componentsInChildren) { obj.applyRootMotion = false; obj.updateMode = (AnimatorUpdateMode)0; obj.cullingMode = (AnimatorCullingMode)0; } val2.AddComponent<KeepIdle>(); val2.SetActive(true); Bounds val5 = Bounds(val4); float scale = setup.Scale; float gap = setup.Gap; val2.transform.localScale = Vector3.one * scale; float num = Mathf.Max(((Bounds)(ref val5)).extents.x, ((Bounds)(ref val5)).extents.z) * scale; Vector3 val6 = position + val * (gap + num) + forward * 0.91f; val6.y = anchor.position.y; string text = "nothing"; RaycastHit val7 = default(RaycastHit); if (Physics.Raycast(val6 + Vector3.up * 5f, Vector3.down, ref val7, 20f)) { val6.y = ((RaycastHit)(ref val7)).point.y; text = ((Object)((RaycastHit)(ref val7)).collider).name + " (layer " + LayerMask.LayerToName(((Component)((RaycastHit)(ref val7)).collider).gameObject.layer) + ")"; } val2.transform.position = val6; Vector3 val8 = position + val * 2.12f - forward * 0.15f - val6; val8.y = 0f; if (((Vector3)(ref val8)).sqrMagnitude > 0.01f) { val2.transform.rotation = Quaternion.LookRotation(val8) * Quaternion.Euler(0f, setup.Turn, 0f); } Plugin.Log.LogDebug((object)$"{((Object)prefab).name}: {((Bounds)(ref val5)).size.y:0.00} m tall, half length {num:0.00} m; scale {scale:0.00}, gap {gap:0.00} m; at {val6} on {text}"); return val2; } private static void ApplyStars(Transform source, GameObject visual, int stars) { //IL_0076: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (stars <= 0) { return; } LevelEffects componentInChildren = ((Component)source.root).GetComponentInChildren<LevelEffects>(true); if ((Object)(object)componentInChildren == (Object)null || componentInChildren.m_levelSetups.Count < stars) { Plugin.Log.LogInfo((object)$"{((Object)source.root).name} has no {stars}-star look"); return; } LevelSetup val = componentInChildren.m_levelSetups[stars - 1]; Transform obj = InCopy(source, visual, ((Component)componentInChildren).transform) ?? visual.transform; obj.localScale *= val.m_scale; Transform val2 = InCopy(source, visual, ((Object)(object)componentInChildren.m_mainRender != (Object)null) ? ((Component)componentInChildren.m_mainRender).transform : null); Renderer val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<Renderer>() : null); if ((Object)(object)val3 != (Object)null) { Material[] sharedMaterials = val3.sharedMaterials; sharedMaterials[0] = new Material(sharedMaterials[0]); sharedMaterials[0].SetFloat("_Hue", val.m_hue); sharedMaterials[0].SetFloat("_Saturation", val.m_saturation); sharedMaterials[0].SetFloat("_Value", val.m_value); Traverse val4 = Traverse.Create((object)val); if (val4.Field("m_setEmissiveColor").FieldExists() && val4.Field<bool>("m_setEmissiveColor").Value) { sharedMaterials[0].SetColor("_EmissionColor", val4.Field<Color>("m_emissiveColor").Value); } val3.sharedMaterials = sharedMaterials; } Transform val5 = InCopy(source, visual, ((Object)(object)componentInChildren.m_baseEnableObject != (Object)null) ? componentInChildren.m_baseEnableObject.transform : null); if ((Object)(object)val5 != (Object)null) { ((Component)val5).gameObject.SetActive(false); } Transform val6 = InCopy(source, visual, ((Object)(object)val.m_enableObject != (Object)null) ? val.m_enableObject.transform : null); if ((Object)(object)val6 != (Object)null) { ((Component)val6).gameObject.SetActive(true); } } private static Transform InCopy(Transform source, GameObject visual, Transform original) { if ((Object)(object)original == (Object)null) { return null; } string text = ""; Transform val = original; while ((Object)(object)val != (Object)(object)source) { if ((Object)(object)val == (Object)null) { return null; } text = ((text.Length == 0) ? ((Object)val).name : (((Object)val).name + "/" + text)); val = val.parent; } if (text.Length != 0) { return visual.transform.Find(text); } return visual.transform; } private static void Strip(GameObject visual) { MonoBehaviour[] componentsInChildren = visual.GetComponentsInChildren<MonoBehaviour>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Collider[] componentsInChildren2 = visual.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } Rigidbody[] componentsInChildren3 = visual.GetComponentsInChildren<Rigidbody>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } } private static Bounds Bounds(GameObject visual) { //IL_0008: 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_004d: 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) Bounds result = default(Bounds); ((Bounds)(ref result))..ctor(visual.transform.position, Vector3.zero); Renderer[] componentsInChildren = visual.GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if (val is SkinnedMeshRenderer || val is MeshRenderer) { ((Bounds)(ref result)).Encapsulate(val.bounds); } } return result; } } internal sealed class KeepIdle : MonoBehaviour { private Animator[] _animators; private int[] _idle; private void Start() { _animators = ((Component)this).GetComponentsInChildren<Animator>(); _idle = new int[_animators.Length]; } private void Update() { //IL_0032: 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) for (int i = 0; i < _animators.Length; i++) { Animator val = _animators[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.runtimeAnimatorController == (Object)null) && !val.IsInTransition(0)) { AnimatorStateInfo currentAnimatorStateInfo = val.GetCurrentAnimatorStateInfo(0); if (_idle[i] == 0) { _idle[i] = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash; } if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash != _idle[i] || (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).loop && ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime >= 1f)) { val.Play(_idle[i], 0, 0f); } } } } } [BepInPlugin("dev.pgarcia.valheim.campfirecompanion", "Campfire Companion", "0.1.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "dev.pgarcia.valheim.campfirecompanion"; public const string PluginName = "Campfire Companion"; public const string PluginVersion = "0.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<Companion> Choice; private Harmony _harmony; private void Awake() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Choice = ((BaseUnityPlugin)this).Config.Bind<Companion>("General", "Companion", Companion.None, "The creature that stands with your character at the main menu campfire. None leaves the menu as it is; Random picks a different one each time the menu loads."); Choice.SettingChanged += delegate { CompanionSpawner.Refresh(); }; _harmony = new Harmony("dev.pgarcia.valheim.campfirecompanion"); _harmony.PatchAll(); } private void Update() { CompanionSpawner.Tick(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class BuildInfo { public const string Version = "0.1.0"; } } namespace ValheimCampfireCompanion.Patches { [HarmonyPatch(typeof(FejdStartup), "Start")] internal static class MenuStartPatch { private static void Postfix(FejdStartup __instance) { try { CompanionSpawner.OnMenuStart(__instance); } catch (Exception arg) { Plugin.Log.LogError((object)$"Campfire companion failed: {arg}"); } } } }