Please disclose if your mod was created primarily 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 HomieHeadcount v1.1.2
HomieHeadcount.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using HomieHeadcount.Extensions; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("HomieHeadcount")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HomieHeadcount")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("5f809d81-4375-4f75-b502-9172a452bb18")] [assembly: AssemblyFileVersion("1.1.2")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.2.0")] [module: UnverifiableCode] namespace HomieHeadcount { public class PluginConfig { public static ConfigEntry<bool> IsModEnabled { get; private set; } public static ConfigEntry<KeyboardShortcut> ToggleHomiePanel { get; private set; } public static void BindConfig(ConfigFile config) { IsModEnabled = config.Bind<bool>("_Global", "isModEnabled", true, "Globally enable or disable this mod."); IsModEnabled.OnSettingChanged<bool>(delegate { PanelManager.Hide(); PanelManager.Destroy(); }); } } public static class ConfigExtensions { public static void OnSettingChanged<T>(this ConfigEntry<T> configEntry, Action settingChangedHandler) { configEntry.SettingChanged += delegate { settingChangedHandler(); }; } } public class HomieCounter { public static List<Tameable> _activeHomies = new List<Tameable>(); public static List<Tameable> GetHomies() { return _activeHomies; } public static void Add(Tameable skeleton) { _activeHomies.Add(skeleton); } public static void Remove(Tameable skeleton) { _activeHomies.Remove(skeleton); } public static bool Contains(Tameable skeleton) { return _activeHomies.Contains(skeleton); } public static void Clear() { _activeHomies.Clear(); _activeHomies = new List<Tameable>(); } public static int Count() { return _activeHomies.Count; } } public static class PanelManager { public static HomieCountPanel HomieCountPanel { get; set; } public static void Toggle() { if (!Object.op_Implicit((Object)(object)HomieCountPanel?.Panel)) { HomieCountPanel = new HomieCountPanel(((Component)Hud.instance).transform); HomieCountPanel.SetInitialPosition(); HomieCountPanel.Panel.SetActive(true); } Update(); HomieCountPanel.Panel.SetActive(!HomieCountPanel.Panel.activeSelf); } public static void Hide() { if (Object.op_Implicit((Object)(object)HomieCountPanel?.Panel)) { HomieCountPanel.Panel.SetActive(false); } } public static void Destroy() { if (Object.op_Implicit((Object)(object)HomieCountPanel?.Panel)) { Object.Destroy((Object)(object)HomieCountPanel.Panel); HomieCountPanel = null; } } public static bool IsHomiePanelActive() { return Object.op_Implicit((Object)(object)HomieCountPanel?.Panel) && HomieCountPanel.Panel.activeSelf; } public static void Update() { if (Object.op_Implicit((Object)(object)HomieCountPanel?.Panel)) { HomieCountPanel.Update(); } } public static void AddHomie(Tameable tameable) { if (Object.op_Implicit((Object)(object)HomieCountPanel?.Panel)) { HomieCountPanel.AddHomie(tameable); } } } [BepInPlugin("bruce.valheim.comfymods.homieheadcount", "HomieHeadcount", "1.1.2")] public class HomieHeadcount : BaseUnityPlugin { public const string PluginGuid = "bruce.valheim.comfymods.homieheadcount"; public const string PluginName = "HomieHeadcount"; public const string PluginVersion = "1.1.2"; private Harmony _harmony; public static int SkeletonAiNameHashCode = StringExtensionMethods.GetStableHashCode("Skeleton_Friendly(Clone)"); private void Awake() { PluginConfig.BindConfig(((BaseUnityPlugin)this).Config); _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "bruce.valheim.comfymods.homieheadcount"); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(Tameable))] internal static class TameablePatch { [HarmonyPrefix] [HarmonyPatch("UnSummon")] public static void UnsummonPrefix(Tameable __instance) { if (Object.op_Implicit((Object)(object)((Component)__instance).gameObject) && HomieCounter.Contains(__instance)) { HomieCounter.Remove(__instance); } } [HarmonyPrefix] [HarmonyPatch("OnDeath")] public static void OnDeathPrefix(Tameable __instance) { if (Object.op_Implicit((Object)(object)((Component)__instance).gameObject) && HomieCounter.Contains(__instance)) { HomieCounter.Remove(__instance); } } } public class HomieCountPanel { private readonly RectTransform panelTransform; private readonly HomieHeaderRow _homieHeader; private readonly List<HomieRow> HomieRows = new List<HomieRow>(); public GameObject Panel { get; private set; } public HomieCountPanel(Transform parentTransform) { Panel = CreateChildPanel(parentTransform); panelTransform = Panel.GetComponent<RectTransform>(); _homieHeader = new HomieHeaderRow((Transform)(object)panelTransform); AddNewHomies(); } public void SetInitialPosition() { //IL_0011: 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_0047: 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_0070: Unknown result type (might be due to invalid IL or missing references) panelTransform.anchorMin = new Vector2(0f, 0.5f); panelTransform.anchorMax = new Vector2(0f, 0.5f); panelTransform.pivot = new Vector2(0f, 0.5f); ((Transform)panelTransform).position = Vector2.op_Implicit(GetDefaultPosition()); panelTransform.sizeDelta = GetSize(); } public void Update() { UpdateHomieInfo(); UpdateHeader(); UpdateHeight(); UpdatePosition(); } private void UpdateHeader() { _homieHeader.Update(); } private void UpdateHomieInfo() { foreach (HomieRow item in HomieRows.ToList()) { if ((Object)(object)item.GetHomie() == (Object)null) { RemoveHomieRow(item); } else { item.Update(); } } } private void UpdatePosition() { } private void AddNewHomies() { foreach (Tameable homy in HomieCounter.GetHomies()) { AddHomie(homy); } } public void AddHomie(Tameable homie) { HomieRows.Add(new HomieRow((Transform)(object)panelTransform, homie)); } public void RemoveHomieRow(HomieRow homieRow) { Object.Destroy((Object)(object)homieRow.Row); HomieRows.Remove(homieRow); } private GameObject CreateChildPanel(Transform parentTransform) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Panel", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parentTransform); VerticalLayoutGroup val2 = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = true; ((LayoutGroup)val2).padding.left = 2; ((LayoutGroup)val2).padding.right = 2; ((LayoutGroup)val2).padding.top = 2; ((LayoutGroup)val2).padding.bottom = 2; ((HorizontalOrVerticalLayoutGroup)val2).spacing = 4f; Image val3 = val.AddComponent<Image>(); val3.type = (Type)1; ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.8f); CanvasGroup val4 = val.AddComponent<CanvasGroup>(); val4.blocksRaycasts = true; return val; } private void UpdateHeight() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) panelTransform.sizeDelta = new Vector2(GetDefaultWidth(), GetConditionalHeight()); } private float GetConditionalHeight() { if (HomieRows.Count() <= 2) { return GetDefaultHeight(); } return (float)HomieRows.Count() * GetDefaultHeight() / 3f; } private Vector2 GetDefaultPosition() { //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_001d: Unknown result type (might be due to invalid IL or missing references) return new Vector2((float)Screen.width * 0.795f, (float)(Screen.height / 2)); } private Vector2 GetSize() { //IL_000d: 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_0015: Unknown result type (might be due to invalid IL or missing references) return new Vector2(GetDefaultWidth(), GetConditionalHeight()); } private float GetDefaultHeight() { return Screen.height / 8; } private float GetDefaultWidth() { return Screen.width / 5; } } public class HomieHeaderRow { private static readonly Dictionary<string, Font> FontCache = new Dictionary<string, Font>(); private readonly Tameable _homie; private readonly Text _homieNameText; private readonly Text _homieHealthText; private readonly Text _homiePositionText; private readonly string _baseHeaderText = "Homies Summoned: "; private static Font AveriaSerifLibre => FindFont("AveriaSerifLibre-Regular"); public GameObject Row { get; private set; } public Transform RowTransform { get; private set; } public HomieHeaderRow(Transform parentTransform) { Row = CreateChildRow(parentTransform); _homieNameText = CreateChildLabel(Row.transform, GetHeaderText()); } public void Update() { _homieNameText.text = GetHeaderText(); } private GameObject CreateChildRow(Transform parentTransform) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown GameObject val = new GameObject("Row", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parentTransform); HorizontalLayoutGroup val2 = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = true; ((LayoutGroup)val2).padding.left = 8; ((LayoutGroup)val2).padding.right = 8; ((LayoutGroup)val2).padding.top = 2; ((LayoutGroup)val2).padding.bottom = 2; ((HorizontalOrVerticalLayoutGroup)val2).spacing = 8f; ((LayoutGroup)val2).childAlignment = (TextAnchor)4; return val; } public Text CreateChildLabel(Transform parentTransform, string displaytext) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0064: 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) GameObject val = new GameObject(((Object)parentTransform).name + ".Label", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parentTransform); Text val2 = val.AddComponent<Text>(); val2.supportRichText = true; val2.font = AveriaSerifLibre; val2.fontSize = 48; val2.alignment = (TextAnchor)4; ((Graphic)val2).color = Color.white; val2.resizeTextForBestFit = false; val2.text = displaytext; Outline val3 = val.AddComponent<Outline>(); ((Shadow)val3).effectColor = Color.black; val.AddComponent<LayoutElement>(); return val2; } public static Font FindFont(string name) { if (!FontCache.TryGetValue(name, out var value)) { value = Resources.FindObjectsOfTypeAll<Font>().First((Font f) => ((Object)f).name == name); FontCache[name] = value; } return value; } private string GetHeaderText() { return $"{_baseHeaderText}{HomieCounter.Count()}"; } } public class HomieRow { private static readonly Dictionary<string, Font> FontCache = new Dictionary<string, Font>(); private readonly Tameable _homie; private readonly Text _homieNameText; private readonly Text _homieLoadoutText; private readonly Text _homieHealthText; private readonly Text _homiePositionText; private static Font AveriaSerifLibre => FindFont("AveriaSerifLibre-Regular"); public GameObject Row { get; private set; } public Transform RowTransform { get; private set; } public HomieRow(Transform parentTransform, Tameable homie) { Row = CreateChildRow(parentTransform); _homie = homie; RectTransform component = ((Component)parentTransform).GetComponent<RectTransform>(); _homieNameText = CreateChildLabel(Row.transform, "name", GetNameWidth(component)); _homieLoadoutText = CreateChildLabel(Row.transform, "loadout", GetLoadoutWidth(component)); _homieHealthText = CreateChildLabel(Row.transform, "health", GetHealthWidth(component)); _homiePositionText = CreateChildLabel(Row.transform, "position", GetPositionWidth(component)); Update(); } public void Update() { _homieNameText.text = _homie.GetName(); _homieLoadoutText.text = _homie.GetLoadout(); _homieHealthText.text = _homie.GetHealth().ToString("F1"); _homiePositionText.text = _homie.GetStringDistanceFromPlayer(); } private GameObject CreateChildRow(Transform parentTransform) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown GameObject val = new GameObject("Row", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parentTransform); HorizontalLayoutGroup val2 = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = true; ((LayoutGroup)val2).padding.left = 8; ((LayoutGroup)val2).padding.right = 8; ((LayoutGroup)val2).padding.top = 2; ((LayoutGroup)val2).padding.bottom = 2; ((HorizontalOrVerticalLayoutGroup)val2).spacing = 8f; ((LayoutGroup)val2).childAlignment = (TextAnchor)4; return val; } public Text CreateChildLabel(Transform parentTransform, string name, float width) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0065: 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) GameObject val = new GameObject(((Object)parentTransform).name + "." + name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parentTransform); Text val2 = val.AddComponent<Text>(); val2.supportRichText = true; val2.font = AveriaSerifLibre; val2.fontSize = 28; val2.alignment = (TextAnchor)4; ((Graphic)val2).color = Color.white; val2.resizeTextForBestFit = false; val2.text = ""; Outline val3 = val.AddComponent<Outline>(); ((Shadow)val3).effectColor = Color.black; LayoutElement val4 = val.AddComponent<LayoutElement>(); val4.minWidth = width / 2f; val4.preferredWidth = width; return val2; } public Tameable GetHomie() { return _homie; } public static Font FindFont(string name) { if (!FontCache.TryGetValue(name, out var value)) { value = Resources.FindObjectsOfTypeAll<Font>().First((Font f) => ((Object)f).name == name); FontCache[name] = value; } return value; } private float GetNameWidth(RectTransform parentTransform) { //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) Rect rect = parentTransform.rect; return ((Rect)(ref rect)).width * 0.5f; } private float GetLoadoutWidth(RectTransform parentTransform) { //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) Rect rect = parentTransform.rect; return ((Rect)(ref rect)).width * 0.8f; } private float GetHealthWidth(RectTransform parentTransform) { //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) Rect rect = parentTransform.rect; return ((Rect)(ref rect)).width * 0.25f; } private float GetPositionWidth(RectTransform parentTransform) { //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) Rect rect = parentTransform.rect; return ((Rect)(ref rect)).width * 0.25f; } } } namespace HomieHeadcount.Patches { [HarmonyPatch(typeof(Menu))] internal static class MenuPatch { [HarmonyPrefix] [HarmonyPatch("OnLogoutYes")] public static void OnLogoutYesPrefix(Menu __instance) { PanelManager.Destroy(); HomieCounter.Clear(); } } [HarmonyPatch(typeof(MonsterAI))] internal static class MonsterAIPatch { [HarmonyPostfix] [HarmonyPatch("SetFollowTarget")] public static void SetFollowTargetPostfix(MonsterAI __instance) { Player val = default(Player); Tameable val2 = default(Tameable); if (Object.op_Implicit((Object)(object)__instance) && StringExtensionMethods.GetStableHashCode(((Object)__instance).name) == HomieHeadcount.SkeletonAiNameHashCode && Object.op_Implicit((Object)(object)__instance.m_follow) && __instance.m_follow.TryGetComponent<Player>(ref val) && ((Component)__instance).TryGetComponent<Tameable>(ref val2) && val.GetPlayerID() == Player.m_localPlayer.GetPlayerID()) { HomieCounter.Add(val2); PanelManager.AddHomie(val2); } } } [HarmonyPatch(typeof(Player))] internal static class PlayerPatch { [HarmonyPostfix] [HarmonyPatch("Update")] public static void UpdatePostifx() { if (PluginConfig.IsModEnabled.Value && Object.op_Implicit((Object)(object)Hud.instance)) { if (PanelManager.IsHomiePanelActive() && HomieCounter.Count() == 0) { PanelManager.Toggle(); } else if (!PanelManager.IsHomiePanelActive() && HomieCounter.Count() > 0) { PanelManager.Toggle(); } else if (PanelManager.IsHomiePanelActive()) { PanelManager.Update(); } } } } } namespace HomieHeadcount.Extensions { public static class TameableExtensions { private static readonly Dictionary<string, string> _itemNameConversions = new Dictionary<string, string> { { "Dragur axe", "Sword" }, { "$item_shield_wood", "Wood Shield" }, { "$item_shield_bronzebuckler", "Bronze Buckler" } }; public static string GetName(this Tameable tameable) { if (!Object.op_Implicit((Object)(object)tameable.m_nview) || !tameable.m_nview.IsValid()) { return ""; } return tameable.m_nview.GetZDO().GetString(ZDOVars.s_tamedName, ""); } public static ItemData GetWeapon(this Tameable tameable) { //IL_0048: 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 (!Object.op_Implicit((Object)(object)tameable) || !Object.op_Implicit((Object)(object)((Component)tameable).gameObject) || !Object.op_Implicit((Object)(object)tameable.m_character) || ((Humanoid)tameable.m_character).GetCurrentWeapon() == null) { return null; } return ((Humanoid)tameable.m_character).GetCurrentWeapon(); } public static ItemData GetOffHand(this Tameable tameable) { //IL_0021: 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) if (!Object.op_Implicit((Object)(object)((Component)tameable).gameObject) || !Object.op_Implicit((Object)(object)tameable.m_character) || ((Humanoid)tameable.m_character).GetCurrentBlocker() == null) { return null; } return ((Humanoid)tameable.m_character).GetCurrentBlocker(); } public static float GetHealth(this Tameable tameable) { Character val = default(Character); if (!Object.op_Implicit((Object)(object)((Component)tameable).gameObject) || !((Component)tameable).gameObject.TryGetComponent<Character>(ref val)) { return 0f; } return val.GetHealth(); } public static float GetDistanceFromPlayer(this Tameable tameable) { //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_0022: 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_003a: 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) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0f; } Vector3 position = tameable.GetPosition(); if (position == Vector3.zero) { return 0f; } return Vector3.Distance(position, ((Component)Player.m_localPlayer).transform.position); } public static string GetStringDistanceFromPlayer(this Tameable tameable) { //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_0022: 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_003a: 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) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return ""; } Vector3 position = tameable.GetPosition(); if (position == Vector3.zero) { return ""; } return Vector3.Distance(position, ((Component)Player.m_localPlayer).transform.position).ToString("F1") + "m"; } public static string GetLoadout(this Tameable tameable) { if ((Object)(object)tameable == (Object)null) { return ""; } ItemData weapon = tameable.GetWeapon(); ItemData offHand = tameable.GetOffHand(); if (weapon != null) { if (offHand != null && weapon.m_shared.m_name != offHand.m_shared.m_name) { return ConvertItemName(weapon.m_shared.m_name) + " + " + ConvertItemName(offHand.m_shared.m_name); } return ConvertItemName(weapon.m_shared.m_name); } if (offHand != null) { return ConvertItemName(offHand.m_shared.m_name) ?? ""; } return null; } public static Vector3 GetPosition(this Tameable tameable) { //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_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) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)tameable.m_nview) || !Object.op_Implicit((Object)(object)((Component)tameable.m_nview).gameObject)) { return Vector3.zero; } return ((Component)tameable.m_nview).gameObject.transform.position; } private static string ConvertItemName(string itemName) { if (_itemNameConversions.ContainsKey(itemName)) { return _itemNameConversions[itemName]; } return itemName; } } }