Decompiled source of Codex v0.1.1
Codex.dll
Decompiled 7 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; 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 System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Burst2Flame; using Burst2Flame.Observable; using HarmonyLib; using Microsoft.CodeAnalysis; using StolenRealmModAPI; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Codex")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+52158c7d25a1953ef0dc1b873b569982776fd2a0")] [assembly: AssemblyProduct("Codex")] [assembly: AssemblyTitle("Codex")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Codex { internal sealed class BestiaryPage : ListPage { private static readonly EnemyType?[] TypeFilters = new EnemyType?[6] { null, (EnemyType)0, (EnemyType)1, (EnemyType)2, (EnemyType)4, (EnemyType)3 }; private int _typeFilter; public override string Title => "Bestiary"; public BestiaryPage(Ui ui) : base(ui) { } public static Color TypeColor(EnemyType t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected I4, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) return (Color)((int)t switch { 0 => Ui.Hex(10130314), 1 => Ui.Hex(13220772), 2 => Ui.Hex(14922838), 4 => Ui.Hex(12159974), 3 => Ui.Hex(15230543), _ => Ui.DimColor, }); } private unsafe static string TypeName(EnemyType t) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { string enemyTypeNameString = Game.Instance.GetEnemyTypeNameString(t); if (!string.IsNullOrWhiteSpace(enemyTypeNameString)) { return enemyTypeNameString; } } catch { } return ((object)(*(EnemyType*)(&t))/*cast due to .constrained prefix*/).ToString(); } protected override void BuildToolbar() { AddSearch(-1f); AddCycler(150f, () => (!TypeFilters[_typeFilter].HasValue) ? "All types" : TypeName(TypeFilters[_typeFilter].Value), delegate(int dir) { _typeFilter = ListPage.Wrap(_typeFilter + dir, TypeFilters.Length); }); } protected override IEnumerable<RowSpec> Rows() { return CodexData.Enemies.Select((EnemyEntry e) => new RowSpec { Data = e, Label = e.Name, Tag = TypeName(e.Type), TagColor = TypeColor(e.Type), Search = e.Search }); } protected override bool PassesFilters(object data, bool searching) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) EnemyType? val = TypeFilters[_typeFilter]; if (val.HasValue) { return ((EnemyEntry)data).Type == val.Value; } return true; } protected override void FillOverview() { DHeader("Bestiary", null, $"{CodexData.Enemies.Count} creatures", null); DText("Pick a creature on the left to see its stats and the moves it can use.\n\nStats scale with level and with the number of heroes in the party: use the arrows above the stats to change both (shift-click steps by 5). Damage numbers in move descriptions use the creature's own power at that level.\n\nSearch matches names, factions and types. The arrows next to the search box filter by type."); } protected override void FillDetail(object data) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) EnemyEntry enemyEntry = (EnemyEntry)data; CharacterInfo info = enemyEntry.Info; string text = Color(TypeName(enemyEntry.Type), TypeColor(enemyEntry.Type)); if (!string.IsNullOrEmpty(enemyEntry.Faction)) { text = text + " · " + enemyEntry.Faction; } string text2 = LevelRange(info); if (text2 != null) { text = text + "\n" + text2; } if (enemyEntry.Special) { text += "\nNot part of random encounters"; } DHeader(enemyEntry.Name, null, text, null); RectTransform parent = DRow(); Ui.Stepper((Transform)(object)parent, "Level", () => CodexState.Level, delegate(int v) { CodexState.Level = v; RedrawDetail(); }, 1, 60); Ui.Stepper((Transform)(object)parent, "Party", () => CodexState.Party, delegate(int v) { CodexState.Party = v; RedrawDetail(); }, 1, 6); EnemyStats enemyStats = EnemyStats.Compute(info, enemyEntry.Type, CodexState.Level, CodexState.Party); DSection("Stats"); DStats(new List<(string, string)> { ("Health", GameText.Num(enemyStats.Health)), ("Mana", GameText.Num(enemyStats.Mana)), ("Attack Power", GameText.Num(enemyStats.AttackPower)), ("Spell Power", GameText.Num(enemyStats.SpellPower)), ("Armor", GameText.Num(enemyStats.Armor)), ("Magic Armor", GameText.Num(enemyStats.MagicArmor)), ("Movement", enemyStats.Movement.ToString()), ("Attacks with", GameText.DamageTypeName(info.basicAttackDamageType)), ("Fire Resist", Pct(enemyStats.FireResist)), ("Cold Resist", Pct(enemyStats.ColdResist)), ("Lightning Res.", Pct(enemyStats.LightningResist)), ("Physical Res.", Pct(enemyStats.PhysicalResist)) }); string text3 = ((enemyStats.Difficulty != null) ? (enemyStats.Difficulty + " difficulty") : "Base values (no run loaded)"); if (EnemyStats.PlayingRoguelike()) { text3 += ", roguelike scaling"; } DText(text3 + ".", 11f, Ui.DimColor); List<string> list = Traits(info); if (list.Count > 0) { DSection("Traits"); DText(string.Join("\n", list.Select((string t) => "• " + t))); } List<(SkillInfo, SkillAndAI, int)> list2 = CodexData.Moves(info); DSection((list2.Count == 1) ? "Move" : $"Moves ({list2.Count})"); if (list2.Count == 0) { DText("No special moves.", 13f, Ui.DimColor); } StatContext ctx = enemyStats.Context(CodexState.Level); foreach (var (skill, ai, phase) in list2) { Move(skill, ai, phase, ctx); } } private static string Color(string text, Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GameText.Color(text, c); } private static string Pct(float v) { if (v != 0f) { return ((v > 0f) ? "+" : "") + GameText.Trim(v) + "%"; } return "0%"; } private static string LevelRange(CharacterInfo info) { int minLevel = info.MinLevel; int maxLevel = info.MaxLevel; if (minLevel <= 1 && (maxLevel <= 0 || maxLevel >= 99)) { return null; } if (maxLevel <= 0 || maxLevel >= 99) { return $"Appears from level {minLevel}"; } if (minLevel != maxLevel) { return $"Appears at levels {minLevel}–{maxLevel}"; } return $"Appears at level {minLevel}"; } private List<string> Traits(CharacterInfo info) { //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); if (info.SpecialEffects != null) { foreach (SpecialEffect item in info.SpecialEffects.Distinct()) { list.Add(Color(GameText.SplitCamel(((object)item/*cast due to .constrained prefix*/).ToString()), Ui.TermColor)); } } if (info.EnemyMods != null) { foreach (EnemyMod item2 in info.EnemyMods.Where((EnemyMod m) => (Object)(object)m != (Object)null)) { string text = GameText.L(GameText.SplitCamel(((Object)item2).name), (LanguageGender)0, (Gender)2); string text2 = GameText.L(item2.description, (LanguageGender)0, (Gender)2); list.Add(Color(text, Ui.TermColor) + (string.IsNullOrWhiteSpace(text2) ? "" : (": " + text2))); } } if (info.CharacterEffects != null) { CharacterEffectInfo[] characterEffects = info.CharacterEffects; for (int num = 0; num < characterEffects.Length; num++) { string text3 = GameText.AttributeEffect(characterEffects[num]); if (text3 != null) { list.Add(text3); } } } if (info.CanEnrage) { list.Add("Can become " + Color("enraged", Ui.TermColor)); } if (info.Untargetable) { list.Add("Can't be targeted"); } if (info.SpawnsWith != null && info.SpawnsWith.Length != 0) { list.Add("Spawns with " + string.Join(", ", from c in info.SpawnsWith where (Object)(object)c != (Object)null select GameText.L(((Object)c).name, (LanguageGender)0, (Gender)2))); } if (Mathf.Abs(info.GoldModifier - 1f) > 0.01f && info.GoldModifier > 0f) { list.Add("Gold ×" + GameText.Trim(info.GoldModifier)); } if (Mathf.Abs(info.ExpModifier - 1f) > 0.01f && info.ExpModifier > 0f) { list.Add("Experience ×" + GameText.Trim(info.ExpModifier)); } return list; } private void Move(SkillInfo skill, SkillAndAI ai, int phase, StatContext ctx) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_016f: 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_0118: Invalid comparison between Unknown and I4 //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Invalid comparison between Unknown and I4 //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Invalid comparison between Unknown and I4 //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_0144: Unknown result type (might be due to invalid IL or missing references) DSpacer(2f); string text = GameText.L(skill.SkillName, (LanguageGender)0, (Gender)2); if (string.IsNullOrWhiteSpace(text)) { text = GameText.SplitCamel(((Object)skill).name); } if (phase > 0) { text += Color($" phase {phase}", Ui.DimColor); } ((TMP_Text)Ui.Text((Transform)(object)DetailContent, text, 15f, header: true)).textWrappingMode = (TextWrappingModes)1; ActionInfo val = ((skill.ActionsGranted != null) ? ((IEnumerable<ActionInfo>)skill.ActionsGranted).FirstOrDefault((Func<ActionInfo, bool>)((ActionInfo a) => (Object)(object)a != (Object)null)) : null); string text2; if ((Object)(object)val == (Object)null) { text2 = "Passive"; } else { text2 = GameText.ActionMeta(val, (ai != null && ai.UseCooldownOverride) ? new int?(ai.CooldownOverride) : ((int?)null), (ai != null && ai.UseRangeOverride) ? new int?(ai.RangeOverride) : ((int?)null)); if ((int)skill.DamageType != 9 || (int)val.DamageType != 9) { DamageType t = (((int)skill.DamageType != 9) ? skill.DamageType : val.DamageType); text2 = text2 + " · " + GameText.DamageTypeName(t); } } if (ai != null && ai.StartsOnCooldown) { text2 += " · starts on cooldown"; } DText(text2, 11f, Ui.DimColor); string text3 = GameText.Description(skill.Description, skill.DescriptionExpressions, ctx); if (string.IsNullOrEmpty(text3) && (Object)(object)val != (Object)null) { text3 = GameText.Description(val.Description, val.DescriptionExpressions, ctx); } if (!string.IsNullOrEmpty(text3)) { DText(text3); } } } internal sealed class EnemyEntry { public CharacterInfo Info; public string Name; public string Faction; public EnemyType Type; public bool Special; public string Search; } internal sealed class WeaponEntry { public WeaponInfo Info; public string Name; public string Search; } internal sealed class SkillEntry { public SkillInfo Info; public string Name; public string Search; public bool Passive { get { if (Info.ActionsGranted != null) { return Info.ActionsGranted.Length == 0; } return true; } } } internal sealed class SkillTree { public SkillType Type; public string Name; public Sprite Icon; public List<SkillEntry> Skills = new List<SkillEntry>(); } internal static class CodexData { public static List<EnemyEntry> Enemies; public static List<WeaponEntry> Weapons; public static List<SkillTree> Trees; private static bool _summaryLogged; private static readonly EquipmentType[] WeaponOrder; public static bool Ready => Enemies != null; public static IEnumerable<EquipmentType> WeaponTypes { get { if (Weapons != null) { return Weapons.Select((WeaponEntry w) => w.Info.EquipmentType).Distinct().OrderBy(WeaponTypeOrder); } return Enumerable.Empty<EquipmentType>(); } } public static void Invalidate() { Enemies = null; Weapons = null; Trees = null; } public static bool EnsureLoaded() { if (Ready) { return true; } Game instance = Game.Instance; if ((Object)(object)instance == (Object)null || instance.Characters == null || instance.Characters.Count == 0 || instance.Items == null || instance.Items.Count == 0 || instance.Skills == null || instance.Skills.Count == 0) { return false; } Enemies = LoadEnemies(instance); Weapons = LoadWeapons(instance); Trees = LoadTrees(instance); if (!_summaryLogged && Plugin.LogDataSummary.Value) { _summaryLogged = true; LogSummary(instance); } return true; } private static List<EnemyEntry> LoadEnemies(Game game) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Invalid comparison between Unknown and I4 //IL_00f9: Unknown result type (might be due to invalid IL or missing references) List<EnemyEntry> list = new List<EnemyEntry>(); foreach (CharacterInfo character in game.Characters) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character == (Object)(object)game.HumanCharacterInfo) && !(((object)character).GetType() != typeof(CharacterInfo))) { EnemyEntry enemyEntry = new EnemyEntry { Info = character, Name = GameText.L(((Object)character).name, SafeLanguageGender(character), character.Gender), Type = character.enemyType, Faction = (((int)character.EnemyGroup == 72) ? "" : GameText.SplitCamel(((object)Unsafe.As<EnemyGroup, EnemyGroup>(ref character.EnemyGroup)/*cast due to .constrained prefix*/).ToString())), Special = IsSpecial(character) }; if (!string.IsNullOrWhiteSpace(enemyEntry.Name) && (!enemyEntry.Special || Plugin.ShowSpecialEnemies.Value)) { enemyEntry.Search = $"{enemyEntry.Name} {enemyEntry.Faction} {enemyEntry.Type}".ToLowerInvariant(); list.Add(enemyEntry); } } } return list.OrderBy<EnemyEntry, string>((EnemyEntry e) => e.Name, StringComparer.CurrentCultureIgnoreCase).ThenBy((EnemyEntry e) => e.Info.MinLevel).ToList(); } private static LanguageGender SafeLanguageGender(CharacterInfo info) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) try { return info.LanguageGender; } catch { return (LanguageGender)0; } } private static bool IsSpecial(CharacterInfo info) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if (info.Untargetable) { return true; } if (!info.ExcludeFromBattlePool) { return false; } if ((int)info.enemyType != 3) { return (int)info.enemyType != 4; } return false; } public static List<(SkillInfo skill, SkillAndAI ai, int phase)> Moves(CharacterInfo info) { List<(SkillInfo, SkillAndAI, int)> list = new List<(SkillInfo, SkillAndAI, int)>(); HashSet<SkillInfo> hashSet = new HashSet<SkillInfo>(); if (info.SkillsAndAI != null) { SkillAndAI[] skillsAndAI = info.SkillsAndAI; foreach (SkillAndAI val in skillsAndAI) { if ((Object)(object)val?.Skill != (Object)null && hashSet.Add(val.Skill)) { list.Add((val.Skill, val, 0)); } } } if (info.Skills != null) { foreach (SkillInfo skill in info.Skills) { if ((Object)(object)skill != (Object)null && hashSet.Add(skill)) { list.Add((skill, null, 0)); } } } if (info.SkillSetOverrides != null) { for (int j = 0; j < info.SkillSetOverrides.Length; j++) { SkillSetOverride val2 = info.SkillSetOverrides[j]; if (val2?.SkillsAndAI == null) { continue; } SkillAndAI[] skillsAndAI = val2.SkillsAndAI; foreach (SkillAndAI val3 in skillsAndAI) { if ((Object)(object)val3?.Skill != (Object)null && hashSet.Add(val3.Skill)) { list.Add((val3.Skill, val3, j + 2)); } } } } return list; } private static List<WeaponEntry> LoadWeapons(Game game) { //IL_002b: 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_003d: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Invalid comparison between Unknown and I4 //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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) List<WeaponEntry> list = new List<WeaponEntry>(); foreach (ItemInfo item in game.Items) { WeaponInfo val = (WeaponInfo)(object)((item is WeaponInfo) ? item : null); if (val != null && (int)((ItemInfo)val).ItemType == 0 && (int)val.EquipmentType != 15 && (int)val.EquipmentType != 12 && (int)val.EquipmentType != 13) { string text = SafeItemName((ItemInfo)(object)val); if (!string.IsNullOrWhiteSpace(text)) { list.Add(new WeaponEntry { Info = val, Name = text, Search = $"{text} {WeaponTypeName(val.EquipmentType)} {((ItemInfo)val).Rarity} {val.DamageType}".ToLowerInvariant() }); } } } return (from e in list orderby WeaponTypeOrder(e.Info.EquipmentType), (int)((ItemInfo)e.Info).Rarity, ((ItemInfo)e.Info).MinLevel select e).ThenBy<WeaponEntry, string>((WeaponEntry e) => e.Name, StringComparer.CurrentCultureIgnoreCase).ToList(); } public static string SafeItemName(ItemInfo info) { try { return GameText.L(info.ItemName, (LanguageGender)0, (Gender)2); } catch { return ((Object)info).name; } } public static int WeaponTypeOrder(EquipmentType t) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected I4, but got Unknown int num = Array.IndexOf(WeaponOrder, t); if (num >= 0) { return num; } return 100 + t; } public unsafe static string WeaponTypeName(EquipmentType t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected I4, but got Unknown return (int)t switch { 0 => "One-Handed Swords", 2 => "Two-Handed Swords", 7 => "One-Handed Axes", 1 => "Two-Handed Axes", 10 => "One-Handed Maces", 11 => "Two-Handed Maces", 3 => "Polearms", 14 => "Fist Weapons", 4 => "Bows", 5 => "Pistols", 6 => "Rifles", 8 => "Staves", 9 => "Wands", _ => GameText.SplitCamel(((object)(*(EquipmentType*)(&t))/*cast due to .constrained prefix*/).ToString()), }; } private static List<SkillTree> LoadTrees(Game game) { //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) List<SkillTree> list = new List<SkillTree>(); MiscSettings val = (((Object)(object)GlobalSettingsManager.instance != (Object)null) ? GlobalSettingsManager.instance.miscSettings : null); List<SkillType> list2 = val?.SkillTabTypes; if (list2 == null || list2.Count == 0) { list2 = (from s in game.Skills where (Object)(object)s != (Object)null select s.SkillType into t where (int)t != 8 && (int)t != 9 select t).Distinct().ToList(); } for (int num = 0; num < list2.Count; num++) { SkillTree item = new SkillTree { Type = list2[num], Name = GameText.Enum<SkillType>(list2[num]), Icon = ((val?.TreeIcons != null && num < val.TreeIcons.Length) ? val.TreeIcons[num] : null) }; list.Add(item); } Dictionary<SkillType, SkillTree> dictionary = list.ToDictionary((SkillTree t) => t.Type); foreach (SkillInfo skill in game.Skills) { if ((Object)(object)skill == (Object)null || skill.Disabled || skill.DontIncludeInTree || !dictionary.TryGetValue(skill.SkillType, out var value)) { continue; } bool flag = true; try { flag = game.FullReleaseModeEnabled(skill); } catch { } if (flag) { string text = GameText.L(skill.SkillName, (LanguageGender)0, (Gender)2); if (string.IsNullOrWhiteSpace(text)) { text = ((Object)skill).name; } value.Skills.Add(new SkillEntry { Info = skill, Name = text, Search = (text + " " + value.Name).ToLowerInvariant() }); } } foreach (SkillTree item2 in list) { item2.Skills = (from e in item2.Skills orderby e.Info.Tier, e.Passive, e.Info.xVal, e.Name select e).ToList(); } return list; } public static int TierCost(int tier) { return TierRule("skillsTierCosts", tier, 1); } public static int TierUnlock(int tier) { return TierRule("skillPointsToUnlockTier", tier, 0); } private static int TierRule(string field, int tier, int fallback) { try { GlobalSettings globalSettings = GlobalSettingsManager.instance.globalSettings; int[] array = ((field == "skillsTierCosts") ? globalSettings.skillsTierCosts : globalSettings.skillPointsToUnlockTier); if (array != null && tier >= 1 && tier <= array.Length) { return array[tier - 1]; } } catch { } return fallback; } private static void LogSummary(Game game) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Codex data: {Enemies.Count} bestiary entries (of {game.Characters.Count} characters), " + $"{Weapons.Count} weapons, {Trees.Count} skill trees ({Trees.Sum((SkillTree t) => t.Skills.Count)} skills)."); stringBuilder.AppendLine(" Bestiary by type: " + string.Join(", ", from e in Enemies group e by e.Type into g orderby g.Key select $"{g.Key} {g.Count()}")); stringBuilder.AppendLine(" Weapons by type: " + string.Join(", ", from w in Weapons group w by w.Info.EquipmentType into g select $"{g.Key} {g.Count()}")); stringBuilder.AppendLine(" Trees: " + string.Join(", ", Trees.Select((SkillTree t) => $"{t.Name} {t.Skills.Count}"))); List<string> list = (from c in game.Characters where (Object)(object)c != (Object)null && (Object)(object)c != (Object)(object)game.HumanCharacterInfo && IsSpecial(c) select $"{((Object)c).name} ({c.enemyType})" into s orderby s select s).ToList(); stringBuilder.AppendLine($" Special entries ({list.Count}, shown only with [Bestiary] ShowSpecialEntries): " + string.Join(", ", list)); Plugin.ModLog.LogInfo((object)stringBuilder.ToString().TrimEnd()); } static CodexData() { EquipmentType[] array = new EquipmentType[13]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); WeaponOrder = (EquipmentType[])(object)array; } } internal struct EnemyStats { public float Health; public float Mana; public float AttackPower; public float SpellPower; public float Armor; public float MagicArmor; public int Movement; public float FireResist; public float ColdResist; public float LightningResist; public float PhysicalResist; public string Difficulty; public static EnemyStats Compute(CharacterInfo info, EnemyType type, int level, int party) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Invalid comparison between Unknown and I4 EnemyStats result = default(EnemyStats); GlobalSettings globalSettings = GlobalSettingsManager.instance.globalSettings; EnemyTypeStatSet enemyTypeStatSet = globalSettings.GetEnemyTypeStatSet(type); BasicEffects val = (BasicEffects)(((object)info.BasicEffects) ?? ((object)new BasicEffects())); bool flag = PlayingRoguelike(); float num = 1f; float damageMod = 1f; float num2 = 1f; float bossDamage = 1f; try { DifficultySetting val2 = (((Object)(object)GameLogic.instance != (Object)null) ? GameLogic.instance.CurrentDifficulty : null); if (val2 != null) { num = val2.HealthMod; damageMod = val2.DamageMod; num2 = val2.BossHealthMod; bossDamage = val2.BossDamageMod; result.Difficulty = GameText.L(val2.DifficultyName, (LanguageGender)0, (Gender)2); } } catch { } bool boss = (int)type == 3; float num3 = (flag ? GlobalExtensions.GetMultipler(globalSettings.AiHealthMultiplerNodesRoguelike, level) : Character.GetAIHealthModifier(globalSettings, level)); float multipler = GlobalExtensions.GetMultipler(flag ? globalSettings.NumberOfCharactersHealthMutliplierNodesRoguelike : globalSettings.NumberOfCharactersHealthMutliplierNodes, party); float num4 = enemyTypeStatSet?.health ?? 1f; result.Health = Mathf.Ceil(num4 * val.health * num3 * multipler * num * (boss ? num2 : 1f)); float damageLevel = DamageLevelMultiplier(globalSettings, level, flag); float damageParty = GlobalExtensions.GetMultipler(flag ? globalSettings.NumberOfCharactersDamageMutliplierNodesRoguelike : globalSettings.NumberOfCharactersDamageMutliplierNodes, party); result.AttackPower = Power(enemyTypeStatSet?.weaponDamage ?? 1f, val.weaponDamage); result.SpellPower = Power(enemyTypeStatSet?.spellPower ?? 1f, val.spellPower); float multipler2 = GlobalExtensions.GetMultipler(flag ? globalSettings.AiHealthMultiplerNodesRoguelike : globalSettings.AiHealthMultiplerNodes, level); result.Mana = Mathf.Ceil((float)(enemyTypeStatSet?.mana ?? 0) * val.mana * multipler2 * Character.GetLevelBasedMultipler(globalSettings.PercentManaPerPlayer, (float)party)); float multipler3 = GlobalExtensions.GetMultipler(globalSettings.AiStatMultiplerNodes, level); result.Armor = Mathf.Ceil(val.armor * multipler3); result.MagicArmor = Mathf.Ceil(val.magicArmor * multipler3); result.Movement = Mathf.FloorToInt(val.movementPoints); result.FireResist = Mathf.Ceil(val.fireResist); result.ColdResist = Mathf.Ceil(val.coldResist); result.LightningResist = Mathf.Ceil(val.lightningResist); result.PhysicalResist = Mathf.Ceil(val.physicalResist); return result; float Power(float basePower, float ratio) { return Mathf.Round(basePower * damageLevel * damageParty * ratio * damageMod) * (boss ? bossDamage : 1f); } } private static float DamageLevelMultiplier(GlobalSettings gs, int level, bool rogue) { if (level > 30) { return GlobalExtensions.GetMultipler(gs.AiDamageMultiplerNodes, 30) * Mathf.Pow(1.025f, (float)(level - 30)) + (float)(2 * (level - 30)); } return GlobalExtensions.GetMultipler(rogue ? gs.AiDamageMultiplerNodesRoguelike : gs.AiDamageMultiplerNodes, level); } public static bool PlayingRoguelike() { try { NetworkingManager instance = NetworkingManager.Instance; Root val = (((Object)(object)instance != (Object)null && instance.NetworkManager != null) ? ((Observer<Root>)(object)instance.NetworkManager).Root : null); return val != null && val.PlayingRoguelike; } catch { return false; } } public static (int level, int party) CurrentParty() { int item = 1; int num = 0; try { Character val = (((Object)(object)GameLogic.instance != (Object)null) ? GameLogic.instance.CurrentlySelectedCharacter : null); if (val != null) { item = Mathf.Max(1, val.Level); } } catch { } try { NetworkingManager instance = NetworkingManager.Instance; if ((Object)(object)instance != (Object)null && instance.PartyCharacters != null) { num = instance.PartyCharacters.Count; } } catch { } return (level: item, party: (num > 0) ? num : 3); } public StatContext Context(int level) { return new StatContext().Set("AttackPower", AttackPower).Set("SpellPower", SpellPower).Set("SpellPowerWithMight", SpellPower) .Set("Level", level) .Set("MaxHealth", Health); } } internal static class CodexState { public static int Level = 1; public static int Party = 3; } internal class CodexTab : MonoBehaviour { public const string TabLabel = "Codex"; private const float SectionBarHeight = 28f; private static CodexTab _instance; private OptionsManager _options; private MenuTabManager _tabs; private MenuTab _tab; private GameObject _panel; private RectTransform _pageHost; private Ui _ui; private ListPage[] _pages; private Clickable[] _sectionButtons; private GameObject[] _underlines; private int _current; private TextMeshProUGUI _message; public static void Install(OptionsManager options) { if ((Object)(object)options == (Object)null || (Object)(object)((Component)options).GetComponent<CodexTab>() != (Object)null) { return; } try { _instance = ((Component)options).gameObject.AddComponent<CodexTab>(); _instance.Build(options); } catch (Exception arg) { Plugin.ModLog.LogError((object)$"Couldn't add the Codex tab: {arg}"); } } public static void ApplyEnabled() { if (!((Object)(object)_instance == (Object)null) && !((Object)(object)_instance._tab == (Object)null)) { bool value = Plugin.Enabled.Value; ((Component)_instance._tab).gameObject.SetActive(value); if (!value) { _instance.Hide(); } } } public static void InvalidateData() { CodexData.Invalidate(); if ((Object)(object)_instance != (Object)null) { _instance.ResetPages(); } } private void Build(OptionsManager options) { _options = options; Traverse obj = Traverse.Create((object)options); MenuTab value = obj.Field("TabTwitch").GetValue<MenuTab>(); GameObject value2 = obj.Field("twitchPanel").GetValue<GameObject>(); _tabs = ((Component)options).GetComponentInChildren<MenuTabManager>(true); if ((Object)(object)value == (Object)null || (Object)(object)value2 == (Object)null || (Object)(object)_tabs == (Object)null) { throw new InvalidOperationException("Options window layout changed (Twitch tab/panel not found)."); } _ui = Ui.FromOptions(options, value, _tabs); BuildTab(value); BuildPanel(value2); ApplyEnabled(); Plugin.ModLog.LogInfo((object)"Codex tab added to the Options window."); } private void BuildTab(MenuTab twitchTab) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(((Component)twitchTab).gameObject, ((Component)twitchTab).transform.parent, false); ((Object)val).name = "TabCodex"; Ui.Sanitize(val); Transform val2 = ((Component)twitchTab).transform.parent.Find("TabMods"); Transform val3 = (((Object)(object)val2 != (Object)null) ? val2 : ((Component)twitchTab).transform); val.transform.SetSiblingIndex(val3.GetSiblingIndex() + 1); val.SetActive(true); _tab = val.GetComponent<MenuTab>(); RefreshLabel(); Button component = val.GetComponent<Button>(); if ((Object)(object)component != (Object)null) { ((UnityEvent)component.onClick).AddListener(new UnityAction(Open)); } Traverse obj = Traverse.Create((object)_tabs).Field("MenuTabs"); List<MenuTab> list = ((IEnumerable<MenuTab>)(((object)obj.GetValue<MenuTab[]>()) ?? ((object)new MenuTab[0]))).ToList(); MenuTab component2 = ((Component)val3).GetComponent<MenuTab>(); int num = (((Object)(object)component2 != (Object)null) ? list.IndexOf(component2) : (-1)); list.Insert((num < 0) ? list.Count : (num + 1), _tab); obj.SetValue((object)list.ToArray()); } public void RefreshLabel() { if (!((Object)(object)_tab == (Object)null)) { TMP_Text[] componentsInChildren = ((Component)_tab).GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].text = "Codex"; } Text[] componentsInChildren2 = ((Component)_tab).GetComponentsInChildren<Text>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].text = "Codex"; } } } private void BuildPanel(GameObject twitchPanel) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_005d: 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_0075: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: 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_030f: Unknown result type (might be due to invalid IL or missing references) _panel = new GameObject("CodexPanel", new Type[1] { typeof(RectTransform) }); RectTransform val = (RectTransform)_panel.transform; RectTransform val2 = (RectTransform)twitchPanel.transform; ((Transform)val).SetParent(((Transform)val2).parent, false); ((Transform)val).SetSiblingIndex(((Transform)val2).GetSiblingIndex() + 1); val.anchorMin = val2.anchorMin; val.anchorMax = val2.anchorMax; val.pivot = val2.pivot; val.offsetMin = val2.offsetMin; val.offsetMax = val2.offsetMax; ((Transform)val).localScale = ((Transform)val2).localScale; RectTransform val3 = Ui.TopStrip(Ui.NewRect((Transform)(object)val, "Sections"), 0f, 28f); Ui.HRow(((Component)val3).gameObject, 26f, (TextAnchor)3, new RectOffset(4, 0, 0, 0)); Ui.TopStrip(((Graphic)Ui.Rect((Transform)(object)val, "Rule", Ui.RuleColor)).rectTransform, 28f, 1f); _pageHost = Ui.Stretch(Ui.NewRect((Transform)(object)val, "Pages"), 0f, 36f); _message = _ui.Text((Transform)(object)_pageHost, "", 14f, header: false, Ui.DimColor, "Message"); Ui.Stretch(((TMP_Text)_message).rectTransform, 8f, 8f, 8f, 8f); ((Component)_message).gameObject.SetActive(false); _pages = new ListPage[3] { new BestiaryPage(_ui), new WeaponsPage(_ui), new SkillTreesPage(_ui) }; _sectionButtons = new Clickable[_pages.Length]; _underlines = (GameObject[])(object)new GameObject[_pages.Length]; for (int i = 0; i < _pages.Length; i++) { int index = i; Clickable clickable = _ui.TextButton((Transform)(object)val3, _pages[i].Title, 16f, delegate { ShowPage(index); }, header: true, "Section (" + _pages[i].Title + ")"); Ui.Size((Component)(object)clickable, -1f, 28f).minWidth = ((TMP_Text)((Component)clickable).GetComponent<TextMeshProUGUI>()).preferredWidth + 4f; _sectionButtons[i] = clickable; Image val4 = Ui.Rect(((Component)clickable).transform, "Underline", _ui.HeaderColor); RectTransform rectTransform = ((Graphic)val4).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(1f, 0f); rectTransform.pivot = new Vector2(0.5f, 0f); rectTransform.offsetMin = new Vector2(0f, 0f); rectTransform.offsetMax = new Vector2(0f, 2f); ((Component)val4).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; ((Component)val4).gameObject.SetActive(false); _underlines[i] = ((Component)val4).gameObject; } _panel.SetActive(false); } private void ResetPages() { if (_pages == null) { return; } ListPage[] pages = _pages; foreach (ListPage listPage in pages) { if ((Object)(object)listPage.Root != (Object)null) { Object.Destroy((Object)(object)listPage.Root); } } _pages = new ListPage[3] { new BestiaryPage(_ui), new WeaponsPage(_ui), new SkillTreesPage(_ui) }; if ((Object)(object)_panel != (Object)null && _panel.activeSelf) { ShowPage(_current); } } public void Open() { _options.CloseAllMenus(); _panel.SetActive(true); _options.AnyWindowOpen(); _tabs.SelectButton(_tab); var (level, party) = EnemyStats.CurrentParty(); if ((Object)(object)GameLogic.instance != (Object)null && GameLogic.instance.CurrentlySelectedCharacter != null) { CodexState.Level = level; CodexState.Party = party; } ShowPage(_current); } public void Hide() { if ((Object)(object)_panel != (Object)null) { _panel.SetActive(false); } } private void ShowPage(int index) { _current = index; for (int i = 0; i < _sectionButtons.Length; i++) { _sectionButtons[i].Selected = i == index; _underlines[i].SetActive(i == index); } bool flag; try { flag = CodexData.EnsureLoaded(); } catch (Exception arg) { Plugin.ModLog.LogError((object)$"Codex: couldn't read the game's data: {arg}"); ShowMessage("The Codex couldn't read the game's data (see the BepInEx log)."); return; } if (!flag) { ShowMessage("The game is still loading its data. Try again in a moment."); return; } ((Component)_message).gameObject.SetActive(false); for (int j = 0; j < _pages.Length; j++) { ListPage listPage = _pages[j]; if (j != index) { if ((Object)(object)listPage.Root != (Object)null) { listPage.Hide(); } continue; } try { if ((Object)(object)listPage.Root == (Object)null) { listPage.Build(_pageHost); } listPage.Show(); } catch (Exception arg2) { Plugin.ModLog.LogError((object)$"Codex: couldn't build the {listPage.Title} section: {arg2}"); if ((Object)(object)listPage.Root != (Object)null) { listPage.Hide(); } ShowMessage("The " + listPage.Title + " section failed to load (see the BepInEx log)."); } } } private void ShowMessage(string text) { ListPage[] pages = _pages; foreach (ListPage listPage in pages) { if ((Object)(object)listPage.Root != (Object)null) { listPage.Hide(); } } ((TMP_Text)_message).text = text; ((Component)_message).gameObject.SetActive(true); } } internal static class GameText { private static readonly CultureInfo Inv = CultureInfo.InvariantCulture; private static readonly Regex ValueToken = new Regex("\\*(\\d)|\\[(\\d)\\]"); private static readonly Regex TermToken = new Regex("@([^@\\n]{1,40})@"); private static readonly Regex LinkToken = new Regex("\\{(\\w+)=([^}]*)\\}"); private static readonly Regex NumberFactor = new Regex("^\\(?\\s*(-?\\d*\\.?\\d+)\\s*f?\\s*\\)?$"); private static readonly Regex SourceMember = new Regex("^(Source|Target)\\s*\\.\\s*(\\w+)\\s*(\\(\\s*(\"\\w*\")?\\s*\\))?$"); private static readonly Regex SourceIndexer = new Regex("^(Source|Target)\\s*\\[\\s*\"(\\w+)\"\\s*\\]$"); private static readonly Dictionary<string, string> StatNames = new Dictionary<string, string> { { "AttackPower", "Attack Power" }, { "SpellPower", "Spell Power" }, { "SpellPowerWithMight", "Spell Power" }, { "GetFlatDamageValue", "Flat Damage" }, { "HighestStatValue", "highest attribute" }, { "MaxHealth", "Max Health" }, { "HealthRatioInverse", "missing health %" } }; private static readonly Regex NumberSuffix = new Regex("(\\d)f\\b"); private static readonly Regex IndexerClean = new Regex("(Source|Target)\\[\\\\?\"(\\w+)\\\\?\"\\]"); public static string L(string s, LanguageGender lg = (LanguageGender)0, Gender g = (Gender)2) { //IL_0015: 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) if (string.IsNullOrEmpty(s)) { return s ?? ""; } try { string text = OptionsManager.Localize(s, lg, g); return string.IsNullOrEmpty(text) ? s : text; } catch { return s; } } public static string Enum<T>(T value) where T : Enum { try { string text = OptionsManager.LocalizeEnum<T>(value, (LanguageGender)0); if (!string.IsNullOrEmpty(text)) { return text; } } catch { } return SplitCamel(value.ToString()); } public static string SplitCamel(string s) { if (string.IsNullOrEmpty(s)) { return ""; } s = s.Replace('_', ' '); StringBuilder stringBuilder = new StringBuilder(s.Length + 8); for (int i = 0; i < s.Length; i++) { char c = s[i]; if (i > 0 && char.IsUpper(c) && s[i - 1] != ' ' && (char.IsLower(s[i - 1]) || (i + 1 < s.Length && char.IsLower(s[i + 1])))) { stringBuilder.Append(' '); } stringBuilder.Append(c); } return stringBuilder.ToString(); } public static string Num(float v) { return Mathf.Round(v).ToString("N0", Inv); } public static string Trim(float v) { if (!(Mathf.Abs(v - Mathf.Round(v)) < 0.001f)) { return v.ToString("0.##", Inv); } return Mathf.Round(v).ToString("0", Inv); } public static string Color(string text, Color c) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return "<color=" + Ui.Html(c) + ">" + text + "</color>"; } public static Color DamageTypeColor(DamageType t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected I4, but got Unknown //IL_002b: 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_0041: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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) return (Color)((t - 2) switch { 0 => Ui.Hex(15764043), 1 => Ui.Hex(8177394), 2 => Ui.Hex(15916899), 3 => Ui.Hex(11832024), 6 => Ui.Hex(16115366), 4 => Ui.Hex(8838022), 5 => Ui.Hex(8364784), _ => Ui.Hex(14075560), }); } public static string DamageTypeName(DamageType t) { //IL_0000: 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_0007: Unknown result type (might be due to invalid IL or missing references) return Color(GameText.Enum<DamageType>(t), DamageTypeColor(t)); } public static Color RarityColor(ItemQuality q) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0024: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected I4, but got Unknown //IL_0093: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_008d: Unknown result type (might be due to invalid IL or missing references) try { Color itemQualityColor = GlobalSettingsManager.instance.globalSettings.GetItemQualityColor(q); if (itemQualityColor.a > 0.01f) { return new Color(itemQualityColor.r, itemQualityColor.g, itemQualityColor.b, 1f); } } catch { } return (Color)((q - 1) switch { 0 => Ui.Hex(6277215), 1 => Ui.Hex(5938154), 2 => Ui.Hex(15243836), 3 => Ui.Hex(14703194), _ => Ui.Hex(14273979), }); } public static string Description(string text, string[] expressions, StatContext ctx = null) { if (string.IsNullOrWhiteSpace(text)) { return ""; } text = L(text, (LanguageGender)0, (Gender)2); text = ValueToken.Replace(text, delegate(Match m) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) int num = int.Parse(m.Groups[1].Success ? m.Groups[1].Value : m.Groups[2].Value, Inv); return Color(Expression((expressions != null && num < expressions.Length) ? expressions[num] : null, ctx), Ui.ScalingColor); }); text = TermToken.Replace(text, (Match m) => Color(m.Groups[1].Value, Ui.TermColor)); text = LinkToken.Replace(text, delegate(Match m) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) string text2 = m.Groups[2].Value; int num = text2.LastIndexOf('|'); if (num >= 0) { text2 = text2.Substring(num + 1); } return Color(L(text2, (LanguageGender)0, (Gender)2), Ui.StatusColor); }); return text.Trim(); } public static string Expression(string expr, StatContext ctx) { if (string.IsNullOrWhiteSpace(expr)) { return "X"; } expr = expr.Trim(); float num = 1f; string text = null; string text2 = null; bool flag = true; foreach (string item in SplitTopLevel(expr, '*')) { string input = item.Trim(); Match match; if ((match = NumberFactor.Match(input)).Success) { num *= float.Parse(match.Groups[1].Value, Inv); continue; } if ((match = SourceMember.Match(input)).Success || (match = SourceIndexer.Match(input)).Success) { bool flag2 = match.Groups[1].Value == "Target"; string value = match.Groups[2].Value; if (!value.StartsWith("DamageMod")) { if (text != null) { flag = false; break; } text2 = (flag2 ? "Target." : "") + value; text = (flag2 ? "target's " : "") + (StatNames.TryGetValue(value, out var value2) ? value2 : SplitCamel(value)); } continue; } flag = false; break; } if (!flag) { return Clean(expr); } if (text == null) { return Trim(num); } if (ctx != null && ctx.TryGet(text2, out var value3)) { return Num(num * value3); } if (text2 == "Level" || text2 == "Target.Level") { return Trim(num) + " × " + ((text2 == "Level") ? "level" : "target level"); } return Trim(num * 100f) + "% " + text; } private static List<string> SplitTopLevel(string s, char sep) { List<string> list = new List<string>(); int num = 0; int num2 = 0; bool flag = false; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c == '"') { flag = !flag; } if (flag) { continue; } switch (c) { case '(': case '[': num++; continue; case ')': case ']': num--; continue; } if (num == 0 && i > 0 && (c == '+' || c == '-' || c == '/' || c == '?')) { return new List<string> { s }; } if (num == 0 && c == sep) { list.Add(s.Substring(num2, i - num2)); num2 = i + 1; } } list.Add(s.Substring(num2)); return list; } private static string Clean(string expr) { string text = IndexerClean.Replace(expr, (Match m) => ((m.Groups[1].Value == "Target") ? "target " : "") + SplitCamel(m.Groups[2].Value)); text = text.Replace("Source.", "").Replace("Target.", "target ").Replace("()", ""); text = NumberSuffix.Replace(text, "$1"); text = Regex.Replace(text, "\\s*\\*\\s*DamageMod\\w+", ""); if (text.Length <= 60) { return text; } return "X"; } public static string AttributeEffect(CharacterEffectInfo e, StatContext ctx = null, float scale = 1f) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if (e == null || (Object)(object)e.CharacterAttribute == (Object)null) { return null; } CharacterAttribute characterAttribute = e.CharacterAttribute; string text = ""; try { text = characterAttribute.GetTooltipDisplayName(); } catch { } if (string.IsNullOrWhiteSpace(text)) { text = characterAttribute.DisplayName; } if (string.IsNullOrWhiteSpace(text)) { text = SplitCamel(((Object)characterAttribute).name); } text = L(text, (LanguageGender)0, (Gender)2); float num = 0f; bool flag = false; try { flag = e.TryGetConstantAmount(ref num); } catch { } if (!flag && float.TryParse((e.Amount ?? "").Trim().TrimEnd('f'), NumberStyles.Float, Inv, out var result)) { num = result; flag = true; } if (flag) { num *= scale; return Color(((num >= 0f) ? "+" : "") + Trim(Mathf.Round(num * 100f) / 100f) + (characterAttribute.OverrideAsPercentage ? "%" : ""), Ui.ValueColor) + " " + text; } return text + ": " + Color(Expression(e.Amount, ctx), Ui.ScalingColor); } public static string ActionMeta(ActionInfo a, int? cooldownOverride = null, int? rangeOverride = null) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 if ((Object)(object)a == (Object)null) { return ""; } List<string> list = new List<string>(); try { if ((int)a.ActionType == 1) { list.Add("Free action"); } else { string text = ConstOrNull(a.Cost); list.Add((text != null) ? (text + " AP") : ("AP: " + Clean(a.Cost ?? "?"))); } } catch { } string text2 = (cooldownOverride.HasValue ? cooldownOverride.Value.ToString(Inv) : ConstOrNull(a.Cooldown)); if (text2 == null && !string.IsNullOrWhiteSpace(a.Cooldown)) { text2 = Clean(a.Cooldown); } if (text2 != null && text2 != "0") { list.Add((text2 == "1") ? "1 turn cooldown" : (text2 + " turn cooldown")); } if (a.HasCharges) { string text3 = ConstOrNull(a.MaxCharges); if (text3 != null) { list.Add(text3 + " charges"); } } int num = rangeOverride ?? SimpleRange(a); if (num > 0) { list.Add((num == 1) ? "Melee" : $"Range {num}"); } return string.Join(" · ", list); } private static int SimpleRange(ActionInfo a) { try { if (a.UseMaxRangeOverride) { return a.MaxRangeOverride; } if (a.Targets == null) { return 0; } ITargetInfo[] targets = a.Targets; foreach (ITargetInfo obj in targets) { TargetInfo val = (TargetInfo)(object)((obj is TargetInfo) ? obj : null); if (val != null) { return a.GetSimpleRange(val); } } } catch { } return 0; } public static string ConstOrNull(string expr) { if (string.IsNullOrWhiteSpace(expr)) { return null; } if (!float.TryParse(expr.Trim().TrimEnd('f'), NumberStyles.Float, Inv, out var result)) { return null; } return Trim(result); } } internal sealed class StatContext { private readonly Dictionary<string, float> _values = new Dictionary<string, float>(); public StatContext Set(string key, float value) { _values[key] = value; return this; } public bool TryGet(string key, out float value) { return _values.TryGetValue(key, out value); } } internal abstract class ListPage { protected sealed class RowSpec { public object Data; public string Label; public Color? LabelColor; public string Tag; public Color? TagColor; public Sprite Icon; public string Search; public string GroupKey; public string GroupLabel; public string GroupLabelSearching; } private sealed class Row { public RowSpec Spec; public GameObject Go; public GameObject Accent; public Clickable Click; public Group Group; } private sealed class Group { public string Key; public string Label; public string SearchLabel; public TextMeshProUGUI Header; public readonly List<Row> Rows = new List<Row>(); } protected const float ListWidth = 200f; protected const float ToolbarHeight = 30f; protected const float RowHeight = 24f; protected readonly Ui Ui; protected RectTransform Toolbar; protected RectTransform ListContent; protected RectTransform DetailContent; protected ScrollRect ListScroll; protected ScrollRect DetailScroll; protected string SearchText = ""; private readonly List<Row> _rows = new List<Row>(); private readonly List<Group> _groups = new List<Group>(); private Row _selected; private bool _rowsBuilt; private TextMeshProUGUI _emptyLabel; private TMP_InputField _search; public GameObject Root { get; private set; } public abstract string Title { get; } protected ListPage(Ui ui) { Ui = ui; } protected abstract void BuildToolbar(); protected abstract IEnumerable<RowSpec> Rows(); protected abstract bool PassesFilters(object data, bool searching); protected abstract void FillDetail(object data); protected abstract void FillOverview(); public void Build(RectTransform host) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown RectTransform val = Ui.Stretch(Ui.NewRect((Transform)(object)host, "Page (" + Title + ")")); Root = ((Component)val).gameObject; Toolbar = Ui.TopStrip(Ui.NewRect((Transform)(object)val, "Toolbar"), 0f, 30f); Ui.HRow(((Component)Toolbar).gameObject, 8f, (TextAnchor)3); RectTransform parent = Ui.Stretch(Ui.NewRect((Transform)(object)val, "Body"), 0f, 38f); RectTransform val2 = Ui.NewRect((Transform)(object)parent, "List"); val2.anchorMin = new Vector2(0f, 0f); val2.anchorMax = new Vector2(0f, 1f); val2.pivot = new Vector2(0f, 0.5f); val2.offsetMin = Vector2.zero; val2.offsetMax = new Vector2(200f, 0f); ListScroll = Ui.ScrollView(val2, out ListContent, new RectOffset(0, 0, 2, 2), 0f); RectTransform root = Ui.Stretch(Ui.NewRect((Transform)(object)parent, "Detail"), 206f); DetailScroll = Ui.ScrollView(root, out DetailContent, new RectOffset(14, 16, 12, 16), 6f); BuildToolbar(); Root.SetActive(false); } public void Show() { Root.SetActive(true); if (!_rowsBuilt) { _rowsBuilt = true; BuildRows(); ApplyFilter(); ShowDetail(null); } } public void Hide() { Root.SetActive(false); } private void BuildRows() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) Group obj = null; foreach (RowSpec item in Rows()) { if (item.GroupKey != null && (obj == null || obj.Key != item.GroupKey)) { obj = new Group { Key = item.GroupKey, Label = item.GroupLabel, SearchLabel = item.GroupLabelSearching }; obj.Header = BuildGroupHeader(obj.Label); _groups.Add(obj); } else if (item.GroupKey == null) { obj = null; } Row row = BuildRow(item); row.Group = obj; obj?.Rows.Add(row); _rows.Add(row); } _emptyLabel = Ui.Text((Transform)(object)ListContent, "Nothing matches.", 13f, header: false, Ui.DimColor, "Empty"); ((TMP_Text)_emptyLabel).margin = new Vector4(10f, 8f, 10f, 0f); ((Component)_emptyLabel).gameObject.SetActive(false); } private TextMeshProUGUI BuildGroupHeader(string label) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Image val = Ui.Rect((Transform)(object)ListContent, "Group", Ui.GroupColor); Ui.Size((Component)(object)val, -1f, 20f); TextMeshProUGUI obj = Ui.Text(((Component)val).transform, label, 12f, header: true); Ui.Stretch(((TMP_Text)obj).rectTransform, 8f, 0f, 6f); ((TMP_Text)obj).alignment = (TextAlignmentOptions)4097; ((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)obj).overflowMode = (TextOverflowModes)1; return obj; } private Row BuildRow(RowSpec spec) { //IL_0018: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) Image val = Ui.Rect((Transform)(object)ListContent, "Row", Ui.PaneColor, raycast: true); Ui.Size((Component)(object)val, -1f, 24f); Row row = new Row { Spec = spec, Go = ((Component)val).gameObject }; Image val2 = Ui.Rect(((Component)val).transform, "Accent", Ui.HeaderColor); RectTransform rectTransform = ((Graphic)val2).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = new Vector2(3f, 0f); ((Component)val2).gameObject.SetActive(false); row.Accent = ((Component)val2).gameObject; float num = 9f; if ((Object)(object)spec.Icon != (Object)null) { Image obj = Ui.Rect(((Component)val).transform, "Icon", Color.white); obj.sprite = spec.Icon; obj.preserveAspect = true; RectTransform rectTransform2 = ((Graphic)obj).rectTransform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 0.5f); rectTransform2.anchorMax = val3; rectTransform2.anchorMin = val3; rectTransform2.pivot = new Vector2(0f, 0.5f); rectTransform2.sizeDelta = new Vector2(18f, 18f); rectTransform2.anchoredPosition = new Vector2(num, 0f); num += 24f; } float num2 = (string.IsNullOrEmpty(spec.Tag) ? 0f : 58f); TextMeshProUGUI obj2 = Ui.Text(((Component)val).transform, spec.Label, 14f, header: false, spec.LabelColor); Ui.Stretch(((TMP_Text)obj2).rectTransform, num, 0f, num2 + 6f); ((TMP_Text)obj2).alignment = (TextAlignmentOptions)4097; ((TMP_Text)obj2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)obj2).overflowMode = (TextOverflowModes)1; if (num2 > 0f) { TextMeshProUGUI obj3 = Ui.Text(((Component)val).transform, spec.Tag, 11f, header: false, (Color)(((??)spec.TagColor) ?? Ui.DimColor)); RectTransform rectTransform3 = ((TMP_Text)obj3).rectTransform; rectTransform3.anchorMin = new Vector2(1f, 0f); rectTransform3.anchorMax = new Vector2(1f, 1f); rectTransform3.pivot = new Vector2(1f, 0.5f); rectTransform3.sizeDelta = new Vector2(num2, 0f); rectTransform3.anchoredPosition = new Vector2(-10f, 0f); ((TMP_Text)obj3).alignment = (TextAlignmentOptions)4100; ((TMP_Text)obj3).textWrappingMode = (TextWrappingModes)0; } row.Click = ((Component)val).gameObject.AddComponent<Clickable>(); row.Click.Init((Graphic)(object)val, Ui.PaneColor, Ui.RowHover, Ui.RowPressed, Ui.RowSelected, Ui.RowSelectedHover); row.Click.OnClick = delegate { Select(row); }; return row; } protected void AddSearch(float width) { _search = Ui.SearchField((Transform)(object)Toolbar, delegate(string s) { SearchText = (s ?? "").Trim().ToLowerInvariant(); ApplyFilter(); }); Ui.Size((Component)(object)_search, width, 28f).flexibleWidth = ((width < 0f) ? 1f : 0f); } protected void ClearSearch() { SearchText = ""; if ((Object)(object)_search != (Object)null) { _search.SetTextWithoutNotify(""); } } protected void AddCycler(float width, Func<string> label, Action<int> step) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Ui.NewRect((Transform)(object)Toolbar, "Cycler"); Ui.HRow(((Component)val).gameObject, 2f, (TextAnchor)4); Ui.Size((Component)(object)val, width, 28f); ((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = Ui.PaneColor; TextMeshProUGUI text = null; Ui.Size((Component)(object)Ui.TextButton((Transform)(object)val, Ui.Arrows.left, 13f, delegate { step(-1); ((TMP_Text)text).text = label(); ApplyFilter(); }, header: true, "Prev"), 20f, 28f); text = Ui.Text((Transform)(object)val, label(), 13f, header: false, Ui.ValueColor, "Value"); ((TMP_Text)text).alignment = (TextAlignmentOptions)514; ((TMP_Text)text).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)text).overflowMode = (TextOverflowModes)1; Ui.Size((Component)(object)text, width - 46f, 28f); Ui.Size((Component)(object)Ui.TextButton((Transform)(object)val, Ui.Arrows.right, 13f, delegate { step(1); ((TMP_Text)text).text = label(); ApplyFilter(); }, header: true, "Next"), 20f, 28f); } protected static int Wrap(int i, int count) { return (i % count + count) % count; } protected void ApplyFilter() { //IL_01ac: Unknown result type (might be due to invalid IL or missing references) if (!_rowsBuilt) { return; } bool flag = SearchText.Length > 0; int num = 0; foreach (Row row in _rows) { bool flag2 = PassesFilters(row.Spec.Data, flag) && (!flag || (row.Spec.Search ?? row.Spec.Label.ToLowerInvariant()).Contains(SearchText)); row.Go.SetActive(flag2); if (flag2) { num++; } } foreach (Group group in _groups) { bool active = false; foreach (Row row2 in group.Rows) { if (row2.Go.activeSelf) { active = true; break; } } ((Component)((TMP_Text)group.Header).transform.parent).gameObject.SetActive(active); ((TMP_Text)group.Header).text = ((flag && group.SearchLabel != null) ? group.SearchLabel : group.Label); } ((Component)_emptyLabel).gameObject.SetActive(num == 0); if (_selected != null && !_selected.Go.activeSelf) { Select(null); } LayoutRebuilder.ForceRebuildLayoutImmediate(ListContent); ListContent.anchoredPosition = Vector2.zero; } private void Select(Row row) { if (_selected != null) { _selected.Click.Selected = false; _selected.Accent.SetActive(false); } _selected = row; if (row != null) { row.Click.Selected = true; row.Accent.SetActive(true); } ShowDetail(row?.Spec.Data); } protected void ClearSelection() { Select(null); } private void ShowDetail(object data) { //IL_0046: 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) Ui.ClearChildren((Transform)(object)DetailContent); try { if (data == null) { FillOverview(); } else { FillDetail(data); } } catch (Exception arg) { Plugin.ModLog.LogError((object)$"Codex: couldn't show {Title} entry: {arg}"); DText("Couldn't read this entry (see the BepInEx log).", 13f, Ui.DimColor); } LayoutRebuilder.ForceRebuildLayoutImmediate(DetailContent); DetailContent.anchoredPosition = Vector2.zero; } protected void RedrawDetail() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Vector2 anchoredPosition = DetailContent.anchoredPosition; ShowDetail(_selected?.Spec.Data); DetailContent.anchoredPosition = anchoredPosition; } protected TextMeshProUGUI DText(string text, float size = 13f, Color? color = null, Transform parent = null) { TextMeshProUGUI obj = Ui.Text((Transform)(((object)parent) ?? ((object)DetailContent)), text, size, header: false, color); ((TMP_Text)obj).lineSpacing = -4f; return obj; } protected void DHeader(string title, Color? titleColor, string subtitle, Sprite icon) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Ui.NewRect((Transform)(object)DetailContent, "Title"); Ui.HRow(((Component)val).gameObject, 10f, (TextAnchor)0); if ((Object)(object)icon != (Object)null) { Image obj = Ui.Rect((Transform)(object)val, "Icon", Color.white); obj.sprite = icon; obj.preserveAspect = true; Ui.Size((Component)(object)obj, 40f, 40f); } RectTransform val2 = Ui.NewRect((Transform)(object)val, "Text"); Ui.VColumn(((Component)val2).gameObject, 1f); Ui.Size((Component)(object)val2, -1f, -1f, 1f); ((TMP_Text)Ui.Text((Transform)(object)val2, title, 20f, header: true, titleColor)).textWrappingMode = (TextWrappingModes)1; if (!string.IsNullOrEmpty(subtitle)) { DText(subtitle, 12f, Ui.DimColor, (Transform)(object)val2); } } protected void DSection(string title) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) DSpacer(4f); ((TMP_Text)Ui.Text((Transform)(object)DetailContent, title.ToUpperInvariant(), 13f, header: true)).characterSpacing = 2f; Ui.Size((Component)(object)Ui.Rect((Transform)(object)DetailContent, "Rule", Ui.RuleColor), -1f, 1f); } protected void DSpacer(float h) { Ui.Size((Component)(object)Ui.NewRect((Transform)(object)DetailContent, "Spacer"), -1f, h); } protected void DStats(IList<(string label, string value)> stats) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); string text = Ui.Html(Ui.DimColor); string text2 = Ui.Html(Ui.ValueColor); for (int i = 0; i < stats.Count; i += 2) { if (i > 0) { stringBuilder.Append('\n'); } stringBuilder.Append("<color=" + text + ">" + stats[i].label + "</color><pos=31%><color=" + text2 + ">" + stats[i].value + "</color>"); if (i + 1 < stats.Count) { stringBuilder.Append("<pos=53%><color=" + text + ">" + stats[i + 1].label + "</color><pos=84%><color=" + text2 + ">" + stats[i + 1].value + "</color>"); } } ((TMP_Text)DText(stringBuilder.ToString())).lineSpacing = 6f; } protected RectTransform DRow(float spacing = 16f) { RectTransform obj = Ui.NewRect((Transform)(object)DetailContent, "Row"); Ui.HRow(((Component)obj).gameObject, spacing, (TextAnchor)3); return obj; } } [HarmonyPatch(typeof(OptionsManager), "Awake")] internal static class OptionsManager_Awake_Patch { private static void Postfix(OptionsManager __instance) { CodexTab.Install(__instance); } } [HarmonyPatch(typeof(OptionsManager), "CloseAllMenus")] internal static class OptionsManager_CloseAllMenus_Patch { private static void Postfix(OptionsManager __instance) { ((Component)__instance).GetComponent<CodexTab>()?.Hide(); } } [HarmonyPatch(typeof(OptionsManager), "LocalizeUI")] internal static class OptionsManager_LocalizeUI_Patch { private static void Postfix() { OptionsManager instance = OptionsManager.instance; if ((Object)(object)instance != (Object)null) { ((Component)instance).GetComponent<CodexTab>()?.RefreshLabel(); } } } [BepInPlugin("com.helvetica.codex", "Codex", "0.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : StolenRealmMod { public const string PluginGuid = "com.helvetica.codex"; public const string PluginName = "Codex"; public const string PluginVersion = "0.1.1"; internal static ManualLogSource ModLog; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> ShowSpecialEnemies; internal static ConfigEntry<bool> LogDataSummary; protected override void OnModLoaded() { ModLog = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show the Codex tab in the Options window."); ShowSpecialEnemies = ((BaseUnityPlugin)this).Config.Bind<bool>("Bestiary", "ShowSpecialEntries", false, "Also list characters that never appear in random battles (summons, props, story NPCs)."); LogDataSummary = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDataSummary", false, "Write a summary of what the Codex found (counts, skipped entries) to the BepInEx log once per launch."); Enabled.SettingChanged += delegate { CodexTab.ApplyEnabled(); }; ShowSpecialEnemies.SettingChanged += delegate { CodexTab.InvalidateData(); }; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Codex v0.1.1 loaded."); } } internal sealed class SkillTreesPage : ListPage { private static readonly Color IconFrame = Ui.Hex(1906195); private int _tree; private readonly List<Clickable> _treeButtons = new List<Clickable>(); private readonly Dictionary<SkillInfo, SkillTree> _treeOf = new Dictionary<SkillInfo, SkillTree>(); public override string Title => "Skill Trees"; private SkillTree Current { get { if (CodexData.Trees.Count <= 0) { return null; } return CodexData.Trees[_tree]; } } public SkillTreesPage(Ui ui) : base(ui) { } protected override void BuildToolbar() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) AddSearch(150f); List<SkillTree> trees = CodexData.Trees; float num = Mathf.Min(28f, 438f / (float)Mathf.Max(1, trees.Count) - 4f); RectTransform val = Ui.NewRect((Transform)(object)Toolbar, "Trees"); Ui.HRow(((Component)val).gameObject, 4f, (TextAnchor)3); for (int i = 0; i < trees.Count; i++) { int index = i; Image val2 = Ui.Rect((Transform)(object)val, "Tree (" + ((object)Unsafe.As<SkillType, SkillType>(ref trees[i].Type)/*cast due to .constrained prefix*/).ToString() + ")", IconFrame, raycast: true); Ui.Size((Component)(object)val2, num, num); Image val3 = Ui.Rect(((Component)val2).transform, "Icon", Color.white); Ui.Stretch(((Graphic)val3).rectTransform, 2f, 2f, 2f, 2f); val3.sprite = trees[i].Icon; val3.preserveAspect = true; if ((Object)(object)trees[i].Icon == (Object)null) { ((Behaviour)val3).enabled = false; TextMeshProUGUI obj = Ui.Text(((Component)val2).transform, trees[i].Name.Substring(0, 1), 14f, header: true); Ui.Stretch(((TMP_Text)obj).rectTransform); ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; } Clickable clickable = ((Component)val2).gameObject.AddComponent<Clickable>(); clickable.Init((Graphic)(object)val2, IconFrame, Ui.RowHover, Ui.RowPressed, Ui.RuleColor, Ui.Hex(6707018)); clickable.OnClick = delegate { SelectTree(index); }; _treeButtons.Add(clickable); } if (_treeButtons.Count > 0) { _treeButtons[0].Selected = true; } } private void SelectTree(int index) { if (index != _tree || SearchText.Length != 0) { _treeButtons[_tree].Selected = false; _tree = index; _treeButtons[_tree].Selected = true; ClearSearch(); ApplyFilter(); ClearSelection(); } } protected override IEnumerable<RowSpec> Rows() { foreach (SkillTree tree in CodexData.Trees) { foreach (SkillEntry skill in tree.Skills) { _treeOf[skill.Info] = tree; ActionInfo val = skill.Info.ActionsGranted?.FirstOrDefault((Func<ActionInfo, bool>)((ActionInfo a) => (Object)(object)a != (Object)null)); object obj; if (!skill.Passive) { string text = GameText.ConstOrNull(val?.Cost); obj = ((text != null) ? (text + " AP") : null); } else { obj = "Passive"; } string tag = (string)obj; yield return new RowSpec { Data = skill, Label = skill.Name, Tag = tag, TagColor = (skill.Passive ? Ui.DimColor : Ui.ValueColor), Icon = skill.Info.Icon, Search = skill.Search, GroupKey = ((object)Unsafe.As<SkillType, SkillType>(ref tree.Type)/*cast due to .constrained prefix*/).ToString() + "/" + skill.Info.Tier, GroupLabel = TierLabel(skill.Info.Tier), GroupLabelSearching = $"{tree.Name} · Tier {skill.Info.Tier}" }; } } } private static string TierLabel(int tier) { int num = CodexData.TierUnlock(tier); if (num <= 0) { return $"Tier {tier}"; } return $"Tier {tier} · {num} points in tree"; } protected override bool PassesFilters(object data, bool searching) { if (!searching) { if (Current != null && _treeOf.TryGetValue(((SkillEntry)data).Info, out var value)) { return value == Current; } return false; } return true; } protected override void FillOverview() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) SkillTree current = Current; if (current == null) { DText("No skill trees found.", 13f, Ui.DimColor); return; } int num = current.Skills.Count((SkillEntry s) => !s.Passive); int num2 = current.Skills.Count - num; DHeader(current.Name, null, $"{current.Skills.Count} skills · {num} active, {num2} passive", current.Icon); DSection("How tiers unlock"); List<string> list = new List<string>(); int tier; for (tier = 1; tier <= 5; tier++) { if (current.Skills.Any((SkillEntry s) => s.Info.Tier == tier)) { int num3 = CodexData.TierCost(tier); int num4 = CodexData.TierUnlock(tier); string text = ((num4 > 0) ? $"after {num4} points spent in this tree on lower tiers" : "available from the start"); list.Add(string.Format("{0}<pos=17%>{1} point{2} per skill, {3}", GameText.Color("Tier " + tier, Ui.ValueColor), num3, (num3 == 1) ? "" : "s", text)); } } ((TMP_Text)DText(string.Join("\n", list))).lineSpacing = 4f; DSpacer(6f); DText("Pick a skill on the left for its full description. Numbers are shown as scaling (for example \"150% Spell Power\"), since the real value depends on the hero using it. Typing in the search box searches every tree.", 13f, Ui.DimColor); } protected unsafe override void FillDetail(object data) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Invalid comparison between Unknown and I4 //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Invalid comparison between Unknown and I4 //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) SkillEntry skillEntry = (SkillEntry)data; SkillInfo info = skillEntry.Info; _treeOf.TryGetValue(info, out var value); int num = CodexData.TierCost(info.Tier); string subtitle = string.Format("{0} · Tier {1} · {2}", value?.Name ?? GameText.Enum<SkillType>(info.SkillType), info.Tier, skillEntry.Passive ? "Passive" : "Active") + string.Format(" · {0} skill point{1}", num, (num == 1) ? "" : "s"); DHeader(skillEntry.Name, null, subtitle, info.Icon); List<string> list = new List<string>(); if ((Object)(object)info.Dependency != (Object)null) { list.Add("Requires " + SkillName(info.Dependency)); } if (info.DisablingSkills != null && info.DisablingSkills.Length != 0) { list.Add("Can't be combined with " + string.Join(", ", info.DisablingSkills.Where((SkillInfo x) => (Object)(object)x != (Object)null).Select(SkillName))); } if (info.SkillsThatReplace != null && info.SkillsThatReplace.Length != 0 && !info.HideReplaceText) { list.Add("Replaced by " + string.Join(", ", info.SkillsThatReplace.Where((SkillInfo x) => (Object)(object)x != (Object)null).Select(SkillName))); } if (list.Count > 0) { DText(string.Join("\n", list), 12f, Ui.TermColor); } if (info.ActionsGranted != null) { foreach (ActionInfo item in info.ActionsGranted.Where((ActionInfo a) => (Object)(object)a != (Object)null)) { string text = GameText.ActionMeta(item); DamageType val = (((int)info.DamageType != 9) ? info.DamageType : item.DamageType); if ((int)val != 9) { text = text + " · " + GameText.DamageTypeName(val); } DText(text, 12f, Ui.DimColor); } } DSpacer(2f); string text2 = GameText.Description(info.Description, info.DescriptionExpressions); if (string.IsNullOrEmpty(text2)) { ActionInfo val2 = info.ActionsGranted?.FirstOrDefault((Func<ActionInfo, bool>)((ActionInfo x) => (Object)(object)x != (Object)null)); if ((Object)(object)val2 != (Object)null) { text2 = GameText.Description(val2.Description, val2.DescriptionExpressions); } } DText(string.IsNullOrEmpty(text2) ? "No description." : text2, 14f); if (!string.IsNullOrWhiteSpace(info.UpgradeText)) { DSection("Upgrade"); DText(GameText.Description(info.UpgradeText, info.DescriptionExpressions)); } if (info.SkillTags != null && info.SkillTags.Count > 0) { DSpacer(4f); DText(string.Join(" · ", info.SkillTags.Select((SkillTag t) => GameText.SplitCamel(((object)(*(SkillTag*)(&t))/*cast due to .constrained prefix*/).ToString()))), 11f, Ui.DimColor); } } private static string SkillName(SkillInfo s) { string text = GameText.L(s.SkillName, (LanguageGender)0, (Gender)2); if (!string.IsNullOrWhiteSpace(text)) { return text; } return GameText.SplitCamel(((Object)s).name); } } internal sealed class Ui { public static readonly Color PaneColor = Hex(1314573); public static readonly Color RowHover = Hex(2826523); public static readonly Color RowPressed = Hex(4338474); public static readonly Color RowSelected = Hex(3812386); public static readonly Color RowSelectedHover = Hex(4535594); public static readonly Color GroupColor = Hex(2234901); public static readonly Color RuleColor = Hex(5523517); public static readonly Color ScrollTrack = Hex(1709073); public static readonly Color ScrollHandle = Hex(5917502); public static readonly Color ValueColor = Hex(15918800); public static readonly Color DimColor = Hex(9208180); public static readonly Color TermColor = Hex(15255418); public static readonly Color StatusColor = Hex(9355750); public static readonly Color ScalingColor = Hex(15784360); public TMP_FontAsset BodyFont; public TMP_FontAsset HeaderFont; public Material BodyMaterial; public Material HeaderMaterial; public Color TextColor = Hex(14273979); public Color HeaderColor = Hex(13349782); public Color UnselectedColor = Hex(6974058); public TMP_InputField InputTemplate; private static readonly HashSet<string> LocalizationComponents = new HashSet<string> { "LocalizedObject", "ManualLocalization", "LocalizationSetting", "PrefabLocalizer" }; private (string left, string right)? _arrows; public (string left, string right) Arrows { get { if (_arrows.HasValue) { return _arrows.Value; } _arrows = ((Has('◄') && Has('►')) ? ("◄", "►") : ("<", ">")); return _arrows.Value; bool Has(char c) { if ((Object)(object)HeaderFont != (Object)null) { return HeaderFont.HasCharacter(c, true, true); } return false; } } } public static Color Hex(int rgb) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) return new Color((float)((rgb >> 16) & 0xFF) / 255f, (float)((rgb >> 8) & 0xFF) / 255f, (float)(rgb & 0xFF) / 255f); } public static string Html(Color c) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return "#" + ColorUtility.ToHtmlStringRGB(c); } public static Ui FromOptions(OptionsManager om, MenuTab tabStyle, MenuTabManager tabs) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_0085: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_0116: Unknown result type (might be due to invalid IL or missing references) Ui ui = new Ui(); Traverse val = Traverse.Create((object)om); ui.InputTemplate = val.Field("twitchServerNameInputField").GetValue<TMP_InputField>(); TextMeshProUGUI val2 = (((Object)(object)tabStyle != (Object)null) ? tabStyle.TextMeshProUGUI : null); if ((Object)(object)val2 != (Object)null) { ui.HeaderFont = ((TMP_Text)val2).font; ui.HeaderMaterial = ((TMP_Text)val2).fontSharedMaterial; } if ((Object)(object)tabs != (Object)null) { Traverse val3 = Traverse.Create((object)tabs); ui.HeaderColor = Opaque(val3.Field("SelectedColor").GetValue<Color>(), ui.HeaderColor); ui.UnselectedColor = Opaque(val3.Field("UnselectedColor").GetValue<Color>(), ui.UnselectedColor); } GameObject value = val.Field("gameplayPanel").GetValue<GameObject>(); if ((Object)(object)value != (Object)null) { TextMeshProUGUI[] componentsInChildren = value.GetComponentsInChildren<TextMeshProUGUI>(true); foreach (TextMeshProUGUI val4 in componentsInChildren) { if (!string.IsNullOrWhiteSpace(((TMP_Text)val4).text)) { ui.BodyFont = ((TMP_Text)val4).font; ui.BodyMaterial = ((TMP_Text)val4).fontSharedMaterial; ui.TextColor = Opaque(((Graphic)val4).color, ui.TextColor); break; } } } if ((Object)(object)ui.BodyFont == (Object)null) { ui.BodyFont = ui.HeaderFont ?? TMP_Settings.defaultFontAsset; ui.BodyMaterial = null; } if ((Object)(object)ui.HeaderFont == (Object)null) { ui.HeaderFont = ui.BodyFont; ui.HeaderMaterial = ui.BodyMaterial; } return ui; } private static Color Opaque(Color c, Color fallback) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!(c.a <= 0.01f)) { return new Color(c.r, c.g, c.b, 1f); } return fallback; } public static RectTransform NewRect(Transform parent, string name) { //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; } public static RectTransform Stretch(RectTransform rt, float left = 0f, float top = 0f, float right = 0f, float bottom = 0f) { //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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.pivot = new Vector2(0.5f, 0.5f); rt.offsetMin = new Vector2(left, bottom); rt.offsetMax = new Vector2(0f - right, 0f - top); return rt; } public static RectTransform TopStrip(RectTransform rt, float y, float height) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_005b: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0f, 1f); rt.anchorMax = new Vector2(1f, 1f); rt.pivot = new Vector2(0.5f, 1f); rt.offsetMin = new Vector2(0f, 0f - y - height); rt.offsetMax = new Vector2(0f, 0f - y); return rt; } public static Image Rect(Transform parent, string name, Color color, bool raycast = false) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)NewRect(parent, name)).gameObject.AddComponent<Image>(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = raycast; return obj; } public TextMeshProUGUI Text(Transform parent, string text, float size, bool header = false, Color? color = null, string name = null) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = ((Component)NewRect(parent, name ?? (header ? "Header" : "Text"))).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val).font = (header ? HeaderFont : BodyFont); Material val2 = (header ? HeaderMaterial : BodyMaterial); if ((Object)(object)val2 != (Object)null) { ((TMP_Text)val).fontSharedMaterial = val2; } ((TMP_Text)val).fontSize = size; ((Graphic)val).color = (Color)(((??)color) ?? (header ? HeaderColor : TextColor)); ((TMP_Text)val).richText = true; ((Graphic)val).raycastTarget = false; ((TMP_Text)val).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)val).alignment = (TextAlignmentOptions)257; ((TMP_Text)val).text = text; return val; } public static LayoutElement Size(Component c, float width = -1f, float height = -1f, float flexWidth = -1f) { LayoutElement val = c.GetComponent<LayoutElement>() ?? c.gameObject.AddComponent<LayoutElement>(); if (width >= 0f) { float minWidth = (val.preferredWidth = width); val.minWidth = minWidth; } if (height >= 0f) { float minWidth = (val.preferredHeight = height); val.minHeight = minWidth; } if (flexWidth >= 0f) { val.flexibleWidth = flexWidth; } return val; } public static HorizontalLayoutGroup HRow(GameObject go, float spacing, TextAnchor align = (TextAnchor)3, RectOffset padding = null) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) HorizontalLayoutGroup val = go.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val).spacing = spacing; ((LayoutGroup)val).childAlignment = align; bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)val).childControlHeight = true); ((HorizontalOrVerticalLayoutGroup)val).childControlWidth = childControlWidth; childControlWidth = (((HorizontalOrVerticalLayoutGroup)val).childForceExpandHeight = false); ((HorizontalOrVerticalLayoutGroup)val).childForceExpandWidth = childControlWidth; if (padding != null) { ((LayoutGroup)val).padding = padding; } return val; } public static VerticalLayoutGroup VColumn(GameObject go, float spacing, RectOffset padding = null) { VerticalLayoutGroup val = go.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val).spacing = spacing; bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)val).childControlHeight = true); ((HorizontalOrVerticalLayoutGroup)val).childControlWidth = childControlWidth; ((HorizontalOrVerticalLayoutGroup)val).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val).childForceExpandHeight = false; if (padding != null) { ((LayoutGroup)val).padding = padding; } return val; } public static ScrollRect ScrollView(RectTransform root, out RectTransform content, RectOffset padding, float spacing) { //IL_000b: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_009f: 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_00e4: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) ((Graphic)((Component)root).gameObject.AddComponent<Image>()).color = PaneColor; RectTransform val = Stretch(NewRect((Transform)(object)root, "Viewport")); ((Component)val).gameObject.AddComponent<RectMask2D>(); content = NewRect((Transform)(object)val, "Content"); content.anchorMin = new Vector2(0f, 1f); content.anchorMax = new Vector2(1f, 1f); content.pivot = new Vector2(0.5f, 1f); RectTransform obj = content; Vector2 offsetMin = (content.offsetMax = Vector2.zero); obj.offsetMin = offsetMin; VColumn(((Component)content).gameObject, spacing, padding); ((Component)content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; RectTransform obj2 = NewRect((Transform)(object)root, "Scrollbar"); obj2.anchorMin = new Vector2(1f, 0f); obj2.anchorMax = new Vector2(1f, 1f); obj2.pivot = new Vector2(1f, 0.5f); obj2.sizeDelta = new Vector2(6f, 0f); obj2.anchoredPosition = Vector2.zero; ((Graphic)((Component)obj2).gameObject.AddComponent<Image>()).color = ScrollTrack; RectTransform val2 = Stretch(NewRect((Transform)(object)Stretch(NewRect((Transform)(object)obj2, "Sliding Area")), "Handle")); Image val3 = ((Component)val2).gameObject.AddComponent<Image>(); ((Graphic)val3).color = ScrollHandle; Scrollbar val4 = ((Component)obj2).gameObject.AddComponent<Scrollbar>(); val4.direction = (Direction)2; val4.handleRect = val2; ((Selectable)val4).targetGraphic = (Graphic)(object)val3; ColorBlock colors = ((Selectable)val4).colors; ((ColorBlock)(ref colors)).highlightedColor = new Color(1.25f, 1.25f, 1.25f, 1f); ((ColorBlock)(ref colors)).fadeDuration = 0.05f; ((Selectable)val4).colors = colors; ScrollRect obj3 = ((Component)root).gameObject.AddComponent<ScrollRect>(); obj3.viewport = val; obj3.content = content; obj3.horizontal = false; obj3.movementType = (MovementType)2; obj3.scrollSensitivity = 30f; obj3.verticalScrollbar = val4; obj3.verticalScrollbarVisibility = (ScrollbarVisibility)2; obj3.verticalScrollbarSpacing = 2f; return obj3; } public Clickable TextButton(Transform parent, string labe