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 Utangard v1.4.0
plugins/Utangard/Utangard.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Ezomic.Core; using HarmonyLib; 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.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("Thijssen Software")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 Robbin Thijssen")] [assembly: AssemblyDescription("Outside the fence: a biome you have not earned will not sustain you.")] [assembly: AssemblyFileVersion("1.4.0.0")] [assembly: AssemblyInformationalVersion("1.4.0+fb613c5505482ae4557e77d64c651dd8f0eb6ece")] [assembly: AssemblyProduct("Utangard")] [assembly: AssemblyTitle("Utangard")] [assembly: AssemblyVersion("1.4.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 Utangard { internal static class BiomeGate { private static readonly Vector2[] Compass = (Vector2[])(object)new Vector2[8] { new Vector2(1f, 0f), new Vector2(0.7071f, 0.7071f), new Vector2(0f, 1f), new Vector2(-0.7071f, 0.7071f), new Vector2(-1f, 0f), new Vector2(-0.7071f, -0.7071f), new Vector2(0f, -1f), new Vector2(0.7071f, -0.7071f) }; private static Vector3 _sampledAt; private static float _sampledMargin = -1f; private static readonly List<string> _sampledKeys = new List<string>(2); private static readonly List<Biome> _sampledBiomes = new List<Biome>(2); private const float ResampleDistance = 0.25f; public static string GatingKey(Player player) { Biome biome; return GatingKey(player, out biome); } public static string GatingKey(Player player, out Biome biome) { //IL_0044: 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) //IL_004a: 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_0060: Expected I4, but got Unknown biome = (Biome)0; if ((Object)(object)player == (Object)null || !UtangardConfig.Enabled.Value) { return null; } if ((Object)(object)player != (Object)(object)Player.m_localPlayer) { return null; } if (!Seams.PenaltyIsEscapable()) { return null; } ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return null; } Biome currentBiome = player.GetCurrentBiome(); string text = UtangardConfig.RequiredKeyFor(currentBiome); if (text != null && !Earned(instance, text)) { biome = (Biome)(int)currentBiome; return text; } return NearbyGatingKey(player, instance, out biome); } public static bool RulingBiomes(Player player, List<Biome> into) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) into.Clear(); if ((Object)(object)player == (Object)null || !UtangardConfig.Enabled.Value) { return false; } if ((Object)(object)player != (Object)(object)Player.m_localPlayer) { return false; } if (!Seams.PenaltyIsEscapable()) { return false; } ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return false; } Biome currentBiome = player.GetCurrentBiome(); string text = UtangardConfig.RequiredKeyFor(currentBiome); if (text != null && !Earned(instance, text)) { into.Add(currentBiome); } if (SampleMargin(player)) { for (int i = 0; i < _sampledKeys.Count; i++) { if (!into.Contains(_sampledBiomes[i]) && !Earned(instance, _sampledKeys[i])) { into.Add(_sampledBiomes[i]); } } } return into.Count > 0; } public static bool IsWithered(Player player) { return GatingKey(player) != null; } public static string BlockersHere(Player player) { if (!UtangardConfig.GateOnGroup.Value) { return null; } string text = GatingKey(player); if (text != null) { return Progression.BlockersFor(text, excludeSelf: true); } return null; } public static bool Earned(ZoneSystem zone, string key) { if (!UtangardConfig.GateOnGroup.Value) { return zone.GetGlobalKey(key); } return Progression.GroupHasKey(key); } private static string NearbyGatingKey(Player player, ZoneSystem zone, out Biome biome) { biome = (Biome)0; if (!SampleMargin(player)) { return null; } return FirstUnearned(zone, out biome); } private static bool SampleMargin(Player player) { //IL_001b: 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_0045: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_00a6: 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_00ad: 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_00d9: Unknown result type (might be due to invalid IL or missing references) float value = UtangardConfig.BorderMargin.Value; if (value <= 0f) { return false; } Vector3 position = ((Component)player).transform.position; if (value == _sampledMargin) { Vector3 val = position - _sampledAt; if (((Vector3)(ref val)).sqrMagnitude < 0.0625f) { return true; } } _sampledAt = position; _sampledMargin = value; _sampledKeys.Clear(); _sampledBiomes.Clear(); for (int i = 0; i < Compass.Length; i++) { Biome val2 = Heightmap.FindBiome(new Vector3(position.x + Compass[i].x * value, position.y, position.z + Compass[i].y * value)); string text = UtangardConfig.RequiredKeyFor(val2); if (text != null && !_sampledBiomes.Contains(val2)) { _sampledKeys.Add(text); _sampledBiomes.Add(val2); } } return true; } private static string FirstUnearned(ZoneSystem zone, out Biome biome) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected I4, but got Unknown for (int i = 0; i < _sampledKeys.Count; i++) { if (!Earned(zone, _sampledKeys[i])) { biome = (Biome)(int)_sampledBiomes[i]; return _sampledKeys[i]; } } biome = (Biome)0; return null; } } internal static class BlockedEffects { private const string GuardianPrefix = "GP_"; private static readonly HashSet<int> Blocked = new HashSet<int>(); private static bool _built; public static void Rebuild() { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return; } Blocked.Clear(); foreach (GameObject item in instance.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null) { StatusEffect consumeStatusEffect = component.m_itemData.m_shared.m_consumeStatusEffect; if ((Object)(object)consumeStatusEffect != (Object)null) { Add(consumeStatusEffect); } } } foreach (StatusEffect statusEffect in instance.m_StatusEffects) { if (!((Object)(object)statusEffect == (Object)null) && ((Object)statusEffect).name != null && ((Object)statusEffect).name.StartsWith("GP_")) { Add(statusEffect); } } if (UtangardConfig.BlockRested.Value) { Blocked.Add(SEMan.s_statusEffectRested); Blocked.Add(SEMan.s_statusEffectResting); } foreach (string alsoBlockName in UtangardConfig.AlsoBlockNames) { Blocked.Add(StringExtensionMethods.GetStableHashCode(alsoBlockName)); } foreach (string neverBlockName in UtangardConfig.NeverBlockNames) { Blocked.Remove(StringExtensionMethods.GetStableHashCode(neverBlockName)); } _built = true; UtangardPlugin.Log.LogInfo((object)("Buff set rebuilt: " + Blocked.Count + " status effects.")); if (UtangardConfig.LogBlockedEffects.Value) { LogNames(instance); } } private static void Add(StatusEffect effect) { if (!UtangardConfig.NeverBlockNames.Contains(((Object)effect).name)) { Blocked.Add(effect.NameHash()); } } public static bool IsBlocked(StatusEffect effect) { if (!_built || (Object)(object)effect == (Object)null) { return false; } if (effect is UtangardMarker || effect is SappedEffect) { return false; } return Blocked.Contains(effect.NameHash()); } public static bool IsBlockedHash(int nameHash) { if (!_built) { return false; } if (nameHash == UtangardEffectsRegistry.MarkerHash) { return false; } if (nameHash == UtangardEffectsRegistry.SappedHash) { return false; } return Blocked.Contains(nameHash); } private static void LogNames(ObjectDB db) { List<string> list = new List<string>(); List<string> list2 = new List<string>(); foreach (StatusEffect statusEffect in db.m_StatusEffects) { if (!((Object)(object)statusEffect == (Object)null)) { (Blocked.Contains(statusEffect.NameHash()) ? list : list2).Add(((Object)statusEffect).name); } } list.Sort(); list2.Sort(); UtangardPlugin.Log.LogInfo((object)"Treated as buffs (blocked and drained):"); UtangardPlugin.Log.LogInfo((object)(" " + Join(list))); UtangardPlugin.Log.LogInfo((object)"Left alone:"); UtangardPlugin.Log.LogInfo((object)(" " + Join(list2))); } private static string Join(List<string> names) { if (names.Count == 0) { return "(none)"; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < names.Count; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(names[i]); } return stringBuilder.ToString(); } } internal static class BossAltars { private static bool _saidFailure; internal static string Unearned(Vector3 position) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!UtangardConfig.Enabled.Value || !UtangardConfig.BlockBossSummons.Value) { return null; } if (!Seams.PenaltyIsEscapable()) { return null; } ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return null; } string text = UtangardConfig.RequiredKeyFor(Heightmap.FindBiome(position)); if (text == null || BiomeGate.Earned(instance, text)) { return null; } return text; } [HarmonyPrefix] [HarmonyPatch(typeof(OfferingBowl), "InitiateSpawnBoss")] private static bool Refuse(OfferingBowl __instance) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return true; } string text = Unearned(((Component)__instance).transform.position); if (text == null) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, UtangardConfig.BossBlockedMessage.Value, 0, (Sprite)null, false); } if (UtangardConfig.Verbose.Value) { UtangardPlugin.Log.LogInfo((object)("Refused an offering at " + ((Object)__instance).name + ": its biome needs " + text + ", and the group has not earned it.")); } return false; } catch (Exception ex) { if (!_saidFailure) { _saidFailure = true; UtangardPlugin.Log.LogWarning((object)("Could not check a boss altar against the gate, so it is allowed: " + ex)); } return true; } } } internal static class BossDoors { private static bool _saidFailure; private static string _parsedFrom; private static readonly HashSet<string> Keys = new HashSet<string>(StringComparer.OrdinalIgnoreCase); [HarmonyPrefix] [HarmonyPatch(typeof(Door), "Interact")] private static bool RefuseInteract(Door __instance, Humanoid __0, bool __1, ref bool __result) { if (__1) { return true; } if (!Refused(__instance, __0)) { return true; } __result = true; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Door), "UseItem")] private static bool RefuseUseItem(Door __instance, Humanoid __0, ItemData __1, ref bool __result) { if ((Object)(object)__instance == (Object)null || __1 == null || __1.m_shared == null || (Object)(object)__instance.m_keyItem == (Object)null) { return true; } if (__1.m_shared.m_name != __instance.m_keyItem.m_itemData.m_shared.m_name) { return true; } if (!Refused(__instance, __0)) { return true; } __result = true; return false; } [HarmonyPostfix] [HarmonyPatch(typeof(ZNetScene), "Awake")] private static void ReportGuarded(ZNetScene __instance) { try { if ((Object)(object)__instance == (Object)null || __instance.m_prefabs == null || string.IsNullOrEmpty((UtangardConfig.BossDoorKeys.Value ?? "").Trim())) { return; } List<string> list = new List<string>(); Door val = default(Door); foreach (GameObject prefab in __instance.m_prefabs) { if (!((Object)(object)prefab == (Object)null) && prefab.TryGetComponent<Door>(ref val) && !((Object)(object)val.m_keyItem == (Object)null) && Guarded(val.m_keyItem)) { list.Add(((Object)prefab).name + " (" + ((Object)((Component)val.m_keyItem).gameObject).name + ")"); } } if (list.Count > 0) { UtangardPlugin.Log.LogInfo((object)("Boss doors kept sealed in a locked biome: " + string.Join(", ", list.ToArray()))); } else { UtangardPlugin.Log.LogWarning((object)("BossDoorKeys (" + UtangardConfig.BossDoorKeys.Value + ") matches no door in this world, so no boss door is guarded.")); } } catch (Exception ex) { UtangardPlugin.Log.LogWarning((object)("Could not list the boss doors: " + ex.Message)); } } private static bool Refused(Door door, Humanoid who) { //IL_006b: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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) try { if ((Object)(object)door == (Object)null || (Object)(object)door.m_keyItem == (Object)null) { return false; } if (!Guarded(door.m_keyItem)) { return false; } ZNetView val = default(ZNetView); if (!((Component)door).TryGetComponent<ZNetView>(ref val) || !val.IsValid()) { return false; } if (val.GetZDO().GetInt(ZDOVars.s_state, 0) != 0) { return false; } string text = BossAltars.Unearned(((Component)door).transform.position); if (text == null) { return false; } door.m_lockedEffects.Create(((Component)door).transform.position, ((Component)door).transform.rotation, (Transform)null, 1f, -1, default(ZDOID)); if ((Object)(object)who != (Object)null && (Object)(object)who == (Object)(object)Player.m_localPlayer) { ((Character)who).Message((MessageType)2, UtangardConfig.BossDoorBlockedMessage.Value, 0, (Sprite)null, false); } if (UtangardConfig.Verbose.Value) { UtangardPlugin.Log.LogInfo((object)("Kept " + ((Object)door).name + " shut: its biome needs " + text + ", and the group has not earned it.")); } return true; } catch (Exception ex) { if (!_saidFailure) { _saidFailure = true; UtangardPlugin.Log.LogWarning((object)("Could not check a boss door against the gate, so it opens: " + ex)); } return false; } } private static bool Guarded(ItemDrop keyItem) { string text = UtangardConfig.BossDoorKeys.Value ?? ""; if (!string.Equals(text, _parsedFrom, StringComparison.Ordinal)) { Keys.Clear(); string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length > 0) { Keys.Add(text2); } } _parsedFrom = text; } if (Keys.Count > 0) { return Keys.Contains(((Object)((Component)keyItem).gameObject).name); } return false; } } internal static class CompendiumPanel { private sealed class Cell { public Biome Biome; public GameObject Go; public Image Edge; public RectTransform Face; public TMP_Text Label; public float EdgeWidth = -1f; } private sealed class Box { public TMP_Text Percent; public RectTransform Fill; public TMP_Text State; } [HarmonyPatch] internal static class Show { [HarmonyTargetMethod] private static MethodBase Target() { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(TextsDialog))) { if (!(declaredMethod.Name != "ShowText")) { ParameterInfo[] parameters = declaredMethod.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(TextInfo)) { return declaredMethod; } } } UtangardPlugin.Log.LogError((object)"TextsDialog has no ShowText(TextInfo) any more - the Utangard page in the compendium stays the plain text version."); return null; } [HarmonyPostfix] private static void Postfix(TextsDialog __instance, TextInfo __0) { Shown(__instance, __0); } } private static readonly Color PanelFace = Rgb(2038292); private static readonly Color PanelEdge = Rgb(5917238); private static readonly Color BodyText = Rgb(15129282); private static readonly Color Muted = Rgb(10720906); private static readonly Color Orange = Rgb(16753920); private static readonly Color OpenText = Rgb(8831614); private static readonly Color OpenEdge = Rgb(5995087); private static readonly Color LockedText = Rgb(13794926); private static readonly Color LockedEdge = Rgb(7227968); private static readonly Color BoxEdge = Rgb(4865326); private static readonly Color Track = Rgb(3813673); private static readonly Color FightingFill = Rgb(12551498); private static readonly Color DiscoveryFill = Rgb(8232888); private const float BodySize = 14f; private const float TitleSize = 20f; private const float SmallSize = 13f; private const float StripSize = 12f; private const float LineHeight = 1.55f; private const float RefreshSeconds = 1f; internal static TextInfo Page; private static TextsDialog _dialog; private static GameObject _root; private static RectTransform _host; private static LayoutElement _floor; private static float _fitScale = -1f; private static Vector2 _fitSize; private static float _fitPixels = -1f; private static float _pixelsPerUnit = 1f; private static readonly List<RectTransform> Rims = new List<RectTransform>(); private static TextsDialog _failedFor; private static Biome _selected = (Biome)0; private static float _nextRefresh; private static TMP_Text _proto; private static float _naturalPerEm; private static readonly List<Cell> Cells = new List<Cell>(); private static TMP_Text _title; private static TMP_Text _waiting; private static TMP_Text _rules; private static GameObject _barsGap; private static GameObject _bars; private static GameObject _rulesGap; private static Box _fighting; private static Box _discovery; private static void Shown(TextsDialog dialog, TextInfo text) { //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) if (Page == null || text != Page || !UtangardConfig.ShowCompendiumPanel.Value) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } } else { if ((Object)(object)dialog == (Object)null || dialog == _failedFor) { return; } try { if ((Object)(object)_root == (Object)null || _dialog != dialog) { Build(dialog); } _selected = Default(); _root.transform.SetAsLastSibling(); _root.SetActive(true); Fit(); Draw(); dialog.m_textArea.text = ""; _nextRefresh = Time.unscaledTime + 1f; } catch (Exception e) { Abandon(dialog, e); } } } internal static void Tick() { if ((Object)(object)_root == (Object)null || !_root.activeInHierarchy) { return; } try { int num = 0; if (ZInput.IsExclusiveGamepadActive()) { if (ZInput.GetButtonDown("JoyDPadLeft")) { num = -1; } else if (ZInput.GetButtonDown("JoyDPadRight")) { num = 1; } } if (num != 0) { Step(num); } else if (Time.unscaledTime < _nextRefresh) { return; } _nextRefresh = Time.unscaledTime + 1f; Fit(); Draw(); } catch (Exception e) { Abandon(_dialog, e); } } private static void Select(Biome biome) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root == (Object)null) { return; } try { _selected = biome; Draw(); } catch (Exception e) { Abandon(_dialog, e); } } private static void Step(int step) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) int num = -1; for (int i = 0; i < Cells.Count; i++) { if (Cells[i].Biome == _selected) { num = i; } } for (int j = 0; j < Cells.Count; j++) { num += step; if (num < 0 || num >= Cells.Count) { break; } if (Cells[num].Go.activeSelf) { _selected = Cells[num].Biome; break; } } } private static Biome Default() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0021: 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) Biome val = Foothold.Frontier(); if ((int)val != 0) { return val; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Biome currentBiome = localPlayer.GetCurrentBiome(); if (Listed(currentBiome)) { return currentBiome; } } return UtangardConfig.GateableBiomes[0]; } private static bool Listed(Biome biome) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (Array.IndexOf(UtangardConfig.GateableBiomes, biome) < 0) { return false; } if ((int)biome == 256) { return UtangardConfig.RequiredKeyFor(biome) != null; } return true; } private static void Abandon(TextsDialog dialog, Exception e) { _failedFor = dialog; UtangardPlugin.Log.LogError((object)("The Utangard compendium panel failed, so the page is back to plain text for this world. Nothing else is affected. " + e)); try { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; if ((Object)(object)dialog != (Object)null && (Object)(object)dialog.m_textArea != (Object)null && Page != null) { dialog.m_textArea.text = ((Localization.instance != null) ? Localization.instance.Localize(Page.m_text) : Page.m_text); } } catch (Exception ex) { UtangardPlugin.Log.LogError((object)("Could not put the Utangard text page back either: " + ex)); } } private static void Draw() { //IL_0022: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00d3: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) List<GateReport.Row> list = GateReport.Rows(); foreach (Cell cell in Cells) { bool flag = Listed(cell.Biome); SetActive(cell.Go, flag); if (flag) { GateReport.Row row = RowOf(list, cell.Biome); bool flag2 = row.Key == null || row.Open; bool flag3 = cell.Biome == _selected; SetText(cell.Label, GateReport.BiomeName(cell.Biome)); SetColor((Graphic)(object)cell.Label, flag3 ? Orange : (flag2 ? OpenText : LockedText)); SetColor((Graphic)(object)cell.Edge, flag3 ? Orange : (flag2 ? OpenEdge : LockedEdge)); SetEdgeWidth(cell, flag3 ? 2f : 1f); } } GateReport.Row row2 = RowOf(list, _selected); bool num = row2.Key != null && !row2.Open; SetText(_title, "The " + GateReport.BiomeName(_selected)); SetText(_waiting, Wrapped((list.Count == 0) ? "No world loaded yet." : GateReport.WaitingLine(row2))); bool flag4 = num && UtangardConfig.FootholdEnabled.Value; SetActive(_barsGap, flag4); SetActive(_bars, flag4); if (flag4) { DrawBars(Foothold.Read(_selected)); } bool warning = false; string text = (num ? Rules(flag4, out warning) : null); bool flag5 = !string.IsNullOrEmpty(text); SetActive(_rulesGap, flag5); SetActive(((Component)_rules).gameObject, flag5); if (flag5) { SetText(_rules, Wrapped(text)); SetColor((Graphic)(object)_rules, warning ? LockedText : Muted); } } private static void DrawBars(Foothold.Standing s) { int num = (s.FightingAvailable ? s.FightingPercent : 0); SetText(_fighting.Percent, s.FightingAvailable ? (num + "%") : "?"); SetFill(_fighting.Fill, (float)num / 100f); if (!UtangardConfig.BlockEating.Value || s.CanEat) { SetState(_fighting.State, "Eating allowed", good: true); } else if (!s.FightingAvailable) { SetState(_fighting.State, "Kills are not being counted", good: false); } else if (s.EatAtPercent > 100) { SetState(_fighting.State, "No eating here", good: false); } else { SetState(_fighting.State, "Eating at " + s.EatAtPercent + "%", good: false); } int num2 = (s.DiscoveryAvailable ? Mathf.FloorToInt(s.DiscoveryPercent) : 0); SetText(_discovery.Percent, s.DiscoveryAvailable ? (num2 + "%") : "?"); SetFill(_discovery.Fill, (float)num2 / 100f); if (UtangardConfig.HealthRegenMultiplier.Value >= 1f || s.CanHeal) { SetState(_discovery.State, "Healing allowed", good: true); } else if (!s.DiscoveryAvailable) { SetState(_discovery.State, "The map cannot be read", good: false); } else if (s.DiscoveryCounting) { SetState(_discovery.State, "Still reading your map", good: false); } else { SetState(_discovery.State, "Healing needs both full", good: false); } } private static string Rules(bool bars, out bool warning) { warning = !Seams.PenaltyIsEscapable(); if (warning) { return "Nothing is enforced right now. A game update moved the code that records boss kills, so the mod has stopped until it is updated."; } return GateReport.RulesLine(!bars && UtangardConfig.BlockEating.Value); } private static GateReport.Row RowOf(List<GateReport.Row> rows, Biome biome) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) foreach (GateReport.Row row in rows) { if (row.Biome == biome) { return row; } } return new GateReport.Row { Biome = biome, Open = true, SecondsLeft = -1L }; } private static void SetState(TMP_Text label, string text, bool good) { //IL_0012: 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) SetText(label, text); SetColor((Graphic)(object)label, good ? OpenText : Muted); } private static string Wrapped(string text) { return "<line-height=" + 1.55f.ToString(CultureInfo.InvariantCulture) + "em><noparse>" + text + "</noparse>"; } private static void SetText(TMP_Text label, string text) { if (label.text != text) { label.text = text; } } private static void SetColor(Graphic graphic, Color color) { //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_000f: Unknown result type (might be due to invalid IL or missing references) if (graphic.color != color) { graphic.color = color; } } private static void SetActive(GameObject go, bool active) { if (go.activeSelf != active) { go.SetActive(active); } } private static void SetFill(RectTransform fill, float amount) { //IL_0009: 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) amount = Mathf.Clamp01(amount); if (!Mathf.Approximately(fill.anchorMax.x, amount)) { fill.anchorMax = new Vector2(amount, 1f); } } private static void SetEdgeWidth(Cell cell, float width) { float num = Edge(width); if (!Mathf.Approximately(cell.EdgeWidth, num)) { cell.EdgeWidth = num; Inset(cell.Face, num); } } private static float Edge(float width) { return Mathf.Max(1f, Mathf.Round(width * _pixelsPerUnit)) / _pixelsPerUnit; } private static void Rim(RectTransform face) { Rims.Add(face); Inset(face, Edge(1f)); } private static void Build(TextsDialog dialog) { //IL_0042: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00e0: 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_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) Forget(); TMP_Text textArea = dialog.m_textArea; if ((Object)(object)textArea == (Object)null) { throw new InvalidOperationException("TextsDialog.m_textArea is not set."); } string passed; RectTransform val = Host(dialog, textArea, out passed); GameObject val2 = new GameObject("Utangard_Panel", new Type[1] { typeof(RectTransform) }); val2.SetActive(false); RectTransform val3 = (RectTransform)val2.transform; ((Transform)val3).SetParent((Transform)(object)val, false); _floor = val2.AddComponent<LayoutElement>(); _floor.ignoreLayout = true; _root = val2; _dialog = dialog; _host = val; Paint(val3, PanelEdge, raycast: true); RectTransform obj = Child("Face", (Transform)(object)val3); ((Component)obj).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; Rim(obj); Paint(obj, PanelFace, raycast: false); VerticalLayoutGroup obj2 = val2.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj2).padding = new RectOffset(1, 1, 1, 1); Stack(obj2, fillHeight: false); val2.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; GameObject obj3 = Object.Instantiate<GameObject>(((Component)textArea).gameObject, (Transform)(object)val3); ((Object)obj3).name = "Utangard_Label"; Strip(obj3); obj3.SetActive(false); _proto = obj3.GetComponent<TMP_Text>(); if ((Object)(object)_proto == (Object)null) { throw new InvalidOperationException("The compendium's text carried no TextMeshPro component."); } Prime(_proto); val2.SetActive(true); _naturalPerEm = Measure(val3); val2.AddComponent<CompendiumPanelTicker>(); RectTransform val4 = Child("Body", (Transform)(object)val3); ((Component)val4).gameObject.AddComponent<LayoutElement>().flexibleHeight = 0f; VerticalLayoutGroup obj4 = ((Component)val4).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj4).padding = new RectOffset(22, 22, 18, 18); Stack(obj4, fillHeight: false); _fitScale = -1f; Fit(); RectTransform val5 = Child("Biomes", (Transform)(object)val4); HorizontalLayoutGroup obj5 = ((Component)val5).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj5).spacing = 6f; Row(obj5, even: true); int num = 0; Biome[] gateableBiomes = UtangardConfig.GateableBiomes; foreach (Biome biome in gateableBiomes) { Cell cell = MakeCell(val5, biome); if (Sound(cell.Go, dialog)) { num++; } Cells.Add(cell); } Gap((Transform)(object)val4, 12f); _title = Label((Transform)(object)val4, 20f, Orange, (TextAlignmentOptions)257); Gap((Transform)(object)val4, 4f); _waiting = Label((Transform)(object)val4, 14f, Muted, (TextAlignmentOptions)257); _barsGap = Gap((Transform)(object)val4, 12f); RectTransform obj6 = Child("Bars", (Transform)(object)val4); HorizontalLayoutGroup obj7 = ((Component)obj6).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj7).spacing = 14f; Row(obj7, even: true); _bars = ((Component)obj6).gameObject; _fighting = MakeBox(obj6, "Fighting", FightingFill); _discovery = MakeBox(obj6, "Discovery", DiscoveryFill); _rulesGap = Gap((Transform)(object)val4, 12f); _rules = Label((Transform)(object)val4, 13f, Muted, (TextAlignmentOptions)257); CultureInfo invariantCulture = CultureInfo.InvariantCulture; Rect rect = val.rect; UtangardPlugin.Log.LogInfo((object)("Compendium panel built over '" + ((Object)val).name + "'" + ((passed.Length > 0) ? (" (past " + passed + ", sized by what is in it)") : "") + ", " + Mathf.RoundToInt(((Rect)(ref rect)).width) + " x " + Mathf.RoundToInt(((Rect)(ref rect)).height) + " at scale " + _fitScale.ToString("0.###", invariantCulture) + ", " + _pixelsPerUnit.ToString("0.###", invariantCulture) + " screen pixels to a unit, the compendium's own text at size " + textArea.fontSize.ToString("0.#", invariantCulture) + ", one line of text at " + _naturalPerEm.ToString("0.00", invariantCulture) + " em, " + num + " of " + Cells.Count + " biome buttons with vanilla's click sound.")); } private static void Fit() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //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_0080: 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_005f: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root == (Object)null || (Object)(object)_host == (Object)null || (Object)(object)_floor == (Object)null) { return; } float num = HostScale(_host); Rect rect = _host.rect; Vector2 size = ((Rect)(ref rect)).size; float num2 = PixelsPerUnit(_host); if (Mathf.Approximately(num, _fitScale) && size == _fitSize && Mathf.Approximately(num2, _fitPixels)) { return; } _fitScale = num; _fitSize = size; _fitPixels = num2; float num3 = ((num >= 0.99f) ? 1f : num); float num4 = 1f / num3; RectTransform val = (RectTransform)_root.transform; val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(0f, 1f); val.pivot = new Vector2(0f, 1f); ((Transform)val).localScale = new Vector3(num4, num4, 1f); val.anchoredPosition = Vector2.zero; val.SetSizeWithCurrentAnchors((Axis)0, size.x * num3); _floor.minHeight = Mathf.Max(0f, size.y * num3); _pixelsPerUnit = num2 * num4; foreach (RectTransform rim in Rims) { Inset(rim, Edge(1f)); } } private static float PixelsPerUnit(RectTransform rect) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null) { return 1f; } Canvas rootCanvas = componentInParent.rootCanvas; float x = ((Component)rootCanvas).transform.lossyScale.x; if (x <= 0f || rootCanvas.scaleFactor <= 0f) { return 1f; } float num = rootCanvas.scaleFactor * ((Transform)rect).lossyScale.x / x; if (!(num > 0.1f) || !(num < 20f)) { return 1f; } return num; } private static float HostScale(RectTransform host) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)host).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null) { return 1f; } float x = ((Component)componentInParent.rootCanvas).transform.lossyScale.x; if (x <= 0f) { return 1f; } float num = ((Transform)host).lossyScale.x / x; if (!(num > 0.2f) || !(num < 5f)) { return 1f; } return num; } private static bool Sound(GameObject button, TextsDialog dialog) { try { return CopySound(button, dialog); } catch (Exception ex) { UtangardPlugin.Log.LogWarning((object)("Compendium panel: the biome buttons stay silent. " + ex.Message)); return false; } } [MethodImpl(MethodImplOptions.NoInlining)] private static bool CopySound(GameObject button, TextsDialog dialog) { if ((Object)(object)dialog.m_elementPrefab == (Object)null) { return false; } ButtonSfx componentInChildren = dialog.m_elementPrefab.GetComponentInChildren<ButtonSfx>(true); if ((Object)(object)componentInChildren == (Object)null) { return false; } ButtonSfx obj = button.AddComponent<ButtonSfx>(); obj.m_sfxPrefab = componentInChildren.m_sfxPrefab; obj.m_sfxPrefabVibrationOnly = componentInChildren.m_sfxPrefabVibrationOnly; obj.m_selectSfxPrefab = componentInChildren.m_selectSfxPrefab; obj.m_selectSfxPrefabVibrationOnly = componentInChildren.m_selectSfxPrefabVibrationOnly; obj.m_enterSfxPrefab = componentInChildren.m_enterSfxPrefab; obj.m_enterSfxPrefabVibrationOnly = componentInChildren.m_enterSfxPrefabVibrationOnly; return true; } private unsafe static Cell MakeCell(RectTransform strip, Biome biome) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Child("Biome_" + ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString(), (Transform)(object)strip); Image val2 = Paint(val, LockedEdge, raycast: true); LayoutElement obj = ((Component)val).gameObject.AddComponent<LayoutElement>(); obj.minWidth = 0f; obj.preferredWidth = 0f; obj.flexibleWidth = 1f; VerticalLayoutGroup obj2 = ((Component)val).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj2).padding = new RectOffset(2, 2, 2, 2); Stack(obj2, fillHeight: true); RectTransform val3 = Child("Face", (Transform)(object)val); ((Component)val3).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; Paint(val3, PanelFace, raycast: false); TMP_Text val4 = Label((Transform)(object)val, 12f, OpenText, (TextAlignmentOptions)514); float num = Lead(12f); val4.margin = new Vector4(2f, 6f + num, 2f, 6f + num); Button obj3 = ((Component)val).gameObject.AddComponent<Button>(); ((Selectable)obj3).transition = (Transition)0; ((Selectable)obj3).targetGraphic = (Graphic)(object)val2; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)obj3).navigation = navigation; Biome chosen = biome; ((UnityEvent)obj3.onClick).AddListener((UnityAction)delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Select(chosen); }); Cell obj4 = new Cell { Biome = biome, Go = ((Component)val).gameObject, Edge = val2, Face = val3, Label = val4 }; SetEdgeWidth(obj4, 1f); return obj4; } private static Box MakeBox(RectTransform parent, string name, Color fill) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0086: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Child(name, (Transform)(object)parent); Paint(val, BoxEdge, raycast: false); LayoutElement obj = ((Component)val).gameObject.AddComponent<LayoutElement>(); obj.minWidth = 0f; obj.preferredWidth = 0f; obj.flexibleWidth = 1f; VerticalLayoutGroup obj2 = ((Component)val).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj2).padding = new RectOffset(11, 11, 11, 11); Stack(obj2, fillHeight: false); RectTransform obj3 = Child("Face", (Transform)(object)val); ((Component)obj3).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; Rim(obj3); Paint(obj3, PanelFace, raycast: false); RectTransform obj4 = Child("Head", (Transform)(object)val); HorizontalLayoutGroup obj5 = ((Component)obj4).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj5).spacing = 8f; Row(obj5, even: false); TMP_Text obj6 = Label((Transform)(object)obj4, 14f, BodyText, (TextAlignmentOptions)257); obj6.text = name; LayoutElement obj7 = ((Component)obj6).gameObject.AddComponent<LayoutElement>(); obj7.minWidth = 0f; obj7.flexibleWidth = 1f; TMP_Text val2 = Label((Transform)(object)obj4, 14f, BodyText, (TextAlignmentOptions)260); val2.textWrappingMode = (TextWrappingModes)0; Gap((Transform)(object)val, 6f); RectTransform val3 = Child("Track", (Transform)(object)val); Paint(val3, Track, raycast: false); LayoutElement obj8 = ((Component)val3).gameObject.AddComponent<LayoutElement>(); obj8.minHeight = 12f; obj8.preferredHeight = 12f; RectTransform val4 = Child("Fill", (Transform)(object)val3); val4.anchorMin = Vector2.zero; val4.anchorMax = new Vector2(0f, 1f); val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; Paint(val4, fill, raycast: false); Gap((Transform)(object)val, 6f); TMP_Text state = Label((Transform)(object)val, 13f, Muted, (TextAlignmentOptions)257); return new Box { Percent = val2, Fill = val4, State = state }; } private static RectTransform Host(TextsDialog dialog, TMP_Text donor, out string passed) { Transform parent = donor.transform.parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("The compendium's text has no parent to draw over."); } passed = ""; while (!Clips(val) && FollowsContent(val)) { Transform parent2 = ((Transform)val).parent; RectTransform val2 = (RectTransform)(object)((parent2 is RectTransform) ? parent2 : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val2 == (Object)(object)((Component)dialog).transform || !((Transform)val2).IsChildOf(((Component)dialog).transform) || Brings((Transform)(object)val, (Transform)(object)val2, (Component)(object)dialog.m_textAreaTopic) || Brings((Transform)(object)val, (Transform)(object)val2, (Component)(object)dialog.m_rightScrollbar) || Brings((Transform)(object)val, (Transform)(object)val2, (Component)(object)dialog.m_listRoot)) { break; } passed = passed + ((passed.Length > 0) ? ", '" : "'") + ((Object)val).name + "'"; val = val2; } return val; } private static bool FollowsContent(RectTransform rect) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) ContentSizeFitter[] components = ((Component)rect).GetComponents<ContentSizeFitter>(); foreach (ContentSizeFitter val in components) { if (((Behaviour)val).enabled && (int)val.verticalFit != 0) { return true; } } ScrollRect[] componentsInParent = ((Component)rect).GetComponentsInParent<ScrollRect>(true); for (int i = 0; i < componentsInParent.Length; i++) { if ((Object)(object)componentsInParent[i].content == (Object)(object)rect) { return true; } } Transform parent = ((Transform)rect).parent; if ((Object)(object)parent == (Object)null) { return false; } HorizontalOrVerticalLayoutGroup[] components2 = ((Component)parent).GetComponents<HorizontalOrVerticalLayoutGroup>(); foreach (HorizontalOrVerticalLayoutGroup val2 in components2) { if (((Behaviour)val2).enabled && val2.childControlHeight) { return true; } } return false; } private static bool Clips(RectTransform rect) { RectMask2D component = ((Component)rect).GetComponent<RectMask2D>(); if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled) { return true; } Mask component2 = ((Component)rect).GetComponent<Mask>(); if ((Object)(object)component2 != (Object)null) { return ((Behaviour)component2).enabled; } return false; } private static bool Brings(Transform from, Transform to, Component part) { if ((Object)(object)part != (Object)null && part.transform.IsChildOf(to)) { return !part.transform.IsChildOf(from); } return false; } private static void Strip(GameObject go) { for (int i = 0; i < 2; i++) { Component[] components = go.GetComponents<Component>(); foreach (Component val in components) { if (!((Object)(object)val == (Object)null) && !(val is RectTransform) && !(val is CanvasRenderer) && !(val is TMP_Text)) { Object.DestroyImmediate((Object)(object)val); } } } for (int num = go.transform.childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)go.transform.GetChild(num)).gameObject); } } private static void Prime(TMP_Text label) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) label.text = ""; label.enableAutoSizing = false; label.richText = true; ((Graphic)label).raycastTarget = false; label.overrideColorTags = false; label.enableVertexGradient = false; label.textWrappingMode = (TextWrappingModes)1; label.overflowMode = (TextOverflowModes)0; label.margin = Vector4.zero; label.lineSpacing = 0f; label.paragraphSpacing = 0f; label.alignment = (TextAlignmentOptions)257; ((Graphic)label).color = BodyText; } private static float Measure(RectTransform parent) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(((Component)_proto).gameObject, (Transform)(object)parent); try { val.SetActive(true); TMP_Text component = val.GetComponent<TMP_Text>(); component.fontSize = 100f; component.textWrappingMode = (TextWrappingModes)0; float num = component.GetPreferredValues("Hg").y / 100f; if (num > 0.6f && num < 2.5f) { return num; } UtangardPlugin.Log.LogWarning((object)("Compendium panel: measured a line of " + num + " em, which cannot be right; spacing the text as if it were 1.2.")); } finally { Object.DestroyImmediate((Object)(object)val); } return 1.2f; } private static float Lead(float size) { return Mathf.Max(0f, (1.55f - _naturalPerEm) * size * 0.5f); } private static TMP_Text Label(Transform parent, float size, Color color, TextAlignmentOptions align) { //IL_002f: 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) //IL_0050: Unknown result type (might be due to invalid IL or missing references) GameObject obj = Object.Instantiate<GameObject>(((Component)_proto).gameObject, parent); ((Object)obj).name = "Text"; obj.SetActive(true); TMP_Text component = obj.GetComponent<TMP_Text>(); component.fontSize = size; ((Graphic)component).color = color; component.alignment = align; float num = Lead(size); component.margin = new Vector4(0f, num, 0f, num); return component; } private static RectTransform Child(string name, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002c: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(parent, false); return val; } private static Image Paint(RectTransform rect, Color color, bool raycast) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)rect).gameObject.AddComponent<Image>(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = raycast; return obj; } private static void Inset(RectTransform rect, float by) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.pivot = new Vector2(0.5f, 0.5f); rect.offsetMin = new Vector2(by, by); rect.offsetMax = new Vector2(0f - by, 0f - by); } private static GameObject Gap(Transform parent, float height) { RectTransform obj = Child("Gap", parent); LayoutElement obj2 = ((Component)obj).gameObject.AddComponent<LayoutElement>(); obj2.minHeight = height; obj2.preferredHeight = height; return ((Component)obj).gameObject; } private static void Stack(VerticalLayoutGroup group, bool fillHeight) { ((HorizontalOrVerticalLayoutGroup)group).spacing = 0f; ((LayoutGroup)group).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)group).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)group).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)group).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)group).childForceExpandHeight = fillHeight; } private static void Row(HorizontalLayoutGroup group, bool even) { ((LayoutGroup)group).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)group).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)group).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)group).childForceExpandWidth = even; ((HorizontalOrVerticalLayoutGroup)group).childForceExpandHeight = even; } private static void Forget() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; _dialog = null; _host = null; _floor = null; _fitScale = -1f; _fitPixels = -1f; Rims.Clear(); _proto = null; _title = null; _waiting = null; _rules = null; _bars = null; _barsGap = null; _rulesGap = null; _fighting = null; _discovery = null; Cells.Clear(); } private static Color Rgb(int hex) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) return new Color((float)((hex >> 16) & 0xFF) / 255f, (float)((hex >> 8) & 0xFF) / 255f, (float)(hex & 0xFF) / 255f, 1f); } } internal sealed class CompendiumPanelTicker : MonoBehaviour { private void Update() { CompendiumPanel.Tick(); } } internal static class DefeatKeys { private static readonly Dictionary<string, List<string>> Setters = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, string> Names = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static ZNetScene _scannedScene; private static void Scan() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance == _scannedScene) { return; } Setters.Clear(); Names.Clear(); _scannedScene = instance; List<GameObject> prefabs = instance.m_prefabs; if (prefabs == null) { return; } Character val2 = default(Character); for (int i = 0; i < prefabs.Count; i++) { GameObject val = prefabs[i]; if ((Object)(object)val == (Object)null || !val.TryGetComponent<Character>(ref val2)) { continue; } string defeatSetGlobalKey = val2.m_defeatSetGlobalKey; if (!string.IsNullOrEmpty(defeatSetGlobalKey)) { if (!Setters.TryGetValue(defeatSetGlobalKey, out var value)) { value = new List<string>(1); Setters[defeatSetGlobalKey] = value; } value.Add(((Object)val).name); if (!string.IsNullOrEmpty(val2.m_name) && (!Names.ContainsKey(defeatSetGlobalKey) || val2.m_boss)) { Names[defeatSetGlobalKey] = val2.m_name; } } } } public static string NameFor(string key) { if (string.IsNullOrEmpty(key)) { return null; } Scan(); if (!Names.TryGetValue(key, out var value)) { return null; } Localization instance = Localization.instance; if (instance == null) { return null; } string text = instance.Localize(value); if (!string.IsNullOrEmpty(text) && !(text == value)) { return text; } return null; } public static bool IsSetByACreature(string key) { if (string.IsNullOrEmpty(key)) { return false; } Scan(); return Setters.ContainsKey(key); } public unsafe static void Report() { //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) Scan(); if (Setters.Count == 0) { UtangardPlugin.Log.LogInfo((object)"No prefab scene to read defeat keys from yet - gate keys unverified."); return; } if (UtangardConfig.LogDefeatKeys.Value) { LogAll(); } List<string> list = new List<string>(); Biome[] gateableBiomes = UtangardConfig.GateableBiomes; for (int i = 0; i < gateableBiomes.Length; i++) { Biome biome = gateableBiomes[i]; string text = UtangardConfig.RequiredKeyFor(biome); if (text != null && !Setters.ContainsKey(text)) { list.Add(((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() + " -> '" + text + "'"); } } if (list.Count == 0) { UtangardPlugin.Log.LogInfo((object)"Gate keys verified against this world's creatures: every gated biome names a key something here actually sets on death."); return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("These gate rows name a key no creature in this world sets: "); for (int j = 0; j < list.Count; j++) { if (j > 0) { stringBuilder.Append(", "); } stringBuilder.Append(list[j]); } stringBuilder.Append(". That is fine if the key comes from somewhere else - another mod, or a location - and is a permanently shut biome if it is a typo, which looks exactly the same from inside the game. The keys creatures here do set are: ").Append(BossKeys()); UtangardPlugin.Log.LogWarning((object)stringBuilder.ToString()); } private static void LogAll() { UtangardPlugin.Log.LogInfo((object)("Defeat keys set by creatures in this world (" + Setters.Count + "):")); List<string> list = new List<string>(Setters.Keys); list.Sort(StringComparer.OrdinalIgnoreCase); foreach (string item in list) { UtangardPlugin.Log.LogInfo((object)(" " + item + " <- " + string.Join(", ", Setters[item].ToArray()))); } } private static string BossKeys() { List<string> list = new List<string>(); foreach (string key in Setters.Keys) { if (key.StartsWith("defeated_", StringComparison.OrdinalIgnoreCase)) { list.Add(key); } } list.Sort(StringComparer.OrdinalIgnoreCase); if (list.Count != 0) { return string.Join(", ", list.ToArray()); } return "(none begin with 'defeated_'; turn on Diagnostics.LogDefeatKeys for the full list)"; } } internal static class DevConsole { [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class Hook { private static void Postfix() { Register(); } } private sealed class DeathCount { internal int AsOwner; internal int NotOwner; internal int BossCredit; } private sealed class Creature { internal string Prefab; internal string Token; internal float Health; internal bool Unconditional; internal readonly List<string> Rows = new List<string>(); } [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__OnCommand; } private static bool _registered; private static readonly Dictionary<string, DeathCount> Deaths = new Dictionary<string, DeathCount>(StringComparer.OrdinalIgnoreCase); private const float DeathsReach = 40f; private static readonly Biome[] Order; private static readonly string[] LeftOut; private static void Register() { //IL_003d: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (!_registered) { _registered = true; object obj = <>O.<0>__OnCommand; if (obj == null) { ConsoleEvent val = OnCommand; <>O.<0>__OnCommand = val; obj = (object)val; } new ConsoleCommand("utangard", "utangard foothold | biomes | creatures | deaths [<creature> [since <notowner>]] - your foothold in each locked biome, the raw numbers behind it, and which machine ran a creature's death", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); RegisterTest(); } } private static void RegisterTest() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand("utangardtest", "utangardtest kills <creature> <count> - set how many of that creature Utangard has counted you killing in this world, for tests", new ConsoleEventFailable(OnTest), true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static object OnTest(ConsoleEventArgs args) { Terminal context = args.Context; if ((Object)(object)context == (Object)null) { return "no console to answer in"; } if (((args.Length > 1) ? args[1].ToLowerInvariant() : "") == "kills") { return SetKills(context, args); } context.AddString("utangardtest kills <creature> <count> - set this character's count of that creature in this world, as if it had killed that many. 0 clears it."); context.AddString("<creature> is a prefab name from a points line: JotunWarrior, Troll, Greydwarf..."); return true; } private static object SetKills(Terminal term, ConsoleEventArgs args) { if (args.Length < 4) { return "utangardtest kills <creature> <count>"; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return "no world loaded yet"; } if (!int.TryParse(args[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 0) { return "'" + args[3] + "' is not a count"; } GameObject prefab = instance.GetPrefab(args[2]); Character val = default(Character); if ((Object)(object)prefab == (Object)null || !prefab.TryGetComponent<Character>(ref val)) { return "no creature called " + args[2]; } string text = val.m_name ?? ""; if (!Foothold.Pays(text)) { if (result != 0) { return args[2] + " (" + text + ") is worth nothing on any points line, so Utangard does not count it"; } Say(term, "utangardtest kills: " + ((Object)prefab).name + " (" + text + ") is worth nothing on any points line, so its count is 0 already."); return true; } if (!KillTally.Set(text, result, out var had)) { return "there is no character in a world to set it on"; } Say(term, "utangardtest kills: " + ((Object)prefab).name + " (" + text + ") was " + had + ", now " + result + ", for " + Player.m_localPlayer.GetPlayerName() + " in this world."); return true; } private static void OnCommand(ConsoleEventArgs args) { Terminal context = args.Context; if (!((Object)(object)context == (Object)null)) { switch ((args.Length > 1) ? args[1].ToLowerInvariant() : "") { case "foothold": FootholdReport(context); return; case "biomes": Biomes(context); return; case "creatures": Creatures(context); return; case "deaths": DeathsReport(context, args); return; } context.AddString("utangard foothold - per biome: your Fighting and Discovery bars, what each kind of creature put in, and what is unlocked"); context.AddString("utangard biomes - per biome: its creatures, the kills of each Utangard counted for you in this world (only creatures a points line pays for), and how much of it you have explored"); context.AddString("utangard creatures - every creature in the foothold tables, checked against the game"); context.AddString("utangard deaths <creature> - whether it dies through its animation, how many this machine saw die this session and whether it had them, and who has the nearest live one"); context.AddString("utangard deaths - every creature that dies through its animation; utangard deaths <creature> since <notowner> - whether this machine ran one it did not own since notowner stood there"); } } internal static void SawDeath(Character creature) { try { ZNetView val = default(ZNetView); if (!((Object)(object)creature == (Object)null) && !creature.IsPlayer() && ((Component)creature).TryGetComponent<ZNetView>(ref val) && val.IsValid()) { DeathCount deathCount = DeathsOf(Utils.GetPrefabName(((Component)creature).gameObject)); if (val.IsOwner()) { deathCount.AsOwner++; } else { deathCount.NotOwner++; } } } catch (Exception) { } } internal static void RanBossCredit(Character creature) { try { if (!((Object)(object)creature == (Object)null)) { DeathsOf(Utils.GetPrefabName(((Component)creature).gameObject)).BossCredit++; } } catch (Exception) { } } private static DeathCount DeathsOf(string prefab) { string key = prefab ?? ""; if (!Deaths.TryGetValue(key, out var value)) { value = (Deaths[key] = new DeathCount()); } return value; } private static void DeathsReport(Terminal term, ConsoleEventArgs args) { ZNetScene instance = ZNetScene.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null) { Say(term, "utangard deaths: no character in a world yet."); return; } if (args.Length < 3) { Say(term, DeathAnimations(instance)); Say(term, "utangard deaths <creature> [since <notowner>] - one of them by prefab name: Greydwarf, Eikthyr..."); return; } GameObject prefab = instance.GetPrefab(args[2]); Character val = default(Character); if ((Object)(object)prefab == (Object)null || !prefab.TryGetComponent<Character>(ref val)) { Say(term, "utangard deaths: no creature called " + args[2] + "."); return; } string name = ((Object)prefab).name; string text = "utangard deaths " + name + ": "; string defeatSetGlobalKey = val.m_defeatSetGlobalKey; string text2 = (string.IsNullOrEmpty(defeatSetGlobalKey) ? "none" : (UtangardConfig.IsGateKey(defeatSetGlobalKey) ? "yes" : "no")); Say(term, text + "deathanim=" + (val.m_deathAnimation ? "yes" : "no") + " gatekey=" + text2 + " (" + (val.m_deathAnimation ? "it dies through its animation, so every machine animating it reaches OnDeath" : "it dies straight from CheckDeath, so only the machine that has it reaches OnDeath") + (string.IsNullOrEmpty(defeatSetGlobalKey) ? "" : ("; its death writes " + defeatSetGlobalKey)) + ")"); Deaths.TryGetValue(name, out var value); string text3 = (Seams.FootholdKills ? "" : " The death hook did not go on this session, so asowner and notowner cannot move.") + ((Seams.KillCredit && UtangardConfig.Enabled.Value && UtangardConfig.GateOnGroup.Value) ? "" : " The boss credit is off this session (its hook, Enabled or GateOnGroup), so bosscredit cannot move."); Say(term, text + "asowner=" + (value?.AsOwner ?? 0) + " notowner=" + (value?.NotOwner ?? 0) + " bosscredit=" + (value?.BossCredit ?? 0) + " (deaths this machine ran this session, by whether it had the creature, and the boss credits it ran for one)" + text3); Say(term, text + NearestAlive(name, localPlayer)); Say(term, text + KillsOf(val)); if (args.Length > 4 && string.Equals(args[3], "since", StringComparison.OrdinalIgnoreCase) && int.TryParse(args[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { Say(term, text + NonOwnerSince(value?.NotOwner ?? 0, result, val.m_deathAnimation)); } } private static string NonOwnerSince(int now, int since, bool deathAnimation) { int num = now - since; string text = " since notowner=" + since.ToString(CultureInfo.InvariantCulture); if (num < 0) { return "nonowner=unknown" + text + " (notowner is " + now + " now, below that, so the number given was not read in this session)"; } if (num > 0) { return "nonowner=" + num + text + " (this machine ran " + num + " death(s) of it that it did not own, so the refusal of a machine that does not have it was exercised here)"; } return "nonowner=0" + text + " (this machine ran no death of it that it did not own, so the refusal of a machine that does not have it was NOT exercised here" + (deathAnimation ? ")" : ", and none can: it dies straight from CheckDeath, so only the machine that has it reaches OnDeath)"); } private static string DeathAnimations(ZNetScene scene) { List<string> list = new List<string>(); if (scene.m_prefabs != null) { Character val = default(Character); foreach (GameObject prefab in scene.m_prefabs) { if (!((Object)(object)prefab == (Object)null) && prefab.TryGetComponent<Character>(ref val) && !(val is Player) && val.m_deathAnimation) { list.Add(((Object)prefab).name); } } } list.Sort(StringComparer.OrdinalIgnoreCase); return "utangard deaths: deathanim=" + list.Count + " (creatures that die through their animation, so a machine that does not have one can still run its death" + ((list.Count == 0) ? "; there are none in this world)" : ("): " + string.Join(", ", list.ToArray()))); } private static string NearestAlive(string prefab, Player player) { //IL_005b: 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) List<Character> allCharacters = Character.GetAllCharacters(); float num = 1600f; float num2 = num; int num3 = 0; Character val = null; if (allCharacters != null) { foreach (Character item in allCharacters) { if ((Object)(object)item == (Object)null || item.IsDead() || !string.Equals(Utils.GetPrefabName(((Component)item).gameObject), prefab, StringComparison.OrdinalIgnoreCase)) { continue; } Vector3 val2 = ((Component)item).transform.position - ((Component)player).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num)) { num3++; if (!(sqrMagnitude > num2)) { num2 = sqrMagnitude; val = item; } } } } if ((Object)(object)val == (Object)null) { return "nearest=none alive=0 (none alive within " + 40f.ToString("0", CultureInfo.InvariantCulture) + " m)"; } ZNetView val3 = default(ZNetView); string text = ((!((Component)val).TryGetComponent<ZNetView>(ref val3) || !val3.IsValid()) ? "nobody" : (val3.IsOwner() ? "here" : "elsewhere")); return "nearest=" + text + " alive=" + num3 + " (the nearest live one, " + Mathf.Sqrt(num2).ToString("0.0", CultureInfo.InvariantCulture) + " m away, belongs to " + ((text == "here") ? "this machine" : ((text == "elsewhere") ? "another machine" : "no machine")) + ")"; } private static string KillsOf(Character creature) { string text = creature.m_name ?? ""; if (!Foothold.Pays(text)) { return "kills=unpaid (" + text + " is on no points line, so Utangard does not count it)"; } Dictionary<string, int> dictionary = KillTally.Here(); if (dictionary == null) { return "kills=unreadable (" + (KillTally.WhyNot() ?? "the kill tally cannot be read") + ")"; } dictionary.TryGetValue(text, out var value); return "kills=" + value.ToString(CultureInfo.InvariantCulture) + " (your kills of " + text + " that Utangard counted in this world, assists included)"; } private static void FootholdReport(Terminal term) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Say(term, "utangard foothold: no character in a world yet."); return; } CultureInfo invariantCulture = CultureInfo.InvariantCulture; int num = Discovery.FullPixels(); float num2 = Discovery.PixelKm2(); int full = Foothold.FullBar(); Say(term, "utangard foothold: " + localPlayer.GetPlayerName() + ". " + (UtangardConfig.FootholdEnabled.Value ? "" : "FootholdEnabled is OFF, so nothing below unlocks anything. ") + "A full Fighting bar is " + full + " points. Eating at " + Foothold.EatAtPercent() + "% (" + Foothold.EatAtPoints(full) + " points), healing at a full bar and full discovery. No kind above " + UtangardConfig.MaxFromOneKindPercent.Value + "% (" + Foothold.KindCap(full) + " points)."); string text = KillTally.WhyNot(); Say(term, (text != null) ? ("utangard foothold: kills cannot be counted right now: " + text + ". Every Fighting bar reads as empty.") : "utangard foothold: kills are the ones Utangard saw you make or help with in this world. Not from other worlds or before this version, not of tamed animals, and not with devcommands."); if (!Discovery.Available()) { Say(term, "utangard foothold: the explored map cannot be read this session, so every Discovery bar is empty."); } else { Say(term, "utangard foothold: full discovery is " + UtangardConfig.DiscoveryFullKm2.Value.ToString("0.##", invariantCulture) + " km2 = " + num + " map pixels of " + (num2 * 1000000f).ToString("0", invariantCulture) + " m2. " + (Discovery.Counting() ? ("Still counting this world's map (" + (Discovery.Progress() * 100f).ToString("0", invariantCulture) + "%), so discovery can only go up from here.") : ("Map counted. " + Discovery.Describe()))); } foreach (Foothold.Standing item in Foothold.ReadAll()) { if (!item.Gated && item.Kinds.Count == 0) { continue; } string text2 = ((!item.Gated) ? "ungated" : (item.Locked ? "LOCKED" : "open")); if (item.Here) { text2 += ", its rules apply to you now"; } string text3 = ((!item.Locked) ? "nothing to unlock" : ((item.CanEat ? "eating allowed" : ("eating at " + item.EatAtPercent + "%")) + ", " + (item.CanHeal ? "healing allowed" : "healing needs both full"))); string text4 = (item.FightingAvailable ? (item.Fighting + "/" + item.Full + " (" + item.FightingPercent.ToString(invariantCulture) + "%)") : "unreadable"); string text5 = (item.DiscoveryAvailable ? (item.Discovered + "/" + item.DiscoveryFull + " px (" + Math.Floor(item.DiscoveryPercent).ToString("0", invariantCulture) + "%" + (item.DiscoveryCounting ? ", still counting" : "") + ")") : "unreadable"); Say(term, ((object)Unsafe.As<Biome, Biome>(ref item.Biome)/*cast due to .constrained prefix*/).ToString() + " (" + text2 + "): fighting " + text4 + ", discovery " + text5 + " - " + text3 + "."); if (item.Kinds.Count == 0) { Say(term, " no creatures on this biome's points line, so its Fighting bar cannot fill."); continue; } List<string> list = new List<string>(); foreach (Foothold.Kind kind in item.Kinds) { string text6 = kind.Name + " " + kind.Points + "pt x" + kind.Kills + " = " + kind.Contribution; if (kind.Capped) { text6 = text6 + " (capped at " + item.KindCap + ", " + kind.Earned + " earned)"; } list.Add(text6); } Say(term, " " + string.Join(", ", list.ToArray())); } } private unsafe static void Biomes(Terminal term) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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) PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (val == null || (Object)(object)Player.m_localPlayer == (Object)null) { Say(term, "utangard biomes: no character in a world yet."); return; } Dictionary<string, int> dictionary = KillTally.Here() ?? new Dictionary<string, int>(); Dictionary<Biome, Dictionary<string, Creature>> dictionary2 = SpawnTables(); Dictionary<Biome, int> area; Dictionary<Biome, int> seen; float pixelKm; string text = Exploration(out area, out seen, out pixelKm); string text2 = KillTally.WhyNot(); Say(term, "utangard biomes: " + val.GetName() + ". " + text + ((text2 != null) ? (" Kills cannot be read: " + text2 + ".") : "")); Biome[] order = Order; for (int i = 0; i < order.Length; i++) { Biome key = order[i]; area.TryGetValue(key, out var value); seen.TryGetValue(key, out var value2); float num = (float)value * pixelKm; float num2 = (float)value2 * pixelKm; float num3 = ((value > 0) ? (100f * (float)value2 / (float)value) : 0f); dictionary2.TryGetValue(key, out var value3); List<Creature> obj = ((value3 != null) ? value3.Values.OrderBy<Creature, string>((Creature c) => c.Prefab, StringComparer.Ordinal).ToList() : new List<Creature>()); int num4 = 0; int num5 = 0; long num6 = 0L; List<string> list = new List<string>(); foreach (Creature item in obj) { dictionary.TryGetValue(item.Token ?? "", out var value4); if (item.Unconditional) { num4++; } if (value4 > 0) { num5++; num6 += value4; } list.Add(item.Prefab + (item.Unconditional ? "" : "*") + " " + item.Health.ToString("0", CultureInfo.InvariantCulture) + "hp x" + value4.ToString(CultureInfo.InvariantCulture)); } Say(term, ((object)(*(Biome*)(&key))/*cast due to .constrained prefix*/).ToString() + ": " + num.ToString("0.0", CultureInfo.InvariantCulture) + " km2 on this map, you explored " + num2.ToString("0.00", CultureInfo.InvariantCulture) + " km2 (" + num3.ToString("0.0", CultureInfo.InvariantCulture) + "%). Creatures: " + num4 + " kinds you can always meet. Utangard counted " + num5 + " kinds, " + num6.ToString(CultureInfo.InvariantCulture) + " kills."); if (list.Count > 0) { Say(term, " " + string.Join(", ", list.ToArray())); } } Say(term, "utangard biomes: * = only spawns behind a world key, a weather or a persistent event. Spawn tables only - creatures a dungeon or a camp places itself are not in them. Each entry is health, then your kills: the ones Utangard counted in this world, assists included, and only for creatures a points line pays for."); Dictionary<string, Creature> dictionary3 = new Dictionary<string, Creature>(); Dictionary<string, int> dictionary4 = new Dictionary<string, int>(); foreach (KeyValuePair<Biome, Dictionary<string, Creature>> item2 in dictionary2) { foreach (Creature value6 in item2.Value.Values) { dictionary3[value6.Prefab] = value6; dictionary4.TryGetValue(value6.Prefab, out var value5); dictionary4[value6.Prefab] = value5 + 1; } } foreach (KeyValuePair<string, int> item3 in dictionary4.Where((KeyValuePair<string, int> p) => p.Value >= 5).OrderBy<KeyValuePair<string, int>, string>((KeyValuePair<string, int> p) => p.Key, StringComparer.Ordinal)) { Say(term, " in " + item3.Value + " biomes: " + item3.Key + ", rows:"); foreach (string row in dictionary3[item3.Key].Rows) { Say(term, " " + row); } } } private static Dictionary<Biome, Dictionary<string, Creature>> SpawnTables() { //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0237: 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) Dictionary<Biome, Dictionary<string, Creature>> dictionary = new Dictionary<Biome, Dictionary<string, Creature>>(); SpawnSystem val = Object.FindObjectOfType<SpawnSystem>(); if ((Object)(object)val == (Object)null || val.m_spawnLists == null) { return dictionary; } Character val2 = default(Character); foreach (SpawnSystemList spawnList in val.m_spawnLists) { if ((Object)(object)spawnList == (Object)null || spawnList.m_spawners == null) { continue; } foreach (SpawnData spawner in spawnList.m_spawners) { if (spawner == null || !spawner.m_enabled || spawner.m_devDisabled || (Object)(object)spawner.m_prefab == (Object)null || !spawner.m_prefab.TryGetComponent<Character>(ref val2) || val2.IsBoss()) { continue; } bool flag = !string.IsNullOrEmpty(spawner.m_requiredGlobalKey) || !string.IsNullOrEmpty(spawner.m_requiredPersistentEvent) || (spawner.m_requiredEnvironments != null && spawner.m_requiredEnvironments.Count > 0); string item = "'" + spawner.m_name + "' biomes=" + ((object)Unsafe.As<Biome, Biome>(ref spawner.m_biome)/*cast due to .constrained prefix*/).ToString() + " area=" + ((object)Unsafe.As<BiomeArea, BiomeArea>(ref spawner.m_biomeArea)/*cast due to .constrained prefix*/).ToString() + " key='" + spawner.m_requiredGlobalKey + "' event='" + spawner.m_requiredPersistentEvent + "' env=" + ((spawner.m_requiredEnvironments != null) ? spawner.m_requiredEnvironments.Count : 0) + " chance=" + spawner.m_spawnChance.ToString("0.#", CultureInfo.InvariantCulture) + " max=" + spawner.m_maxSpawned + " day=" + spawner.m_spawnAtDay + " night=" + spawner.m_spawnAtNight; Biome[] order = Order; foreach (Biome val3 in order) { if ((spawner.m_biome & val3) != 0) { if (!dictionary.TryGetValue(val3, out var value)) { value = (dictionary[val3] = new Dictionary<string, Creature>()); } if (!value.TryGetValue(((Object)spawner.m_prefab).name, out var value2)) { Dictionary<string, Creature> dictionary3 = value; string name = ((Object)spawner.m_prefab).name; Creature obj = new Creature { Prefab = ((Object)spawner.m_prefab).name, Token = val2.m_name, Health = val2.m_health }; value2 = obj; dictionary3[name] = obj; } if (!flag) { value2.Unconditional = true; } if (!value2.Rows.Contains(item)) { value2.Rows.Add(item); } } } } } return dictionary; } private static string Exploration(out Dictionary<Biome, int> area, out Dictionary<Biome, int> seen, out float pixelKm2) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) area = new Dictionary<Biome, int>(); seen = new Dictionary<Biome, int>(); pixelKm2 = 0f; Minimap instance = Minimap.instance; WorldGenerator instance2 = WorldGenerator.instance; if ((Object)(object)instance == (Object)null || instance2 == null) { return "No minimap or world generator, so no exploration."; } BitArray bitArray = null; try { bitArray = Traverse.Create((object)instance).Field("m_explored").GetValue<BitArray>(); } catch (Exception) { bitArray = null; } int textureSize = instance.m_textureSize; float pixelSize = instance.m_pixelSize; int num = ((textureSize < 1024) ? 1 : 2); int num2 = textureSize / 2; for (int i = 0; i < textureSize; i += num) { for (int j = 0; j < textureSize; j += num) { float num3 = (float)(j - num2) * pixelSize; float num4 = (float)(i - num2) * pixelSize; if (!(num3 * num3 + num4 * num4 > 100000000f)) { Biome biome = instance2.GetBiome(num3, num4, 0.02f, false); area.TryGetValue(biome, out var value); area[biome] = value + 1; if (bitArray != null && bitArray[i * textureSize + j]) { seen.TryGetValue(biome, out var value2); seen[biome] = value2 + 1; } } } } pixelKm2 = (float)(num * num) * pixelSize * pixelSize / 1000000f; return "Map " + textureSize + "x" + textureSize + " at " + pixelSize.ToString("0.#", CultureInfo.InvariantCulture) + " m a pixel, explore radius " + instance.m_exploreRadius.ToString("0", CultureInfo.InvariantCulture) + " m" + ((bitArray == null) ? ", and the explored bits could not be read." : "."); } private unsafe static void Creatures(Terminal term) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { Say(term, "utangard creatures: no world loaded yet."); return; } Dictionary<string, int> kills = KillTally.Here(); int full = Foothold.FullBar(); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); Biome[] gateableBiomes = UtangardConfig.GateableBiomes; for (int i = 0; i < gateableBiomes.Length; i++) { Biome biome = gateableBiomes[i]; List<KeyValuePair<string, int>> list = Foothold.Parse(UtangardConfig.PointsLineFor(biome)); if (list.Count == 0) { continue; } Say(term, "utangard creatures: " + ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() + ", " + list.Count + " kinds, full bar " + full + " points, no kind above " + Foothold.KindCap(full) + "."); foreach (KeyValuePair<string, int> item in list) { Say(term, " " + item.Value + " pt " + Describe(instance, item.Key, kills, dictionary, ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() + " " + item.Key + "=" + item.Value)); } } Say(term, "utangard creatures: left out on purpose -"); string[] leftOut = LeftOut; foreach (string text in leftOut) { Say(term, " - " + Describe(instance, text, kills, dictionary, "left out " + text)); } int num = 0; foreach (KeyValuePair<string, List<string>> item2 in dictionary) { if (item2.Value.Count >= 2) { num++; Say(term, "utangard creatures: SHARED TOKEN " + item2.Key + " - " + string.Join("; ", item2.Value.ToArray())); } } Say(term, (num == 0) ? "utangard creatures: every creature has a token of its own." : ("utangard creatures: " + num + " token(s) shared - those creatures cannot be scored apart.")); int num2 = 0; foreach (Foothold.Entry item3 in Foothold.Resolve(instance)) { if (!string.IsNullOrEmpty(item3.Dropped)) { num2++; Say(term, "utangard creatures: DROPPED " + ((object)Unsafe.As<Biome, Biome>(ref item3.Biome)/*cast due to .constrained prefix*/).ToString() + " " + item3.Prefab + " - " + item3.Dropped); } } Say(term, (num2 == 0) ? "utangard creatures: after the shared-name rule, every entry in the tables counts." : ("utangard creatures: after the shared-name rule, " + num2 + " entr(ies) do not count.")); } private static string Describe(ZNetScene scene, string prefabName, Dictionary<string, int> kills, Dictionary<string, List<string>> byToken, string label) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Invalid comparison between Unknown and I4 GameObject prefab = scene.GetPrefab(prefabName); if ((Object)(object)prefab == (Object)null) { return prefabName + " - NOT FOUND in ZNetScene"; } Character val = default(Character); if (!prefab.TryGetComponent<Character>(ref val)) { return prefabName + " - not a creature"; } string text = "no AI"; if ((Object)(object)prefab.GetComponent<MonsterAI>() != (Object)null) { text = "monster"; } else if ((Object)(object)prefab.GetComponent<AnimalAI>() != (Object)null) { text = "ANIMAL"; } string text2 = (((Object)(object)prefab.GetComponent<Tameable>() != (Object)null) ? ", tameable" : ""); string text3 = ((text == "ANIMAL" || (int)val.m_faction == 1) ? " <- prey" : ""); string text4 = val.m_name ?? ""; if (!byToken.TryGetValue(text4, out var value)) { value = (byToken[text4] = new List<string>()); } value.Add(label); int value2 = 0; string text5 = ((kills != null && kills.TryGetValue(text4, out value2)) ? value2.ToString(CultureInfo.InvariantCulture) : ((kills != null) ? "0" : "?")); return prefabName + " " + text4 + " " + val.m_health.ToString("0", CultureInfo.InvariantCulture) + "hp " + ((object)Unsafe.As<Faction, Faction>(ref val.m_faction)/*cast due to .constrained prefix*/).ToString() + " " + text + text2 + ", your kills here " + text5 + text3; } private static void Say(Terminal term, string line) { term.AddString(line); UtangardPlugin.Log.LogInfo((object)line); } static DevConsole() { Biome[] array = new Biome[9]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Order = (Biome[])(object)array; LeftOut = new string[11] { "Deer", "Bat", "Hare", "SeekerBrood", "Seal", "Seal_Pup", "Seal_pup", "Moose_calf", "Asksvin_hatchling", "AsksvinHatchling", "Skeleton_Swamps" }; } } internal static class Discovery { [HarmonyPatch] internal static class Uncover { [HarmonyTargetMethod] private static MethodBase Target() { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(Minimap))) { if (!(declaredMethod.Name != "Explore") && !(declaredMethod.ReturnType != typeof(bool))) { ParameterInfo[] parameters = declaredMethod.GetParameters(); if (parameters.Length == 2 && parameters[0].ParameterType == typeof(int) && parameters[1].ParameterType == typeof(int)) { return declaredMethod; } } } UtangardPlugin.Log.LogError((object)"Minimap has no Explore(int, int) any more - the Discovery bar cannot follow new exploration, so healing stays locked in a locked biome."); return null; } [HarmonyPostfix] private static void Postfix(Minimap __instance, int __0, int __1, bool __result) { if (!__result || _gaveUp) { return; } try { if (__instance != _map) { Restart(__instance); } int num = __1 * __instance.m_textureSize + __0; if (_done || num < _cursor) { WorldGenerator instance = WorldGenerator.instance; if (instance != null) { Count(__instance, instance, __0, __1); } } } catch (Exception ex) { GiveUp(ex.ToString()); } } } [HarmonyPatch] internal static class Rewrite { private static readonly string[] Names = new string[3] { "SetMapData", "Reset", "ExploreAll" }; [HarmonyTargetMethods] private static IEnumerable<MethodBase> Targets() { List<MethodBase> list = new List<MethodBase>(); string[] names = Names; foreach (string text in names) { bool flag = false; foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(Minimap))) { if (!(declaredMethod.Name != text)) { list.Add(declaredMethod); flag = true; } } if (!flag) { throw new MissingMethodException("Minimap", text); } } return list; } [HarmonyPrefix] private static void Prefix(Minimap __instance) { if ((Object)(object)__instance != (Object)null) { Restart(__instance); } } } private static Minimap _map; private static int _cursor; private static bool _done; private static readonly Dictionary<Biome, int> Counts = new Dictionary<Biome, int>(); private static readonly long Budget = Stopwatch.Frequency / 1000; private const int Slice = 256; private const float Edge = 10500f; private static bool _saidFailure; private static bool _gaveUp; private static FieldRef<Minimap, BitArray> _exploredOf; private static bool _exploredBound; internal static bool Available() { if (Seams.MapExplore && Seams.FoodTick && !_gaveUp) { return ExploredOf() != null; } return false; } internal static bool Counting() { return !_done; } internal static int Pixels(Biome biome) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || instance != _map) { return 0; } if (!Counts.TryGetValue(biome, out var value)) { return 0; } return value; } internal static int FullPixels() { float value = UtangardConfig.DiscoveryFullKm2.Value; if (value <= 0f) { return 0; } float num = PixelKm2(); if (num <= 0f) { return int.MaxValue; } return (int)Math.Ceiling(value / num); } internal static float PixelKm2() { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return 0f; } float pixelSize = instance.m_pixelSize; return pixelSize * pixelSize / 1000000f; } internal static float Progress() { if (_done) { return 1f; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || instance != _map) { return 0f; } int num = instance.m_textureSize * instance.m_textureSize; if (num > 0) { return (float)_cursor / (float)num; } return 0f; } internal static void Step() { if (_gaveUp || !Seams.MapExplore || !UtangardConfig.Enabled.Value || !UtangardConfig.FootholdEnabled.Value) { return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } if (instance != _map) { Restart(instance); } if (_done) { return; } try { BitArray bitArray = Bits(instance); WorldGenerator instance2 = WorldGenerator.instance; if (bitArray == null || instance2 == null) { return; } int textureSize = instance.m_textureSize; int length = bitArray.Length; if (textureSize <= 0 || textureSize * textureSize != length) {