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 BestiaryTracker v1.0.0
BestiaryTracker.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Koendertjh.Shared; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [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("BestiaryTracker")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a45c570d17c512d77d75166ff42bc1dee72ef243")] [assembly: AssemblyProduct("BestiaryTracker")] [assembly: AssemblyTitle("BestiaryTracker")] [assembly: AssemblyVersion("1.0.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 Koendertjh.Shared { internal static class AchievementStats { private static readonly Dictionary<object, KeyValuePair<int, HashSet<string>>> s_keys = new Dictionary<object, KeyValuePair<int, HashSet<string>>>(); internal static Achievement Find(string id) { if ((Object)(object)Achievements.m_instance == (Object)null) { return null; } foreach (AchievementList achievementList in Achievements.m_instance.m_achievementLists) { foreach (Achievement achievement in achievementList.m_achievements) { if ((Object)(object)achievement != (Object)null && achievement.m_id == id) { return achievement; } } } return null; } internal static PlayerStats StatsFor(Achievement achievement) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) Game instance = Game.instance; PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null); if (val == null || (Object)(object)achievement == (Object)null) { return null; } return val.m_playerStats[achievement.m_difficultyRequirement]; } internal static HashSet<string> Keys(List<DictStatRequirement> triggers) { //IL_0040: 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_0047: Unknown result type (might be due to invalid IL or missing references) if (triggers == null) { return new HashSet<string>(); } if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count) { return value.Value; } HashSet<string> hashSet = new HashSet<string>(); foreach (DictStatRequirement trigger in triggers) { hashSet.Add(trigger.m_stat); } s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet); return hashSet; } internal static HashSet<string> Keys(List<EnemyStatRequirement> triggers) { //IL_0040: 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_0047: Unknown result type (might be due to invalid IL or missing references) if (triggers == null) { return new HashSet<string>(); } if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count) { return value.Value; } HashSet<string> hashSet = new HashSet<string>(); foreach (EnemyStatRequirement trigger in triggers) { hashSet.Add(trigger.m_stat); } s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet); return hashSet; } internal static bool Has(Dictionary<string, float> stats, string key) { if (stats != null && stats.TryGetValue(key, out var value)) { return value >= 1f; } return false; } internal static int CountDone(HashSet<string> keys, Dictionary<string, float> stats) { int num = 0; foreach (string key in keys) { if (Has(stats, key)) { num++; } } return num; } } internal enum Boss { None, Eikthyr, Elder, Bonemass, Moder, Yagluth, Queen, Fader, Kall } internal static class BossProgress { private static readonly string[] EnemyNames = new string[9] { null, "$enemy_eikthyr", "$enemy_gdking", "$enemy_bonemass", "$enemy_dragon", "$enemy_goblinking", "$enemy_seekerqueen", "$enemy_fader", "$enemy_frozenking_p3" }; private static Dictionary<string, string> s_defeatKeys; private static ZNetScene s_keysScene; internal static string EnemyName(Boss boss) { return EnemyNames[(int)boss]; } internal static bool IsDefeated(Boss boss) { if (boss == Boss.None) { return true; } string enemyName = EnemyName(boss); if (HasKilled(enemyName)) { return true; } string text = DefeatKey(enemyName); if (string.IsNullOrEmpty(text)) { return false; } if (!((Object)(object)ZoneSystem.instance != (Object)null) || !ZoneSystem.instance.GetGlobalKey(text)) { if ((Object)(object)Player.m_localPlayer != (Object)null) { return ((Humanoid)Player.m_localPlayer).HaveUniqueKey(text); } return false; } return true; } internal static bool HasKilled(string enemyName) { Game instance = Game.instance; PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null); if (val == null) { return false; } PlayerStats[] playerStats = val.m_playerStats; foreach (PlayerStats val2 in playerStats) { if (val2?.m_enemyStats == null) { continue; } Dictionary<string, float>[] enemyStats = val2.m_enemyStats; foreach (Dictionary<string, float> dictionary in enemyStats) { if (dictionary != null && dictionary.TryGetValue(enemyName, out var value) && value > 0f) { return true; } } } return false; } private static string DefeatKey(string enemyName) { if ((Object)(object)ZNetScene.instance == (Object)null) { return null; } if (s_defeatKeys == null || (Object)(object)s_keysScene != (Object)(object)ZNetScene.instance) { s_defeatKeys = new Dictionary<string, string>(); s_keysScene = ZNetScene.instance; foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { Character val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Character>() : null); if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(val.m_defeatSetGlobalKey)) { s_defeatKeys[val.m_name] = val.m_defeatSetGlobalKey; } } } s_defeatKeys.TryGetValue(enemyName, out var value); return value; } } internal enum Stage { Meadows, BlackForest, Swamp, Mountain, Plains, Mistlands, Ashlands, DeepNorth } internal static class Stages { internal static Boss RevealedBy(Stage stage) { return (Boss)stage; } internal static bool IsRevealed(Stage stage) { return BossProgress.IsDefeated(RevealedBy(stage)); } internal static Stage FromBiome(Biome biome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0005: 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) //IL_001d: Expected I4, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if ((int)biome <= 16) { switch (biome - 1) { case 0: return Stage.Meadows; case 1: goto IL_0043; case 3: return Stage.Mountain; case 2: goto IL_004d; } if ((int)biome == 8) { return Stage.BlackForest; } if ((int)biome == 16) { return Stage.Plains; } } else { if ((int)biome == 32) { return Stage.Ashlands; } if ((int)biome == 256) { goto IL_0043; } if ((int)biome == 512) { return Stage.Mistlands; } } goto IL_004d; IL_0043: return Stage.Swamp; IL_004d: return Stage.DeepNorth; } internal static Stage Earliest(Biome biomes) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0030: 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) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Stage stage = Stage.DeepNorth; foreach (Biome value in Enum.GetValues(typeof(Biome))) { if ((int)value != 0 && (int)value != 895 && (Biome)(biomes & value) == value) { Stage stage2 = FromBiome(value); if (stage2 < stage) { stage = stage2; } } } return stage; } internal static string BiomeName(Stage stage) { return stage switch { Stage.Meadows => "the Meadows", Stage.BlackForest => "the Black Forest", Stage.Swamp => "the Swamp", Stage.Mountain => "the Mountains", Stage.Plains => "the Plains", Stage.Mistlands => "the Mistlands", Stage.Ashlands => "the Ashlands", _ => "the Deep North", }; } } internal enum EntryState { Done, Missing, Hidden } internal class WindowEntry { public Sprite Icon; public string Name; public string Description; public EntryState State; } internal sealed class InventoryWindow { private sealed class Slot { public GameObject Root; public Image Icon; public TMP_Text Name; public TMP_Text Description; public Color NameColor; public Color DescriptionColor; public GameObject QuestionMark; } private const string PanelSuffix = "_InventoryWindow"; private const string HiddenText = "<i>Only Odin knows what is hidden here.</i>"; private static readonly Color GreyIcon = new Color(0.25f, 0.25f, 0.25f, 0.85f); private static readonly Color GreyText = new Color(0.55f, 0.55f, 0.55f, 1f); private readonly string _id; private readonly string _title; private readonly string _tooltip; private readonly Func<Sprite> _buttonIcon; private readonly Func<List<WindowEntry>, string> _fill; private GameObject _panel; private RectTransform _listRoot; private Scrollbar _scrollbar; private TMP_Text _titleText; private float _baseHeight; private readonly List<Slot> _slots = new List<Slot>(); private static int s_columns; private static ObjectDB s_columnsDb; public bool IsOpen { get { if ((Object)(object)_panel != (Object)null) { return _panel.activeSelf; } return false; } } public InventoryWindow(string id, string title, string tooltip, Func<Sprite> buttonIcon, Func<List<WindowEntry>, string> fill) { _id = id; _title = title; _tooltip = tooltip; _buttonIcon = buttonIcon; _fill = fill; } public bool Create(InventoryGui gui, ManualLogSource log) { try { CreatePanel(gui); CreateButton(gui, log); return true; } catch (Exception arg) { log.LogWarning((object)$"Couldn't add the {_title} window: {arg}"); if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); } _panel = null; return false; } } private void CreatePanel(InventoryGui gui) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Expected O, but got Unknown GameObject trophiesPanel = gui.m_trophiesPanel; string text = PathFrom(trophiesPanel.transform, (Transform)(object)gui.m_trophieListRoot); string text2 = PathFrom(trophiesPanel.transform, ((Component)gui.m_trophyListScroll).transform); _slots.Clear(); _panel = Object.Instantiate<GameObject>(trophiesPanel, trophiesPanel.transform.parent); ((Object)_panel).name = _id + "_InventoryWindow"; _panel.SetActive(false); _listRoot = (RectTransform)_panel.transform.Find(text); Transform obj = _panel.transform.Find(text2); _scrollbar = ((obj != null) ? ((Component)obj).GetComponent<Scrollbar>() : null); Rect rect = gui.m_trophieListRoot.rect; _baseHeight = ((Rect)(ref rect)).height; for (int num = ((Transform)_listRoot).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)_listRoot).GetChild(num)).gameObject); } UIGroupHandler[] componentsInChildren = _panel.GetComponentsInChildren<UIGroupHandler>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.Destroy((Object)(object)componentsInChildren[i]); } string text3 = Localization.instance.Localize("$inventory_trophies"); TMP_Text[] componentsInChildren2 = _panel.GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val in componentsInChildren2) { if (val.transform.IsChildOf((Transform)(object)_listRoot) || (val.text != text3 && val.text != "$inventory_trophies")) { continue; } Component[] components = ((Component)val).GetComponents<Component>(); foreach (Component val2 in components) { if ((Object)(object)val2 != (Object)null && ((object)val2).GetType().Name == "Localize") { Object.Destroy((Object)(object)val2); } } val.text = _title; _titleText = val; } Button[] componentsInChildren3 = _panel.GetComponentsInChildren<Button>(true); foreach (Button val3 in componentsInChildren3) { if (Rewire((UnityEventBase)(object)val3.onClick, "OnCloseTrophies")) { ((UnityEvent)val3.onClick).AddListener(new UnityAction(Close)); } } } private void CreateButton(InventoryGui gui, ManualLogSource log) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_014c: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) Button val = null; Button[] componentsInChildren = ((Component)gui).GetComponentsInChildren<Button>(true); foreach (Button val2 in componentsInChildren) { if (HasPersistent((UnityEventBase)(object)val2.onClick, "OnOpenTrophies") && !((Object)val2).name.EndsWith("_Button") && !((Component)val2).transform.IsChildOf(_panel.transform)) { val = val2; break; } } if ((Object)(object)val == (Object)null) { log.LogWarning((object)("Couldn't find the Trophies button; the " + _title + " window has no button.")); return; } GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val3).name = _id + "_Button"; Button component = val3.GetComponent<Button>(); Rewire((UnityEventBase)(object)component.onClick, "OnOpenTrophies"); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { Open(gui); }); val3.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1); if ((Object)(object)((Component)val3.transform.parent).GetComponent<LayoutGroup>() == (Object)null) { SpreadRow((RectTransform)((Component)val).transform, (RectTransform)val3.transform); } UITooltip component2 = val3.GetComponent<UITooltip>(); if ((Object)(object)component2 != (Object)null) { component2.Set(_title, _tooltip, (RectTransform)null, default(Vector2)); } Transform obj = val3.transform.Find("Image"); Image val4 = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null); Sprite val5 = _buttonIcon?.Invoke(); if ((Object)(object)val4 != (Object)null && (Object)(object)val5 != (Object)null) { val4.sprite = val5; val4.preserveAspect = true; } } private static void SpreadRow(RectTransform trophies, RectTransform added) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_003c: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) List<RectTransform> list = new List<RectTransform>(); foreach (Transform item in ((Transform)trophies).parent) { Transform val = item; RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null); if (val2 != null && (Object)(object)val != (Object)(object)added && Mathf.Abs(val2.anchoredPosition.y - trophies.anchoredPosition.y) < 1f) { Vector2 val3 = val2.sizeDelta - trophies.sizeDelta; if (((Vector2)(ref val3)).sqrMagnitude < 1f) { list.Add(val2); } } } list.Sort((RectTransform a, RectTransform b) => a.anchoredPosition.x.CompareTo(b.anchoredPosition.x)); list.Insert(list.IndexOf(trophies) + 1, added); if (list.Count < 3) { return; } float x = list[0].anchoredPosition.x; float x2 = list[list.Count - 1].anchoredPosition.x; float num = Mathf.Max(x2 - x, 0f) / (float)(list.Count - 2); Rect rect = ((RectTransform)((Transform)trophies).parent).rect; float width = ((Rect)(ref rect)).width; if (width > 0f) { num = Mathf.Min(num, (width - trophies.sizeDelta.x - 8f) / (float)(list.Count - 1)); } float num2 = (x + x2) / 2f - num * (float)(list.Count - 1) / 2f; foreach (RectTransform item2 in list) { item2.anchoredPosition = new Vector2(num2, trophies.anchoredPosition.y); num2 += num; } } private static string PathFrom(Transform root, Transform target) { List<string> list = new List<string>(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Insert(0, ((Object)val).name); val = val.parent; } return string.Join("/", list); } private static bool HasPersistent(UnityEventBase onClick, string method) { for (int i = 0; i < onClick.GetPersistentEventCount(); i++) { if (onClick.GetPersistentMethodName(i) == method) { return true; } } return false; } private static bool Rewire(UnityEventBase onClick, string method) { bool result = false; for (int i = 0; i < onClick.GetPersistentEventCount(); i++) { if (!(onClick.GetPersistentMethodName(i) != method)) { onClick.SetPersistentListenerState(i, (UnityEventCallState)0); result = true; } } return result; } private void Open(InventoryGui gui) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown if ((Object)(object)_panel == (Object)null) { return; } gui.m_trophiesPanel.SetActive(false); ((Component)gui.m_achievementsPanel).gameObject.SetActive(false); foreach (Transform item in _panel.transform.parent) { Transform val = item; if ((Object)(object)((Component)val).gameObject != (Object)(object)_panel && ((Object)val).name.EndsWith("_InventoryWindow")) { ((Component)val).gameObject.SetActive(false); } } _panel.SetActive(true); Fill(gui); } public void Close() { if ((Object)(object)_panel != (Object)null) { _panel.SetActive(false); } } public bool HandleEscape() { if (!IsOpen || (!ZInput.GetButtonDown("JoyButtonB") && !ZInput.GetKeyDown((KeyCode)27, true))) { return false; } Close(); return true; } private void Fill(InventoryGui gui) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)_listRoot == (Object)null) { return; } List<WindowEntry> list = new List<WindowEntry>(); string text = _fill(list); float trophieListSpace = gui.m_trophieListSpace; int num = Columns(); while (_slots.Count < list.Count) { _slots.Add(NewSlot(gui)); } for (int i = 0; i < _slots.Count; i++) { Slot slot = _slots[i]; if (i >= list.Count) { if (slot.Root.activeSelf) { slot.Root.SetActive(false); } continue; } WindowEntry windowEntry = list[i]; slot.Root.SetActive(true); ((RectTransform)slot.Root.transform).anchoredPosition = new Vector2((float)(i % num) * trophieListSpace, (float)(i / num) * (0f - trophieListSpace)); switch (windowEntry.State) { case EntryState.Done: SetIcon(slot, windowEntry.Icon, Color.white); SetText(slot.Name, windowEntry.Name, slot.NameColor); SetText(slot.Description, windowEntry.Description, slot.DescriptionColor); break; case EntryState.Missing: SetIcon(slot, windowEntry.Icon, GreyIcon); SetText(slot.Name, windowEntry.Name, GreyText); SetText(slot.Description, windowEntry.Description, GreyText); break; default: SetIcon(slot, null, GreyIcon); SetText(slot.Name, "??????", GreyText); SetText(slot.Description, "<i>Only Odin knows what is hidden here.</i>", GreyText); break; } } if ((Object)(object)_titleText != (Object)null) { _titleText.text = text ?? _title; } int num2 = (list.Count + num - 1) / num; _listRoot.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(_baseHeight, (float)num2 * trophieListSpace)); if ((Object)(object)_scrollbar != (Object)null) { _scrollbar.value = 1f; } } private Slot NewSlot(InventoryGui gui) { //IL_0099: 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) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(gui.m_trophieElementPrefab, (Transform)(object)_listRoot); Transform transform = val.transform; Slot obj = new Slot { Root = val }; Transform obj2 = transform.Find("icon_bkg/icon"); obj.Icon = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null); Transform obj3 = transform.Find("name"); obj.Name = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null); Transform obj4 = transform.Find("description"); obj.Description = ((obj4 != null) ? ((Component)obj4).GetComponent<TMP_Text>() : null); Slot slot = obj; slot.NameColor = (((Object)(object)slot.Name != (Object)null) ? ((Graphic)slot.Name).color : Color.white); slot.DescriptionColor = (((Object)(object)slot.Description != (Object)null) ? ((Graphic)slot.Description).color : Color.white); return slot; } private static void SetText(TMP_Text text, string value, Color color) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)text == (Object)null)) { text.text = value; ((Graphic)text).color = color; } } private static void SetIcon(Slot slot, Sprite sprite, Color color) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) Image icon = slot.Icon; if ((Object)(object)icon == (Object)null) { return; } if ((Object)(object)sprite != (Object)null) { ((Behaviour)icon).enabled = true; icon.sprite = sprite; ((Graphic)icon).color = color; if ((Object)(object)slot.QuestionMark != (Object)null) { slot.QuestionMark.SetActive(false); } return; } ((Behaviour)icon).enabled = false; if ((Object)(object)slot.QuestionMark == (Object)null && (Object)(object)slot.Name != (Object)null) { GameObject val = Object.Instantiate<GameObject>(((Component)slot.Name).gameObject, ((Component)icon).transform); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.pivot = new Vector2(0.5f, 0.5f); val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; ((Transform)val2).localScale = Vector3.one; TMP_Text component = val.GetComponent<TMP_Text>(); Rect rect = ((RectTransform)((Component)icon).transform).rect; float height = ((Rect)(ref rect)).height; component.enableAutoSizing = false; component.fontSize = ((height > 0f) ? (height * 0.8f) : 48f); component.alignment = (TextAlignmentOptions)514; ((Graphic)component).color = GreyText; component.text = "?"; slot.QuestionMark = val; } if ((Object)(object)slot.QuestionMark != (Object)null) { slot.QuestionMark.SetActive(true); } } private static int Columns() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Invalid comparison between Unknown and I4 if ((Object)(object)s_columnsDb == (Object)(object)ObjectDB.instance && s_columns > 0) { return s_columns; } int num = 1; foreach (GameObject item in ObjectDB.instance.m_items) { ItemDrop val = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null); if ((Object)(object)val != (Object)null && (int)val.m_itemData.m_shared.m_itemType == 13) { num = Mathf.Max(num, ((Vector2Int)(ref val.m_itemData.m_shared.m_trophyPos)).x + 1); } } s_columnsDb = ObjectDB.instance; s_columns = num; return num; } } internal static class ShapeIcon { private const int Size = 128; private const int MaxDistance = 16; internal static Sprite Create(string name, Func<float, float, bool> inside) { //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) float[] array = new float[16384]; for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { int num = 0; for (int k = 0; k < 4; k++) { for (int l = 0; l < 4; l++) { if (inside((float)j + ((float)l + 0.5f) / 4f, (float)i + ((float)k + 0.5f) / 4f)) { num++; } } } array[i * 128 + j] = (float)num / 16f; } } float[] array2 = new float[16384]; for (int m = 0; m < 128; m++) { for (int n = 0; n < 128; n++) { array2[m * 128 + n] = ((array[m * 128 + n] > 0f) ? DistanceToEdge(array, n, m) : 0f); } } Color32[] array3 = (Color32[])(object)new Color32[16384]; for (int num2 = 0; num2 < 128; num2++) { for (int num3 = 0; num3 < 128; num3++) { float num4 = array[num2 * 128 + num3]; byte b = (byte)(Mathf.Clamp01((num4 > 0f) ? Shade(array2, num3, num2) : 1f) * 255f); array3[num2 * 128 + num3] = new Color32(b, b, b, (byte)(num4 * 255f)); } } Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; val.SetPixels32(array3); val.Apply(); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f); ((Object)obj).name = name; return obj; } private static float Shade(float[] distance, int x, int y) { float num = Mathf.PerlinNoise((float)x * 0.07f + 3.1f, (float)y * 0.07f + 7.7f) * 0.6f + Mathf.PerlinNoise((float)x * 0.19f + 11.3f, (float)y * 0.19f + 1.9f) * 0.4f; float num2 = Mathf.Lerp(0.78f, 1f, num) * Mathf.Lerp(1f, 0.86f, (float)x / 128f); float num3 = distance[y * 128 + x]; if (num3 < 2.5f) { num2 *= Mathf.Lerp(0.55f, 1f, num3 / 2.5f); } else if (num3 >= 6f && num3 < 8f && DeepNearby(distance, x, y)) { num2 *= 0.62f; } return num2; } private static bool DeepNearby(float[] distance, int x, int y) { for (int i = -5; i <= 5; i++) { for (int j = -5; j <= 5; j++) { int num = x + j; int num2 = y + i; if (num >= 0 && num2 >= 0 && num < 128 && num2 < 128 && distance[num2 * 128 + num] >= 13f) { return true; } } } return false; } private static float DistanceToEdge(float[] coverage, int x, int y) { int num = 256; for (int i = -16; i <= 16; i++) { int num2 = y + i; for (int j = -16; j <= 16; j++) { int num3 = j * j + i * i; if (num3 < num) { int num4 = x + j; if (num4 < 0 || num2 < 0 || num4 >= 128 || num2 >= 128 || coverage[num2 * 128 + num4] < 0.5f) { num = num3; } } } } return Mathf.Sqrt((float)num); } internal static bool Trapezoid(float x, float y, float bottom, float top, float bottomLeft, float bottomRight, float topLeft, float topRight) { if (y < bottom || y > top) { return false; } float num = (y - bottom) / (top - bottom); if (x >= Mathf.Lerp(bottomLeft, topLeft, num)) { return x <= Mathf.Lerp(bottomRight, topRight, num); } return false; } internal static bool Ellipse(float x, float y, float cx, float cy, float rx, float ry) { float num = (x - cx) / rx; float num2 = (y - cy) / ry; return num * num + num2 * num2 <= 1f; } } } namespace BestiaryTracker { internal static class Bestiary { private static Achievement s_hunter; private static Achievement s_masterHunter; private static Achievement Hunter { get { if (!((Object)(object)s_hunter != (Object)null)) { return s_hunter = AchievementStats.Find("KillAllCreatures"); } return s_hunter; } } private static Achievement MasterHunter { get { if (!((Object)(object)s_masterHunter != (Object)null)) { return s_masterHunter = AchievementStats.Find("KillAllCreaturesHard"); } return s_masterHunter; } } internal static Achievement Current { get { //IL_0017: 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) Achievement masterHunter = MasterHunter; if ((Object)(object)masterHunter != (Object)null && !masterHunter.m_unlocked && Achievements.GetCurrentAchievementDifficulty() >= masterHunter.m_difficultyRequirement) { return masterHunter; } return Hunter; } } internal static HashSet<string> Creatures(Achievement achievement) { return AchievementStats.Keys(achievement?.m_enemyStatsTriggers); } private static Dictionary<string, float> Kills(Achievement achievement) { PlayerStats obj = AchievementStats.StatsFor(achievement); if (obj == null) { return null; } return obj.m_enemyStats[0]; } internal static bool Counts(Achievement achievement, string creature) { return Creatures(achievement).Contains(creature); } internal static bool IsSlain(Achievement achievement, string creature) { return AchievementStats.Has(Kills(achievement), creature); } internal static int SlainCount(Achievement achievement) { return AchievementStats.CountDone(Creatures(achievement), Kills(achievement)); } } internal class CreatureInfo { public string Name; public Sprite Trophy; public Biome Biomes; public Stage Stage; } [HarmonyPatch(typeof(InventoryGui))] internal static class BestiaryWindow { private const string Title = "Bestiary"; private static readonly Dictionary<string, Stage> FixedStages = new Dictionary<string, Stage> { { "$enemy_eikthyr", Stage.Meadows }, { "$enemy_gdking", Stage.BlackForest }, { "$enemy_bonemass", Stage.Swamp }, { "$enemy_dragon", Stage.Mountain }, { "$enemy_goblinking", Stage.Plains }, { "$enemy_seekerqueen", Stage.Mistlands }, { "$enemy_fader", Stage.Ashlands } }; private static readonly InventoryWindow Window = new InventoryWindow("BestiaryTracker", "Bestiary", "Every creature to slay for The Hunter", PawIcon, Fill); private static Sprite s_paw; private static Dictionary<string, CreatureInfo> s_creatures; private static ZNetScene s_scene; [HarmonyPostfix] [HarmonyPatch("Awake")] private static void Create(InventoryGui __instance) { Window.Create(__instance, BestiaryTrackerPlugin.Log); } [HarmonyPostfix] [HarmonyPatch("Hide")] private static void AfterHide() { Window.Close(); } [HarmonyPostfix] [HarmonyPatch("OnOpenTrophies")] private static void AfterOpenTrophies() { Window.Close(); } [HarmonyPrefix] [HarmonyPatch("Update")] private static bool BeforeUpdate() { return !Window.HandleEscape(); } private static Sprite PawIcon() { if (!((Object)(object)s_paw != (Object)null)) { return s_paw = ShapeIcon.Create("BestiaryTracker_Paw", (float x, float y) => ShapeIcon.Ellipse(x, y, 64f, 42f, 30f, 25f) || ShapeIcon.Ellipse(x, y, 26f, 76f, 11f, 14f) || ShapeIcon.Ellipse(x, y, 49f, 96f, 11f, 15f) || ShapeIcon.Ellipse(x, y, 79f, 96f, 11f, 15f) || ShapeIcon.Ellipse(x, y, 102f, 76f, 11f, 14f)); } return s_paw; } private static string Fill(List<WindowEntry> entries) { //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) Achievement current = Bestiary.Current; PlayerStats obj = AchievementStats.StatsFor(current); Dictionary<string, float> dictionary = ((obj != null) ? obj.m_enemyStats[0] : null); Dictionary<string, CreatureInfo> creatures = Creatures(); int num = 0; CreatureInfo value2; foreach (CreatureInfo item in from name in Bestiary.Creatures(current) select (!creatures.TryGetValue(name, out value2)) ? Unknown(name) : value2 into c orderby c.Stage, Localization.instance.Localize(c.Name) select c) { float value = 0f; bool flag = dictionary != null && dictionary.TryGetValue(item.Name, out value) && value >= 1f; if (flag) { num++; } if (!flag || BestiaryTrackerPlugin.ShowSlain.Value) { bool flag2 = flag || BestiaryTrackerPlugin.ShowAll.Value || Stages.IsRevealed(item.Stage); string text = (((int)item.Biomes != 0) ? ("Lives in " + Stages.BiomeName(Stages.Earliest(item.Biomes))) : "Found in special places"); entries.Add(new WindowEntry { Icon = (((Object)(object)item.Trophy != (Object)null) ? item.Trophy : PawIcon()), Name = Localization.instance.Localize(item.Name), Description = (flag ? string.Format("Slain {0:0} time{1}", value, (value >= 2f) ? "s" : "") : (text + "\n<i>Not slain yet</i>")), State = ((!flag) ? (flag2 ? EntryState.Missing : EntryState.Hidden) : EntryState.Done) }); } } int count = Bestiary.Creatures(current).Count; string arg = (((Object)(object)current != (Object)null) ? Localization.instance.Localize(current.m_name) : "Bestiary"); return $"{arg} {num} / {count}"; } private static CreatureInfo Unknown(string name) { return new CreatureInfo { Name = name, Stage = StageOf(name, (Biome)0) }; } private static Dictionary<string, CreatureInfo> Creatures() { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Invalid comparison between Unknown and I4 if (s_creatures != null && (Object)(object)s_scene == (Object)(object)ZNetScene.instance) { return s_creatures; } s_scene = ZNetScene.instance; s_creatures = new Dictionary<string, CreatureInfo>(); if ((Object)(object)s_scene == (Object)null) { return s_creatures; } Dictionary<string, Biome> dictionary = new Dictionary<string, Biome>(); SpawnSystemList[] array = Resources.FindObjectsOfTypeAll<SpawnSystemList>(); for (int i = 0; i < array.Length; i++) { foreach (SpawnData spawner in array[i].m_spawners) { if (!((Object)(object)spawner?.m_prefab == (Object)null) && spawner.m_enabled) { dictionary.TryGetValue(((Object)spawner.m_prefab).name, out var value); dictionary[((Object)spawner.m_prefab).name] = (Biome)(value | spawner.m_biome); } } } foreach (GameObject prefab in s_scene.m_prefabs) { Character val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Character>() : null); if ((Object)(object)val == (Object)null) { continue; } if (!s_creatures.TryGetValue(val.m_name, out var value2)) { Dictionary<string, CreatureInfo> dictionary2 = s_creatures; string name = val.m_name; CreatureInfo obj = new CreatureInfo { Name = val.m_name }; value2 = obj; dictionary2[name] = obj; } if (dictionary.TryGetValue(((Object)prefab).name, out var value3)) { CreatureInfo creatureInfo = value2; creatureInfo.Biomes |= value3; } if (!((Object)(object)value2.Trophy == (Object)null)) { continue; } CharacterDrop component = prefab.GetComponent<CharacterDrop>(); if (component == null) { continue; } foreach (Drop drop in component.m_drops) { ItemDrop val2 = (((Object)(object)drop.m_prefab != (Object)null) ? drop.m_prefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 != (Object)null && (int)val2.m_itemData.m_shared.m_itemType == 13) { value2.Trophy = val2.m_itemData.GetIcon(); break; } } } foreach (CreatureInfo value4 in s_creatures.Values) { value4.Stage = StageOf(value4.Name, value4.Biomes); } return s_creatures; } private static Stage StageOf(string name, Biome biomes) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (FixedStages.TryGetValue(name, out var value)) { return value; } if (name.StartsWith("$enemy_aspect_") || name.StartsWith("$enemy_frozenking")) { return Stage.DeepNorth; } if ((int)biomes != 0) { return Stages.Earliest(biomes); } return Stage.Plains; } } [HarmonyPatch] internal static class Patches { private static readonly FieldInfo HudsField = AccessTools.Field(typeof(EnemyHud), "m_huds"); private static EnemyHud s_hudOwner; private static IDictionary s_huds; private static IDictionary Huds(EnemyHud hud) { if ((Object)(object)hud != (Object)(object)s_hudOwner) { s_hudOwner = hud; s_huds = (IDictionary)HudsField.GetValue(hud); } return s_huds; } [HarmonyPrefix] [HarmonyPatch(typeof(EnemyHud), "ShowHud")] private static void BeforeShowHud(EnemyHud __instance, Character c, out bool __state) { __state = BestiaryTrackerPlugin.NameMarker.Value && (Object)(object)c != (Object)null && !Huds(__instance).Contains(c); } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyHud), "ShowHud")] private static void AfterShowHud(EnemyHud __instance, Character c, bool __state) { if (!__state || !BestiaryTrackerPlugin.NameMarker.Value || c.IsPlayer() || c.IsTamed()) { return; } Achievement current = Bestiary.Current; if (Bestiary.Counts(current, c.m_name) && !Bestiary.IsSlain(current, c.m_name)) { TextMeshProUGUI value = Traverse.Create(Huds(__instance)[c]).Field("m_name").GetValue<TextMeshProUGUI>(); if ((Object)(object)value != (Object)null) { ((TMP_Text)value).text = ((TMP_Text)value).text + " " + BestiaryTrackerPlugin.MarkerText.Value; } } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerProfile), "IncrementStatEnemy")] private static void BeforeKill(PlayerProfile __instance, string name, out bool __state) { Achievement current = Bestiary.Current; Game instance = Game.instance; __state = __instance == ((instance != null) ? instance.GetPlayerProfile() : null) && Bestiary.Counts(current, name) && !Bestiary.IsSlain(current, name); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerProfile), "IncrementStatEnemy")] private static void AfterKill(string name, bool __state) { Achievement current = Bestiary.Current; if (__state && BestiaryTrackerPlugin.KillMessage.Value && Bestiary.IsSlain(current, name) && !((Object)(object)Player.m_localPlayer == (Object)null)) { string text = Localization.instance.Localize(name); string text2 = Localization.instance.Localize(current.m_name); ((Character)Player.m_localPlayer).Message((MessageType)1, $"New creature slain: {text} ({text2}: {Bestiary.SlainCount(current)} / {Bestiary.Creatures(current).Count})", 0, (Sprite)null, false); } } } [BepInPlugin("com.koendertjh.bestiarytracker", "BestiaryTracker", "1.0.0")] public class BestiaryTrackerPlugin : BaseUnityPlugin { public const string ModGuid = "com.koendertjh.bestiarytracker"; public const string ModName = "BestiaryTracker"; public const string ModVersion = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> NameMarker; internal static ConfigEntry<string> MarkerText; internal static ConfigEntry<bool> KillMessage; internal static ConfigEntry<bool> ShowAll; internal static ConfigEntry<bool> ShowSlain; private Harmony _harmony; private void Awake() { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; NameMarker = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "NameMarker", true, "Creatures you haven't slain yet get a marker after their name, above their health bar."); MarkerText = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "MarkerText", "<color=#ffb347>(not slain)</color>", "The marker. Rich text is allowed."); KillMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "KillMessage", true, "Slaying a new kind of creature shows a message with your progress."); ShowAll = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Bestiary", "ShowAll", false, "Show every creature in the Bestiary right away. Off = creatures of a biome show once you defeated the boss before it; later ones show as '?'."); ShowSlain = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Bestiary", "ShowSlain", true, "Also list the creatures you have already slain. Off = only the missing ones."); _harmony = new Harmony("com.koendertjh.bestiarytracker"); _harmony.PatchAll(typeof(BestiaryTrackerPlugin).Assembly); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class PluginInfo { public const string Version = "1.0.0"; } }