Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ItemRecommender v0.9.0
ItemRecommender.dll
Decompiled 4 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.Collections.ObjectModel; using System.Diagnostics; using System.IO; 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.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HG; using HarmonyLib; using Microsoft.CodeAnalysis; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Skills; using RoR2.UI; using TMPro; using UnityEngine; 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("ItemRecommender")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+67389cb27a7774c11f1c5b24c271963b7b04cbc3")] [assembly: AssemblyProduct("ItemRecommender")] [assembly: AssemblyTitle("ItemRecommender")] [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 ItemRecommender { public sealed class Entry { public int Tier; public string De; public string En; } public sealed class Synergy { public string Have; public string Want; public int Kind; public string De; public string En; } public sealed class Advice { public int Tier; public string Reason; public readonly List<string> SynergyReasons = new List<string>(); public readonly List<string> Warnings = new List<string>(); public readonly List<string> BuildReasons = new List<string>(); public readonly List<string> Notes = new List<string>(); public int Bonus; public readonly HashSet<string> RuleHaves = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public int Score => Tier * 10 + SynergyReasons.Count + Bonus / 4; } public sealed class BuildData { public const int MinTier = -2; public const int MaxTier = 2; private const string DefaultSection = "Default"; private const string SynergySection = "Synergy"; private static readonly Regex RuleRegex = new Regex("^(.+?)\\s*(!{0,2})\\s*(<>|>)\\s*(.+)$"); private readonly ManualLogSource log; private readonly string path; private DateTime loadedStamp = DateTime.MinValue; private bool validated; private readonly Dictionary<string, Dictionary<string, Entry>> sections = new Dictionary<string, Dictionary<string, Entry>>(StringComparer.OrdinalIgnoreCase); private readonly List<Synergy> rules = new List<Synergy>(); private readonly Dictionary<string, List<List<PathStep>>> paths = new Dictionary<string, List<List<PathStep>>>(StringComparer.OrdinalIgnoreCase); private static readonly Regex StepRegex = new Regex("^(\\S+?)(?:\\s*[x\\*]\\s*(\\d+))?$", RegexOptions.IgnoreCase); public BuildData(string path, ManualLogSource log) { this.path = path; this.log = log; } public void ReloadIfChanged() { DateTime lastWriteTimeUtc; try { lastWriteTimeUtc = File.GetLastWriteTimeUtc(path); } catch { return; } if (lastWriteTimeUtc != loadedStamp) { loadedStamp = lastWriteTimeUtc; Load(); validated = false; } ValidateOnce(); } private void Load() { sections.Clear(); rules.Clear(); paths.Clear(); string[] array; try { array = File.ReadAllLines(path); } catch (Exception ex) { log.LogError((object)("Could not read " + path + ": " + ex.Message)); return; } List<string> list = new List<string> { "Default" }; for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0 || text.StartsWith("#")) { continue; } if (text.StartsWith("[") && text.EndsWith("]")) { list = new List<string>(); string[] array2 = text.Substring(1, text.Length - 2).Split(','); foreach (string text2 in array2) { if (text2.Trim().Length > 0) { list.Add(text2.Trim()); } } continue; } if (text.StartsWith("Path:", StringComparison.OrdinalIgnoreCase)) { List<PathStep> list2 = ParsePath(text.Substring(5), i + 1); foreach (string item in list) { if (!paths.TryGetValue(item, out var value)) { value = (paths[item] = new List<List<PathStep>>()); } if (list2.Count > 0) { value.Add(list2); } } continue; } string[] array3 = text.Split('|'); for (int k = 0; k < array3.Length; k++) { array3[k] = array3[k].Trim(); } if (list.Count == 1 && list[0].Equals("Synergy", StringComparison.OrdinalIgnoreCase)) { ParseRule(array3, i + 1); continue; } if (array3.Length < 2 || !int.TryParse(array3[1], out var result)) { log.LogWarning((object)$"builds.txt line {i + 1}: expected 'Item | Tier | DE | EN'"); continue; } Entry value2 = new Entry { Tier = Math.Max(-2, Math.Min(2, result)), De = ((array3.Length > 2) ? array3[2] : ""), En = ((array3.Length > 3) ? array3[3] : ((array3.Length > 2) ? array3[2] : "")) }; foreach (string item2 in list) { if (!sections.TryGetValue(item2, out var value3)) { value3 = (sections[item2] = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase)); } value3[array3[0]] = value2; } } log.LogInfo((object)$"Loaded builds: {sections.Count} sections, {rules.Count} synergy rules, {paths.Count} build paths"); } private List<PathStep> ParsePath(string text, int lineNo) { List<PathStep> list = new List<PathStep>(); string[] array = text.Split('>', '<', ','); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0) { Match match = StepRegex.Match(text2); if (!match.Success) { log.LogWarning((object)$"builds.txt line {lineNo}: expected 'Path: Item x10 > Item x5 > ...', got '{text2}'"); continue; } int target = ((!match.Groups[2].Success) ? 1 : Math.Max(1, int.Parse(match.Groups[2].Value))); list.Add(new PathStep { Item = match.Groups[1].Value, Target = target }); } } return list; } public List<List<PathStep>> GetPath(string bodyName) { if (bodyName != null && paths.TryGetValue(bodyName, out var value)) { return value; } if (!paths.TryGetValue("Default", out value)) { return null; } return value; } public IEnumerable<string> CandidateItems(string bodyName) { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (sections.TryGetValue("Default", out var value)) { hashSet.UnionWith(value.Keys); } if (bodyName != null && sections.TryGetValue(bodyName, out var value2)) { hashSet.UnionWith(value2.Keys); } foreach (Synergy rule in rules) { if (rule.Kind > 0) { hashSet.Add(rule.Want); } } return hashSet; } private void ParseRule(string[] parts, int lineNo) { Match match = RuleRegex.Match(parts[0]); if (!match.Success) { log.LogWarning((object)$"builds.txt line {lineNo}: expected 'A > B', 'A <> B', 'A !> B' or 'A !!> B'"); return; } string text = match.Groups[1].Value.Trim(); string text2 = match.Groups[4].Value.Trim(); int kind = ((match.Groups[2].Value.Length == 0) ? 1 : (-match.Groups[2].Value.Length)); bool num = match.Groups[3].Value == "<>"; string text3 = ((parts.Length > 1) ? parts[1] : ""); string en = ((parts.Length > 2) ? parts[2] : text3); rules.Add(new Synergy { Have = text, Want = text2, Kind = kind, De = text3, En = en }); if (num) { rules.Add(new Synergy { Have = text2, Want = text, Kind = kind, De = text3, En = en }); } } private void ValidateOnce() { //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Invalid comparison between Unknown and I4 //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Invalid comparison between Unknown and I4 if (validated || ItemCatalog.itemCount == 0) { return; } validated = true; HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (Dictionary<string, Entry> value in sections.Values) { foreach (string key in value.Keys) { hashSet.Add(key); } } foreach (Synergy rule in rules) { hashSet.Add(rule.Have); hashSet.Add(rule.Want); } foreach (List<List<PathStep>> value2 in paths.Values) { foreach (List<PathStep> item in value2) { foreach (PathStep item2 in item) { hashSet.Add(item2.Item); } } } foreach (string item3 in hashSet) { if ((int)ItemCatalog.FindItemIndex(item3) == -1 && (int)EquipmentCatalog.FindEquipmentIndex(item3) == -1) { log.LogWarning((object)("builds.txt: unknown item/equipment name '" + item3 + "'")); } } } private Entry Lookup(string bodyName, string itemName) { if (bodyName != null && sections.TryGetValue(bodyName, out var value) && value.TryGetValue(itemName, out var value2)) { return value2; } if (sections.TryGetValue("Default", out var value3) && value3.TryGetValue(itemName, out value2)) { return value2; } return null; } private int TierOf(string bodyName, string itemName) { return Lookup(bodyName, itemName)?.Tier ?? 0; } public Advice Get(string bodyName, string itemName, Func<string, int> countOf, bool german, BuildProfile profile = null) { Advice advice = new Advice(); Entry entry = Lookup(bodyName, itemName); int num = entry?.Tier ?? 0; if (entry != null) { advice.Reason = (german ? entry.De : entry.En); } int val = 0; foreach (Synergy rule in rules) { if (rule.Want.Equals(itemName, StringComparison.OrdinalIgnoreCase) && countOf(rule.Have) > 0) { string item = DisplayName(rule.Have) + ": " + (german ? rule.De : rule.En); if (rule.Kind > 0) { advice.SynergyReasons.Add(item); advice.RuleHaves.Add(rule.Have); } else { advice.Warnings.Add(item); val = Math.Min(val, rule.Kind); } } } val = Math.Min(val, VoidWarnings(bodyName, itemName, num, countOf, german, advice, out var floor)); try { profile?.Apply(itemName, advice, german); } catch (Exception ex) { log.LogWarning((object)("Build analysis failed for " + itemName + ": " + ex.Message)); } if (num >= 0) { int num2 = ((advice.SynergyReasons.Count > 0) ? 1 : 0) + ((advice.Bonus >= 12) ? 1 : 0); num = Math.Min(2, num + num2); if (num == 0 && advice.Bonus >= 6) { num = 1; } if (num > 0 && advice.Bonus <= -10) { num--; } } num = Math.Max(num, floor); if (val < 0) { num = Math.Min(num, val); } advice.Tier = num; return advice; } private int VoidWarnings(string bodyName, string itemName, int ownTier, Func<string, int> countOf, bool german, Advice advice, out int floor) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0040: 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) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) floor = -2; ItemIndex val = ItemCatalog.FindItemIndex(itemName); if ((int)val == -1 || (Object)(object)ItemRelationshipTypes.ContagiousItem == (Object)null) { return 0; } int num = 0; Enumerator<Pair> enumerator = ItemCatalog.GetItemPairsForRelationship(ItemRelationshipTypes.ContagiousItem).GetEnumerator(); try { while (enumerator.MoveNext()) { Pair current = enumerator.Current; if (!Object.op_Implicit((Object)(object)current.itemDef1) || !Object.op_Implicit((Object)(object)current.itemDef2)) { continue; } string name = ((Object)current.itemDef1).name; string name2 = ((Object)current.itemDef2).name; if (current.itemDef2.itemIndex == val) { int num2 = countOf(name); if (num2 > 0) { int num3 = TierOf(bodyName, name); if (ownTier > num3) { advice.SynergyReasons.Add(german ? $"Ersetzt deine {num2}x {DisplayName(name)} – hier lohnt es sich." : $"Replaces your {num2}x {DisplayName(name)} – worth it here."); continue; } int val2 = ((num3 >= 1) ? (-2) : (-1)); advice.Warnings.Add(german ? $"Wandelt deine {num2}x {DisplayName(name)} in {DisplayName(name2)} um!" : $"Converts your {num2}x {DisplayName(name)} into {DisplayName(name2)}!"); num = Math.Min(num, val2); } } else if (current.itemDef1.itemIndex == val && countOf(name2) > 0) { int num4 = countOf(name2); int num5 = TierOf(bodyName, name2); if (num5 < 0) { advice.Warnings.Add(german ? ("Wird zu " + DisplayName(name2) + " – das lohnt sich hier nicht.") : ("Turns into " + DisplayName(name2) + " – not worth it here.")); num = Math.Min(num, num5); } else { advice.SynergyReasons.Add(german ? $"Wird zu {DisplayName(name2)} (du hast {num4}x) – mehr Stacks!" : $"Becomes {DisplayName(name2)} (you have {num4}x) – more stacks!"); floor = Math.Max(floor, Math.Max(1, num5)); } } } return num; } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } public static string DisplayName(string internalName) { //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_000b: 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) ItemIndex val = ItemCatalog.FindItemIndex(internalName); if ((int)val != -1) { return Language.GetString(ItemCatalog.GetItemDef(val).nameToken); } EquipmentIndex val2 = EquipmentCatalog.FindEquipmentIndex(internalName); if ((int)val2 != -1) { return Language.GetString(EquipmentCatalog.GetEquipmentDef(val2).nameToken); } return internalName; } } public sealed class PathStep { public string Item; public int Target; public bool Optional; } public sealed class PathTile : MonoBehaviour { private sealed class Snapshot { public string Number; public List<PathStep> Steps; } private sealed class Cand { public char Role; public bool Rare; public bool Used; public int Score; public PathStep Step; } private const float Icon = 20f; private const float Sep = 8f; private const float Gap = 2f; private const float Pad = 6f; private const float CountH = 11f; private const float DefaultWidth = 260f; private const int PageSize = 10; private const string TileName = "ItemRecommenderBuildPath"; private static bool loggedStyle; private HUD hud; private RectTransform objective; private LayoutElement layout; private bool inLayoutGroup; private Image bg; private TMP_Text headerStyle; private float titleH = 22f; private RectTransform content; private string signature; private float nextRefresh; private readonly List<AsyncImage> pendingIcons = new List<AsyncImage>(); private const int GenSize = 8; private List<PathStep> genPage; private int genNumber = 1; private string genBody; private readonly HashSet<string> lastPageItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> pageBeforeItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> skipped = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private bool skipStart; private bool onStartPage; private List<PathStep> shownSteps; private string currentItem; private Run lastRun; private const int MaxHistory = 50; private readonly List<Snapshot> history = new List<Snapshot>(); private int back; private string currentNumber; private List<PathStep> currentSteps; private string savedState; private bool rarityView; private static Dictionary<string, HashSet<string>> voidPairs; private static readonly HashSet<string> Empty = new HashSet<string>(); private static Dictionary<string, string> voidOf; private static Dictionary<string, List<string>> normalsOf; private static readonly List<string> NoNames = new List<string>(); private static string StatePath => Path.Combine(Paths.ConfigPath, "ItemRecommender.state.txt"); public static void Ensure(HUD hud) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)hud) || Object.op_Implicit((Object)(object)((Component)hud).GetComponentInChildren<PathTile>(true))) { return; } ObjectivePanelController componentInChildren = ((Component)hud).GetComponentInChildren<ObjectivePanelController>(true); if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)((Component)componentInChildren).transform.parent)) { GameObject val = new GameObject("ItemRecommenderBuildPath", new Type[1] { typeof(RectTransform) }); Transform parent = ((Component)componentInChildren).transform.parent; val.transform.SetParent(parent, false); PathTile pathTile = val.AddComponent<PathTile>(); pathTile.hud = hud; pathTile.objective = (RectTransform)((Component)componentInChildren).transform; pathTile.layout = val.AddComponent<LayoutElement>(); pathTile.inLayoutGroup = Object.op_Implicit((Object)(object)((Component)parent).GetComponent<VerticalLayoutGroup>()); if (pathTile.inLayoutGroup) { val.transform.SetSiblingIndex(((Component)componentInChildren).transform.GetSiblingIndex() + 1); } else { pathTile.layout.ignoreLayout = true; } pathTile.Build(); } } private void Build() { //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_000c: 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_0034: 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_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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)((Component)this).transform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(1f, 1f); val.anchorMax = val2; val.anchorMin = val2; val.pivot = new Vector2(1f, 1f); bg = Ui.MakeImage(((Component)this).transform, "Bg", Sprites.Fill); ((Graphic)bg).color = Palette.Panel; bg.preserveAspect = false; Ui.Place(((Graphic)bg).rectTransform, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero); CopyObjectiveStyle(); GameObject val3 = new GameObject("Content", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(((Component)this).transform, false); content = (RectTransform)val3.transform; Ui.Place(content, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero); SetVisible(on: false); } private void CopyObjectiveStyle() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) Image val = null; float num = 0f; Image[] componentsInChildren = ((Component)objective).GetComponentsInChildren<Image>(true); foreach (Image val2 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val2.sprite)) { Rect rect = ((Graphic)val2).rectTransform.rect; if (((Rect)(ref rect)).width * ((Rect)(ref rect)).height > num) { num = ((Rect)(ref rect)).width * ((Rect)(ref rect)).height; val = val2; } } } if (Object.op_Implicit((Object)(object)val)) { bg.sprite = val.sprite; bg.type = val.type; ((Graphic)bg).color = ((Graphic)val).color; ((Graphic)bg).material = ((Graphic)val).material; bg.pixelsPerUnitMultiplier = val.pixelsPerUnitMultiplier; bg.fillCenter = val.fillCenter; } TMP_Text[] componentsInChildren2 = ((Component)objective).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val3 in componentsInChildren2) { if (Object.op_Implicit((Object)(object)((Component)val3).GetComponent<LanguageTextMeshController>())) { headerStyle = val3; break; } } if (Object.op_Implicit((Object)(object)headerStyle)) { titleH = Mathf.Max(22f, headerStyle.fontSize + 8f); } if (!loggedStyle) { loggedStyle = true; Plugin.Log.LogInfo((object)(string.Format("Build path tile: layout group={0}, background={1}, ", inLayoutGroup, Object.op_Implicit((Object)(object)val) ? (((Object)val).name + "/" + ((Object)val.sprite).name) : "none") + "heading=" + (Object.op_Implicit((Object)(object)headerStyle) ? (((Object)headerStyle).name + " " + headerStyle.fontSize) : "none"))); } } private void SetVisible(bool on) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) ((Behaviour)bg).enabled = on; ((Component)content).gameObject.SetActive(on); layout.ignoreLayout = !on || !inLayoutGroup; if (!on) { ((RectTransform)((Component)this).transform).sizeDelta = Vector2.zero; } } private void Update() { HandleHotkeys(); if (Time.unscaledTime < nextRefresh) { return; } nextRefresh = Time.unscaledTime + 0.5f; try { Refresh(); } catch (Exception ex) { Plugin.Log.LogError((object)ex); nextRefresh = Time.unscaledTime + 10f; } } private void LateUpdate() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (!inLayoutGroup && Object.op_Implicit((Object)(object)objective) && ((Behaviour)bg).enabled) { Vector3[] array = (Vector3[])(object)new Vector3[4]; objective.GetWorldCorners(array); Vector3 val = ((Transform)(RectTransform)((Component)this).transform.parent).InverseTransformPoint(array[3]); ((Component)this).transform.localPosition = new Vector3(val.x, val.y, 0f); } } private void Refresh() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) for (int num = pendingIcons.Count - 1; num >= 0; num--) { AsyncImage val = pendingIcons[num]; if (!Object.op_Implicit((Object)(object)val) || Object.op_Implicit((Object)(object)((AsyncViewable<Sprite, Image>)(object)val).renderer.sprite)) { pendingIcons.RemoveAt(num); } else { ((AsyncViewable<Sprite, Image>)(object)val).LoadAssetReference(); } } CharacterBody val2 = ((Object.op_Implicit((Object)(object)hud) && Object.op_Implicit((Object)(object)hud.targetBodyObject)) ? hud.targetBodyObject.GetComponent<CharacterBody>() : null); if (!Plugin.Enabled.Value || !Plugin.ShowBuildPath.Value || !Object.op_Implicit((Object)(object)val2)) { if (((Behaviour)bg).enabled) { SetVisible(on: false); signature = null; } return; } Plugin.Data.ReloadIfChanged(); string bodyName = BodyCatalog.GetBodyName(val2.bodyIndex); List<List<PathStep>> list = Paginate(Plugin.Data.GetPath(bodyName)); if (list.Count == 0) { if (((Behaviour)bg).enabled) { SetVisible(on: false); signature = null; } return; } bool flag = Plugin.German(); if ((Object)(object)lastRun != (Object)(object)Run.instance) { lastRun = Run.instance; skipStart = false; skipped.Clear(); genPage = null; genNumber = 1; genBody = null; lastPageItems.Clear(); pageBeforeItems.Clear(); history.Clear(); back = 0; currentNumber = null; currentSteps = null; LoadState(bodyName); } float num2; if (inLayoutGroup && Object.op_Implicit((Object)(object)objective)) { Rect rect = objective.rect; if (((Rect)(ref rect)).width > 100f) { rect = objective.rect; num2 = ((Rect)(ref rect)).width; goto IL_01e9; } } num2 = 260f; goto IL_01e9; IL_01e9: float num3 = num2; if (rarityView) { RefreshRarity(val2, bodyName, flag, num3); return; } List<PathStep> list2 = null; List<PathStep> list3 = list[0].FindAll((PathStep st) => !skipped.Contains(st.Item)); bool flag2 = skipStart || Complete(val2, list3); onStartPage = !flag2; list2 = ((flag2 && Plugin.LivePages.Value) ? GeneratedPage(val2, bodyName, flag, list) : (flag2 ? list[list.Count - 1] : list3)); string text = ""; if (list2 == null) { list2 = list[list.Count - 1]; } else if (flag2 && Plugin.LivePages.Value) { text = genNumber.ToString(); } else if (!flag2) { text = "1"; } if (currentNumber != null && currentNumber != text) { history.Add(new Snapshot { Number = currentNumber, Steps = currentSteps }); if (history.Count > 50) { history.RemoveAt(0); } } currentNumber = text; currentSteps = list2.ConvertAll((PathStep st) => new PathStep { Item = st.Item, Target = st.Target, Optional = st.Optional }); SaveState(bodyName); string text2 = PageLabel(flag, text); if (back > history.Count) { back = history.Count; } if (back > 0) { Snapshot snapshot = history[history.Count - back]; list2 = snapshot.Steps; text2 = PageLabel(flag, snapshot.Number) + (flag ? " (zurück)" : " (back)"); } list2 = MapVoid(val2, list2); int[] array = new int[list2.Count]; StringBuilder stringBuilder = new StringBuilder(bodyName).Append(flag).Append(Plugin.PathSeparator.Value); for (int num4 = 0; num4 < list2.Count; num4++) { array[num4] = PathCount(val2, list2[num4].Item); stringBuilder.Append('|').Append(list2[num4].Item).Append(list2[num4].Target) .Append(':') .Append(array[num4]); } stringBuilder.Append(num3).Append('#').Append(text2) .Append(Plugin.HintSignature()); if (!(stringBuilder.ToString() == signature)) { signature = stringBuilder.ToString(); Rebuild(list2, array, num3, flag, text2); } } private void HandleHotkeys() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)bg) || !((Behaviour)bg).enabled) { return; } KeyboardShortcut value = Plugin.SwitchViewKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { rarityView = !rarityView; signature = null; nextRefresh = 0f; } else { if (rarityView) { return; } bool flag = false; value = Plugin.BackPageKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (back < history.Count) { back++; flag = true; } } else if (back > 0) { value = Plugin.SkipPageKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { back--; flag = true; } } else { if (shownSteps == null) { return; } value = Plugin.SkipItemKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && currentItem != null) { skipped.Add(currentItem); foreach (string item in NormalsOf(currentItem)) { skipped.Add(item); } if (genPage != null) { genPage.RemoveAll((PathStep st) => skipped.Contains(st.Item)); } flag = true; } else { value = Plugin.SkipPageKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (onStartPage) { skipStart = true; } else if (genPage != null) { foreach (PathStep item2 in genPage) { skipped.Add(item2.Item); lastPageItems.Add(item2.Item); } genPage = null; } flag = true; } } } if (flag) { signature = null; nextRefresh = 0f; } } } private static bool Complete(CharacterBody body, List<PathStep> steps) { bool flag = steps.TrueForAll((PathStep st) => st.Optional); foreach (PathStep step in steps) { if ((flag || !step.Optional) && PathCount(body, step.Item) < step.Target) { return false; } } return true; } private List<PathStep> GeneratedPage(CharacterBody body, string bodyName, bool german, List<List<PathStep>> filePages) { //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Invalid comparison between Unknown and I4 //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Invalid comparison between Unknown and I4 //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Invalid comparison between Unknown and I4 //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Invalid comparison between Unknown and I4 //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Invalid comparison between Unknown and I4 //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Invalid comparison between Unknown and I4 //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Invalid comparison between Unknown and I4 //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Invalid comparison between Unknown and I4 //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Invalid comparison between Unknown and I4 if (genBody != bodyName) { if (genBody != null) { history.Clear(); back = 0; } genPage = null; genNumber = 1; genBody = bodyName; lastPageItems.Clear(); pageBeforeItems.Clear(); } if (genPage != null && genPage.Count > 0 && Complete(body, genPage)) { pageBeforeItems.Clear(); pageBeforeItems.UnionWith(lastPageItems); lastPageItems.Clear(); foreach (PathStep item in genPage) { lastPageItems.Add(item.Item); } genPage = null; } if (genPage != null && genPage.Count >= 8) { return genPage; } if (genPage == null) { genPage = new List<PathStep>(); genNumber++; } Func<string, int> func = (string n) => PickerPatches.PlayerCount(body, n); BuildProfile profile = BuildProfile.Of(body); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); for (int num = 1; num < filePages.Count; num++) { foreach (PathStep item2 in filePages[num]) { hashSet.Add(item2.Item); } } HashSet<string> hashSet2 = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (PathStep item3 in genPage) { hashSet2.Add(item3.Item); } HashSet<string> hashSet3 = new HashSet<string>(Plugin.Data.CandidateItems(bodyName), StringComparer.OrdinalIgnoreCase); hashSet3.UnionWith(Roles.Items); List<Cand> cands = new List<Cand>(); foreach (string item4 in hashSet3) { if (skipped.Contains(item4) || hashSet2.Contains(item4)) { continue; } ItemIndex val = ItemCatalog.FindItemIndex(item4); if ((int)val == -1) { continue; } ItemDef itemDef = ItemCatalog.GetItemDef(val); if (!Object.op_Implicit((Object)(object)itemDef) || (int)itemDef.tier == 5 || (int)itemDef.tier == 3 || itemDef.hidden || (Object.op_Implicit((Object)(object)Run.instance) && !Run.instance.IsItemAvailable(val)) || HeldVoid(body, item4) != null) { continue; } Advice advice = Plugin.Data.Get(bodyName, item4, func, german, profile); if (advice.Tier < 0) { continue; } int num2 = func(item4); int num3 = Roles.Cap(item4); if (num2 < num3) { Roles.Info info = Roles.Get(item4, advice.Tier); bool flag = (int)itemDef.tier == 2 || (int)itemDef.tier == 4 || (int)itemDef.tier == 8 || (int)itemDef.tier == 9; if (!flag) { int num4 = (((int)itemDef.tier == 1 || (int)itemDef.tier == 7) ? 3 : 5); int score = info.Consensus * 10 + advice.Tier * 8 + advice.SynergyReasons.Count * 5 + advice.Bonus + (hashSet.Contains(item4) ? 6 : 0) - Mathf.Min(num2, 10) - (flag ? 15 : 0) - (lastPageItems.Contains(item4) ? 20 : (pageBeforeItems.Contains(item4) ? 10 : 0)); cands.Add(new Cand { Role = info.Role, Rare = flag, Score = score, Step = new PathStep { Item = item4, Target = Mathf.Min(num2 + num4, num3), Optional = flag } }); } } } cands.Sort((Cand a, Cand b) => b.Score.CompareTo(a.Score)); bool flag2 = genNumber >= 3; string text = (Plugin.LatePageFocus.Value ?? "sustain").ToLowerInvariant(); int num5 = 1; int num6 = 1; int num7; int num8; int num9; if (text == "damage") { num7 = 5; num8 = 1; num5 = 0; num9 = 1; } else if (text == "balanced" || !flag2) { num7 = 4; num8 = 1; num9 = 1; } else { num7 = 3; num8 = 1; num9 = 2; } int rareLeft = 2; HashSet<char> rareRoles = new HashSet<char>(); foreach (PathStep item5 in genPage) { char role = Roles.Get(item5.Item, 0).Role; switch (role) { case 'D': case 'P': num7--; break; case 'F': num8--; break; case 'H': num5--; break; case 'S': num9--; break; default: num6--; break; } if (item5.Optional) { rareLeft--; rareRoles.Add(role); } } Func<Func<char, bool>, int, bool> obj = delegate(Func<char, bool> match, int n) { for (int i = 0; i < cands.Count; i++) { if (n <= 0) { break; } if (genPage.Count >= 8) { break; } Cand cand = cands[i]; if (!cand.Used && match(cand.Role) && (!cand.Rare || (rareLeft > 0 && !rareRoles.Contains(cand.Role))) && !ConflictsWithPage(cand.Step.Item)) { cand.Used = true; if (cand.Rare) { rareLeft--; rareRoles.Add(cand.Role); } genPage.Add(cand.Step); n--; } } return true; }; obj((char r) => r == 'F', num8); obj((char r) => r == 'H', num5); obj((char r) => r == 'S', num9); obj((char r) => r == 'U' || r == 'M', num6); obj((char r) => r == 'D' || r == 'P', num7); obj((char r) => true, 8); if (genPage.Count == 0) { genPage = null; return null; } genPage.Sort((PathStep a, PathStep b) => RoleOrder(Roles.Get(a.Item, 0).Role).CompareTo(RoleOrder(Roles.Get(b.Item, 0).Role))); return genPage; } private void RefreshRarity(CharacterBody body, string bodyName, bool german, float width) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Invalid comparison between Unknown and I4 //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Invalid comparison between Unknown and I4 //IL_00cf: 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_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) shownSteps = null; currentItem = null; Func<string, int> func = (string n) => PickerPatches.PlayerCount(body, n); BuildProfile profile = BuildProfile.Of(body); HashSet<string> hashSet = new HashSet<string>(Plugin.Data.CandidateItems(bodyName), StringComparer.OrdinalIgnoreCase); hashSet.UnionWith(Roles.Items); List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>(); List<KeyValuePair<int, string>> list2 = new List<KeyValuePair<int, string>>(); foreach (string item2 in hashSet) { ItemIndex val = ItemCatalog.FindItemIndex(item2); if ((int)val == -1) { continue; } ItemDef itemDef = ItemCatalog.GetItemDef(val); if (!Object.op_Implicit((Object)(object)itemDef) || itemDef.hidden || ((int)itemDef.tier != 0 && (int)itemDef.tier != 1) || (Object.op_Implicit((Object)(object)Run.instance) && !Run.instance.IsItemAvailable(val)) || HeldVoid(body, item2) != null) { continue; } Advice advice = Plugin.Data.Get(bodyName, item2, func, german, profile); if (advice.Tier >= 0) { int num = func(item2); if (num < Roles.Cap(item2)) { KeyValuePair<int, string> item = new KeyValuePair<int, string>(Roles.Score(item2, advice, num), item2); (((int)itemDef.tier == 0) ? list : list2).Add(item); } } } list.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => b.Key.CompareTo(a.Key)); list2.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => b.Key.CompareTo(a.Key)); int num2 = Mathf.Clamp(Plugin.RarityRowSize.Value, 3, 8); List<List<string>> list3 = new List<List<string>> { Roles.TopMixed(list, (KeyValuePair<int, string> kv) => kv.Value, num2, num2 - 3).ConvertAll((KeyValuePair<int, string> kv) => kv.Value), Roles.TopMixed(list2, (KeyValuePair<int, string> kv) => kv.Value, num2, num2 - 3).ConvertAll((KeyValuePair<int, string> kv) => kv.Value) }; StringBuilder stringBuilder = new StringBuilder("rarity").Append(bodyName).Append(german).Append(width) .Append(Plugin.HintSignature()); foreach (List<string> item3 in list3) { foreach (string item4 in item3) { stringBuilder.Append('|').Append(item4).Append(func(item4)); } } if (stringBuilder.ToString() == signature) { return; } signature = stringBuilder.ToString(); for (int num3 = ((Transform)content).childCount - 1; num3 >= 0; num3--) { Object.Destroy((Object)(object)((Component)((Transform)content).GetChild(num3)).gameObject); } pendingIcons.Clear(); TMP_Text obj = MakeTitle(); Ui.Fixed(obj.rectTransform, new Vector2(6f, -6f), new Vector2(width - 12f, titleH)); obj.text = (german ? "Nach Seltenheit:" : "By rarity:"); float num4 = 31f; float num5 = -6f - titleH - 2f; float inner = width - 12f; Color[] array = (Color[])(object)new Color[2] { new Color(0.92f, 0.92f, 0.92f), new Color(0.47f, 0.86f, 0.35f) }; for (int num6 = 0; num6 < list3.Count; num6++) { List<RectTransform> list4 = new List<RectTransform>(); Image val2 = Ui.MakeImage((Transform)(object)content, "Rarity" + num6, Sprites.Dot); ((Graphic)val2).color = array[num6]; Ui.Fixed(((Graphic)val2).rectTransform, new Vector2(0f, num5 - 4f), new Vector2(10f, 10f)); list4.Add(((Graphic)val2).rectTransform); float num7 = 16f; for (int num8 = 0; num8 < list3[num6].Count; num8++) { PathStep pathStep = new PathStep { Item = list3[num6][num8], Target = -1 }; Step(pathStep, func(pathStep.Item), num6 * 10 + num8, num8 == 0, num7, num5, list4); num7 += 26f; } CenterRow(list4, num7 - 2f - 4f, inner); num5 -= num4 + 2f + 2f; } FinishLayout(width, 0f - num5 + 6f - 2f - 2f, german); } private static int RoleOrder(char r) { switch (r) { default: return 3; case 'S': return 2; case 'F': case 'H': return 1; case 'D': case 'P': return 0; } } private bool ConflictsWithPage(string item) { HashSet<string> hashSet = VoidPartners(item); foreach (PathStep item2 in genPage) { if (hashSet.Contains(item2.Item)) { return true; } } return false; } private static HashSet<string> VoidPartners(string item) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_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_003f: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (voidPairs == null) { voidPairs = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase); if (Object.op_Implicit((Object)(object)ItemRelationshipTypes.ContagiousItem)) { Enumerator<Pair> enumerator = ItemCatalog.GetItemPairsForRelationship(ItemRelationshipTypes.ContagiousItem).GetEnumerator(); try { while (enumerator.MoveNext()) { Pair current = enumerator.Current; if (Object.op_Implicit((Object)(object)current.itemDef1) && Object.op_Implicit((Object)(object)current.itemDef2)) { Link(((Object)current.itemDef1).name, ((Object)current.itemDef2).name); Link(((Object)current.itemDef2).name, ((Object)current.itemDef1).name); } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } } if (!voidPairs.TryGetValue(item, out var value)) { return Empty; } return value; } private static void Link(string a, string b) { if (!voidPairs.TryGetValue(a, out var value)) { value = (voidPairs[a] = new HashSet<string>(StringComparer.OrdinalIgnoreCase)); } value.Add(b); } private static string PageLabel(bool german, string number) { return (german ? "Build-Pfad" : "Build path") + (string.IsNullOrEmpty(number) ? "" : (" " + number)); } private static void EnsureVoidMaps() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00ab: Unknown result type (might be due to invalid IL or missing references) if (voidOf != null) { return; } voidOf = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); normalsOf = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); if (!Object.op_Implicit((Object)(object)ItemRelationshipTypes.ContagiousItem)) { return; } Enumerator<Pair> enumerator = ItemCatalog.GetItemPairsForRelationship(ItemRelationshipTypes.ContagiousItem).GetEnumerator(); try { while (enumerator.MoveNext()) { Pair current = enumerator.Current; if (Object.op_Implicit((Object)(object)current.itemDef1) && Object.op_Implicit((Object)(object)current.itemDef2)) { voidOf[((Object)current.itemDef1).name] = ((Object)current.itemDef2).name; if (!normalsOf.TryGetValue(((Object)current.itemDef2).name, out var value)) { value = (normalsOf[((Object)current.itemDef2).name] = new List<string>()); } value.Add(((Object)current.itemDef1).name); } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } private static List<string> NormalsOf(string item) { EnsureVoidMaps(); if (item == null || !normalsOf.TryGetValue(item, out var value)) { return NoNames; } return value; } private static string HeldVoid(CharacterBody body, string item) { EnsureVoidMaps(); if (!voidOf.TryGetValue(item, out var value) || PickerPatches.PlayerCount(body, value) <= 0) { return null; } return value; } private static int PathCount(CharacterBody body, string item) { int num = PickerPatches.PlayerCount(body, item); string text = HeldVoid(body, item); if (text != null) { return num + PickerPatches.PlayerCount(body, text); } if (num > 0) { foreach (string item2 in NormalsOf(item)) { num += PickerPatches.PlayerCount(body, item2); } } return num; } private static List<PathStep> MapVoid(CharacterBody body, List<PathStep> steps) { List<PathStep> list = new List<PathStep>(steps.Count); foreach (PathStep step in steps) { string item = HeldVoid(body, step.Item) ?? step.Item; PathStep pathStep = list.Find((PathStep r) => string.Equals(r.Item, item, StringComparison.OrdinalIgnoreCase)); if (pathStep != null) { pathStep.Target = Mathf.Max(pathStep.Target, step.Target); continue; } list.Add(new PathStep { Item = item, Target = step.Target, Optional = step.Optional }); } return list; } private static string StepsText(List<PathStep> steps) { if (steps != null) { return string.Join(",", steps.ConvertAll((PathStep st) => $"{st.Item}:{st.Target}:{(st.Optional ? 1 : 0)}")); } return ""; } private static List<PathStep> ParseSteps(string text) { List<PathStep> list = new List<PathStep>(); string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(':'); if (array2.Length >= 3 && int.TryParse(array2[1], out var result)) { list.Add(new PathStep { Item = array2[0], Target = result, Optional = (array2[2] == "1") }); } } return list; } private void SaveState(string bodyName) { if (!Object.op_Implicit((Object)(object)Run.instance)) { return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("seed=").Append(Run.instance.seed).Append('\n'); stringBuilder.Append("body=").Append(bodyName).Append('\n'); stringBuilder.Append("skipStart=").Append(skipStart ? 1 : 0).Append('\n'); stringBuilder.Append("gen=").Append(genNumber).Append('\n'); stringBuilder.Append("skipped=").Append(string.Join(",", skipped)).Append('\n'); stringBuilder.Append("last=").Append(string.Join(",", lastPageItems)).Append('\n'); stringBuilder.Append("before=").Append(string.Join(",", pageBeforeItems)).Append('\n'); if (genPage != null) { stringBuilder.Append("page=").Append(StepsText(genPage)).Append('\n'); } if (currentNumber != null) { stringBuilder.Append("cur=").Append(currentNumber).Append('|') .Append(StepsText(currentSteps)) .Append('\n'); } foreach (Snapshot item in history) { stringBuilder.Append("hist=").Append(item.Number).Append('|') .Append(StepsText(item.Steps)) .Append('\n'); } string text = stringBuilder.ToString(); if (text == savedState) { return; } savedState = text; try { File.WriteAllText(StatePath, text); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not save build path state: " + ex.Message)); } } private void LoadState(string bodyName) { try { if (!Object.op_Implicit((Object)(object)Run.instance) || !File.Exists(StatePath)) { return; } List<KeyValuePair<string, string>> kv = new List<KeyValuePair<string, string>>(); string[] array = File.ReadAllLines(StatePath); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { kv.Add(new KeyValuePair<string, string>(text.Substring(0, num), text.Substring(num + 1))); } } if (Get("seed") != Run.instance.seed.ToString() || Get("body") != bodyName) { return; } Func<string, string[]> func = (string v) => (v ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); genBody = bodyName; skipStart = Get("skipStart") == "1"; if (int.TryParse(Get("gen"), out var result)) { genNumber = result; } skipped.UnionWith(func(Get("skipped"))); lastPageItems.UnionWith(func(Get("last"))); pageBeforeItems.UnionWith(func(Get("before"))); string text2 = Get("page"); if (text2 != null) { genPage = ParseSteps(text2); } foreach (KeyValuePair<string, string> item in kv) { if (item.Key != "hist" && item.Key != "cur") { continue; } int num2 = item.Value.IndexOf('|'); if (num2 >= 0) { Snapshot snapshot = new Snapshot { Number = item.Value.Substring(0, num2), Steps = ParseSteps(item.Value.Substring(num2 + 1)) }; if (item.Key == "hist") { history.Add(snapshot); continue; } currentNumber = snapshot.Number; currentSteps = snapshot.Steps; } } Plugin.Log.LogInfo((object)$"Build path state restored: page {currentNumber}, {skipped.Count} skipped, {history.Count} older pages"); string Get(string key) { foreach (KeyValuePair<string, string> item2 in kv) { if (item2.Key == key) { return item2.Value; } } return null; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not read build path state: " + ex.Message)); } } private static List<List<PathStep>> Paginate(List<List<PathStep>> lines) { List<List<PathStep>> list = new List<List<PathStep>>(); if (lines == null) { return list; } foreach (List<PathStep> line in lines) { for (int i = 0; i < line.Count; i += 10) { list.Add(line.GetRange(i, Mathf.Min(10, line.Count - i))); } } return list; } private void Rebuild(List<PathStep> steps, int[] counts, float width, bool german, string label) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) for (int num = ((Transform)content).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)content).GetChild(num)).gameObject); } pendingIcons.Clear(); int num2 = -1; for (int i = 0; i < steps.Count; i++) { if (counts[i] < steps[i].Target) { num2 = i; break; } } shownSteps = steps; currentItem = ((num2 >= 0) ? steps[num2].Item : null); TMP_Text obj = MakeTitle(); Ui.Fixed(obj.rectTransform, new Vector2(6f, -6f), new Vector2(width - 12f, titleH)); obj.text = ((num2 < 0) ? (label + ": " + (german ? "fertig!" : "done!")) : (label + ":")); float num3 = 31f; float num4 = 0f; float num5 = -6f - titleH - 2f; float num6 = width - 12f; List<RectTransform> list = new List<RectTransform>(); float rowWidth = 0f; for (int j = 0; j < steps.Count; j++) { if (j > 0) { if (num4 + 8f + 20f > num6) { CenterRow(list, rowWidth, num6); list.Clear(); num4 = 0f; num5 -= num3 + 2f; } else { HGTextMeshProUGUI val = Ui.MakeText((Transform)(object)content, "Sep" + j, 11f, new Color(0.75f, 0.75f, 0.75f)); ((TMP_Text)val).alignment = (TextAlignmentOptions)514; ((TMP_Text)val).overflowMode = (TextOverflowModes)0; ((TMP_Text)val).text = Plugin.PathSeparator.Value; Ui.Fixed(((TMP_Text)val).rectTransform, new Vector2(num4, num5), new Vector2(8f, 20f)); list.Add(((TMP_Text)val).rectTransform); num4 += 8f; } } Step(steps[j], counts[j], j, j == num2, num4, num5, list); num4 += 22f; rowWidth = num4 - 2f; } CenterRow(list, rowWidth, num6); FinishLayout(width, 0f - num5 + num3 + 6f, german); } private void FinishLayout(float width, float height, bool german) { //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_013d: 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) if (Plugin.ShowSkipHint.Value) { HGTextMeshProUGUI val = Ui.MakeText((Transform)(object)content, "Hint", 9f, new Color(0.6f, 0.6f, 0.6f)); ((TMP_Text)val).alignment = (TextAlignmentOptions)514; string text = ((object)Plugin.SwitchViewKey.Value/*cast due to .constrained prefix*/).ToString(); ((TMP_Text)val).text = ((!rarityView) ? (german ? $"{text}: Seltenheit · {Plugin.SkipItemKey.Value}: tauschen · {Plugin.BackPageKey.Value}/{Plugin.SkipPageKey.Value}: Seite zurück/vor" : $"{text}: rarity · {Plugin.SkipItemKey.Value}: swap · {Plugin.BackPageKey.Value}/{Plugin.SkipPageKey.Value}: page back/next") : (german ? (text + ": Build-Pfad") : (text + ": build path"))); Ui.Fixed(((TMP_Text)val).rectTransform, new Vector2(6f, 0f - height + 6f - 2f), new Vector2(width - 12f, 12f)); height += 12f; } ((RectTransform)((Component)this).transform).sizeDelta = new Vector2(width, height); LayoutElement obj = layout; float preferredHeight = (layout.minHeight = height); obj.preferredHeight = preferredHeight; layout.preferredWidth = width; SetVisible(on: true); } private static void CenterRow(List<RectTransform> row, float rowWidth, float inner) { //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_003b: Unknown result type (might be due to invalid IL or missing references) float num = 6f + Mathf.Max(0f, (inner - rowWidth) / 2f); foreach (RectTransform item in row) { item.anchoredPosition += new Vector2(num, 0f); } } private TMP_Text MakeTitle() { //IL_0010: 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_007e: Unknown result type (might be due to invalid IL or missing references) HGTextMeshProUGUI val = Ui.MakeText((Transform)(object)content, "Title", 18f, Color.white); ((TMP_Text)val).alignment = (TextAlignmentOptions)514; if (Object.op_Implicit((Object)(object)headerStyle)) { ((TMP_Text)val).font = headerStyle.font; ((TMP_Text)val).fontSharedMaterial = headerStyle.fontSharedMaterial; ((TMP_Text)val).fontSize = headerStyle.fontSize; ((TMP_Text)val).fontStyle = headerStyle.fontStyle; ((Graphic)val).color = ((Graphic)headerStyle).color; ((TMP_Text)val).characterSpacing = headerStyle.characterSpacing; } return (TMP_Text)(object)val; } private void Step(PathStep step, int have, int index, bool isCurrent, float x, float y, List<RectTransform> row) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_00f0: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) bool flag = step.Target < 0; bool flag2 = !flag && have >= step.Target; Image val = Ui.MakeImage((Transform)(object)content, "Icon" + index, null); Ui.Fixed(((Graphic)val).rectTransform, new Vector2(x, y), new Vector2(20f, 20f)); ((Graphic)val).color = (Color)(flag2 ? new Color(1f, 1f, 1f, 0.45f) : Color.white); ((Behaviour)val).enabled = false; SetIcon(step.Item, val); row.Add(((Graphic)val).rectTransform); if (isCurrent) { Image val2 = Ui.MakeImage((Transform)(object)content, "Frame" + index, Sprites.Frame); val2.type = (Type)1; val2.preserveAspect = false; val2.pixelsPerUnitMultiplier = 2.2f; ((Graphic)val2).color = Palette.Gold; Ui.Fixed(((Graphic)val2).rectTransform, new Vector2(x - 2f, y + 2f), new Vector2(24f, 24f)); row.Add(((Graphic)val2).rectTransform); } HGTextMeshProUGUI val3 = Ui.MakeText((Transform)(object)content, "Count" + index, 9f, (Color)(flag2 ? new Color(0.45f, 0.95f, 0.45f) : (isCurrent ? Palette.Gold : (step.Optional ? new Color(0.55f, 0.75f, 1f) : new Color(0.8f, 0.8f, 0.8f))))); ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((TMP_Text)val3).overflowMode = (TextOverflowModes)0; ((TMP_Text)val3).text = (flag ? $"{have}x" : $"{Mathf.Min(have, step.Target)}/{step.Target}"); Ui.Fixed(((TMP_Text)val3).rectTransform, new Vector2(x - 6f, y - 20f), new Vector2(32f, 11f)); row.Add(((TMP_Text)val3).rectTransform); } private void SetIcon(string internalName, Image target) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_001e: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) PickupIndex val = PickupIndex.none; ItemIndex val2 = ItemCatalog.FindItemIndex(internalName); if ((int)val2 != -1) { val = PickupCatalog.FindPickupIndex(val2); } else { EquipmentIndex val3 = EquipmentCatalog.FindEquipmentIndex(internalName); if ((int)val3 != -1) { val = PickupCatalog.FindPickupIndex(val3); } } PickupDef pickupDef = PickupCatalog.GetPickupDef(val); if (pickupDef == null) { return; } if (Object.op_Implicit((Object)(object)pickupDef.iconSprite)) { target.sprite = pickupDef.iconSprite; ((Behaviour)target).enabled = true; return; } AsyncImage val4 = ((Component)target).gameObject.AddComponent<AsyncImage>(); ((AsyncViewable<Sprite, Image>)(object)val4).renderer = target; ((AsyncViewable<Sprite, Image>)(object)val4).disableWhileLoading = true; ((AsyncViewable<Sprite, Image>)(object)val4).OnAssetFoundCallback += delegate { if (Object.op_Implicit((Object)(object)target)) { ((Behaviour)target).enabled = true; } }; val4.SetAssetOrDirectReference((AsyncIconProvider)(object)pickupDef); ((AsyncViewable<Sprite, Image>)(object)val4).LoadAssetReference(); if (!Object.op_Implicit((Object)(object)target.sprite)) { pendingIcons.Add(val4); } } } public sealed class BuildProfile { private sealed class Src { public string Item; public string Name; } public string Body; public Trait Have; public bool SingleTargetPrimary; public float Crit; public float AttackSpeedMult = 1f; private readonly Dictionary<Trait, List<Src>> debuffs = new Dictionary<Trait, List<Src>>(); private readonly List<Src> aoe = new List<Src>(); private readonly List<Src> onKill = new List<Src>(); private readonly List<Src> procs = new List<Src>(); private readonly List<Src> burn = new List<Src>(); private readonly List<Src> bleed = new List<Src>(); private readonly List<Src> stun = new List<Src>(); private readonly List<Src> wantsDebuffs = new List<Src>(); private readonly List<Src> wantsCrit = new List<Src>(); private readonly List<Src> wantsBurn = new List<Src>(); private readonly List<Src> wantsBleed = new List<Src>(); private readonly List<Src> wantsStun = new List<Src>(); private static readonly Dictionary<string, bool> PrimaryAreaOverride = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase) { ["EngiBody"] = true }; private static readonly HashSet<string> logged = new HashSet<string>(); public static BuildProfile Of(CharacterBody body) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Invalid comparison between Unknown and I4 //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) BuildProfile buildProfile = new BuildProfile(); if (!Object.op_Implicit((Object)(object)body)) { return buildProfile; } buildProfile.Body = BodyCatalog.GetBodyName(body.bodyIndex); buildProfile.Crit = body.crit; buildProfile.AttackSpeedMult = ((body.baseAttackSpeed > 0f) ? (body.attackSpeed / body.baseAttackSpeed) : 1f); SkillLocator skillLocator = body.skillLocator; if (Object.op_Implicit((Object)(object)skillLocator)) { string text = null; GenericSkill[] array = (GenericSkill[])(object)new GenericSkill[4] { skillLocator.primary, skillLocator.secondary, skillLocator.utility, skillLocator.special }; foreach (GenericSkill val in array) { SkillDef val2 = (Object.op_Implicit((Object)(object)val) ? val.skillDef : null); if (Object.op_Implicit((Object)(object)val2)) { string text2 = Traits.English(val2.skillDescriptionToken); if ((Object)(object)val == (Object)(object)skillLocator.primary) { text = text2; } buildProfile.Add(Traits.Parse(text2), null, Language.GetString(val2.skillNameToken), (Object)(object)val == (Object)(object)skillLocator.primary); } } if (skillLocator.passiveSkill.enabled) { buildProfile.Add(Traits.Parse(Traits.English(skillLocator.passiveSkill.skillDescriptionToken)), null, Language.GetString(skillLocator.passiveSkill.skillNameToken), primary: false); } buildProfile.SingleTargetPrimary = text != null && !(PrimaryAreaOverride.TryGetValue(buildProfile.Body ?? "", out var value) ? value : Traits.HitsArea(text)); } Inventory inventory = body.inventory; if (Object.op_Implicit((Object)(object)inventory)) { foreach (ItemIndex item in inventory.itemAcquisitionOrder) { ItemDef itemDef = ItemCatalog.GetItemDef(item); if (Object.op_Implicit((Object)(object)itemDef) && !itemDef.hidden && inventory.GetItemCountPermanent(item) > 0) { buildProfile.Add(Traits.Of(((Object)itemDef).name), ((Object)itemDef).name, Language.GetString(itemDef.nameToken), primary: false); } } } if (Object.op_Implicit((Object)(object)body.equipmentSlot) && (int)body.equipmentSlot.equipmentIndex != -1) { EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(body.equipmentSlot.equipmentIndex); if (Object.op_Implicit((Object)(object)equipmentDef)) { buildProfile.Add(Traits.Of(((Object)equipmentDef).name), ((Object)equipmentDef).name, Language.GetString(equipmentDef.nameToken), primary: false); } } if (buildProfile.Body != null && logged.Add(buildProfile.Body)) { Plugin.Log.LogInfo((object)("Survivor analysis [" + buildProfile.Body + "]: primary " + (buildProfile.SingleTargetPrimary ? "single target" : "hits an area") + ", debuffs from skills: " + string.Join(", ", buildProfile.debuffs.Keys.Select((Trait k) => Traits.DebuffName(k, german: false))))); } return buildProfile; } private void Add(Trait t, string item, string name, bool primary) { if (t == Trait.None) { return; } Have |= t; Src item2 = new Src { Item = item, Name = name }; foreach (Trait item3 in Traits.DebuffTypes(t)) { if (!debuffs.TryGetValue(item3, out var value)) { value = (debuffs[item3] = new List<Src>()); } value.Add(item2); } if ((t & Trait.Aoe) != Trait.None && !primary) { aoe.Add(item2); } if ((t & Trait.OnKill) != Trait.None && item != null) { onKill.Add(item2); } if ((t & Trait.Proc) != Trait.None && item != null) { procs.Add(item2); } if ((t & Trait.Burn) != Trait.None) { burn.Add(item2); } if ((t & Trait.Bleed) != Trait.None) { bleed.Add(item2); } if ((t & Trait.Stun) != Trait.None) { stun.Add(item2); } if ((t & Trait.WantsDebuffs) != Trait.None) { wantsDebuffs.Add(item2); } if ((t & Trait.WantsCrit) != Trait.None && item != null) { wantsCrit.Add(item2); } if ((t & Trait.WantsBurn) != Trait.None) { wantsBurn.Add(item2); } if ((t & Trait.WantsBleed) != Trait.None) { wantsBleed.Add(item2); } if ((t & Trait.WantsStun) != Trait.None) { wantsStun.Add(item2); } } private static List<Src> Others(List<Src> list, string item, Advice advice) { return list.Where((Src s) => s.Item == null || (!s.Item.Equals(item, StringComparison.OrdinalIgnoreCase) && !advice.RuleHaves.Contains(s.Item))).ToList(); } private static string Names(List<Src> list, int max = 3) { List<string> list2 = list.Select((Src s) => s.Name).Distinct().ToList(); string text = string.Join(", ", list2.Take(max)); if (list2.Count <= max) { return text; } return text + ", …"; } private List<Trait> DebuffTypesWithout(string item) { return (from kv in debuffs where kv.Value.Any((Src s) => s.Item == null || !s.Item.Equals(item, StringComparison.OrdinalIgnoreCase)) select kv.Key).ToList(); } private void Reason(Advice a, int bonus, string de, string en, bool german) { a.Bonus += bonus; a.BuildReasons.Add(german ? de : en); } private void Note(Advice a, int malus, string de, string en, bool german) { a.Bonus += malus; a.Notes.Add(german ? de : en); } public void Apply(string item, Advice a, bool german) { if (Body == null) { return; } Trait trait = Traits.Of(item); if (trait == Trait.None) { return; } List<Trait> types = DebuffTypesWithout(item); int count = types.Count; string text = string.Join(", ", types.Select((Trait d) => Traits.DebuffName(d, german))); if ((trait & Trait.WantsDebuffs) != Trait.None) { if (count >= 3) { Reason(a, 12 + 3 * Math.Min(count - 3, 3), $"Dein Build verteilt schon {count} Debuff-Arten ({text}) – genau dafür ist dieses Item.", $"Your build already applies {count} debuff types ({text}) – exactly what this item wants.", german); } else if (count == 2) { Reason(a, 6, "2 Debuff-Arten (" + text + ") – noch 1-2 mehr, dann lohnt es sich richtig.", "2 debuff types (" + text + ") – 1-2 more and it really pays off.", german); } else { Note(a, -4, (count == 1) ? ("Bisher nur 1 Debuff-Art (" + text + ") – braucht mehr Debuff-Items.") : "Du verteilst noch keine Debuffs – braucht Debuff-Items.", (count == 1) ? ("Only 1 debuff type so far (" + text + ") – needs more debuff items.") : "You don't apply debuffs yet – needs debuff items.", german); } } List<Trait> list = (from d in Traits.DebuffTypes(trait) where !types.Contains(d) select d).ToList(); if (list.Count > 0) { string arg = string.Join(", ", list.Select((Trait d) => Traits.DebuffName(d, german))); List<Src> list2 = Others(wantsDebuffs, item, a); if (list2.Count > 0) { Reason(a, Math.Min(12, 7 * list.Count), $"Neue Debuff-Art ({arg}) für {Names(list2)} – dann {count + list.Count} Arten.", $"New debuff type ({arg}) for your {Names(list2)} – {count + list.Count} types then.", german); } else if (count >= 2) { Reason(a, 3, $"Weitere Debuff-Art ({arg}) – {count + list.Count} Arten machen Death Mark / Noxious Thorn stark.", $"Another debuff type ({arg}) – {count + list.Count} types make Death Mark / Noxious Thorn strong.", german); } } Pair(a, trait, item, german, Trait.WantsBurn, Trait.Burn, burn, wantsBurn, "Brand", "burn"); Pair(a, trait, item, german, Trait.WantsBleed, Trait.Bleed, bleed, wantsBleed, "Bluten", "bleed"); Pair(a, trait, item, german, Trait.WantsStun, Trait.Stun, stun, wantsStun, "Betäubung", "stun"); int num = (int)Math.Round(Crit); if ((trait & Trait.WantsCrit) != Trait.None) { if (num >= 40) { Reason(a, 10, $"Du hast {num}% Crit – das Item profitiert voll davon.", $"You have {num}% crit – this item gets full value.", german); } else if (num >= 20) { Reason(a, 5, $"Du hast {num}% Crit – wird mit mehr Crit noch besser.", $"You have {num}% crit – gets better with more.", german); } else { Note(a, -3, $"Braucht Crit (du hast {num}%) – Lens-Maker's Glasses zuerst.", $"Needs crit (you have {num}%) – Lens-Maker's Glasses first.", german); } } if ((trait & Trait.Crit) != Trait.None && (trait & Trait.WantsCrit) == 0) { List<Src> list3 = Others(wantsCrit, item, a); if (num >= 100) { Note(a, -15, "Du hast schon 100% Crit – mehr bringt nichts.", "You already have 100% crit – more does nothing.", german); } else if (list3.Count > 0) { Reason(a, 6, "Mehr Crit für " + Names(list3) + ".", "More crit for your " + Names(list3) + ".", german); } } if ((trait & Trait.Proc) != Trait.None && AttackSpeedMult >= 1.6f) { Reason(a, 5, $"Du greifst schnell an (x{AttackSpeedMult:0.0}) – On-Hit-Effekte lösen öfter aus.", $"You attack fast (x{AttackSpeedMult:0.0}) – on-hit effects proc more often.", german); } if ((trait & Trait.AttackSpeed) != Trait.None) { List<Src> list4 = Others(procs, item, a); if (list4.Count >= 3) { Reason(a, 6, $"Mehr Treffer für deine {list4.Count} On-Hit-Items ({Names(list4)}).", $"More hits for your {list4.Count} on-hit items ({Names(list4)}).", german); } } List<Src> list5 = (from s in Others(aoe, item, a) where s.Item != null select s).ToList(); List<Src> list6 = Others(onKill, item, a); if ((trait & Trait.Aoe) != Trait.None) { if (SingleTargetPrimary && list5.Count < 5) { Reason(a, Math.Max(3, 10 - 2 * list5.Count), "Dein Hauptangriff trifft nur ein Ziel – das bringt Flächenschaden gegen Gruppen.", "Your primary hits one target – this adds area damage against groups.", german); } if (list6.Count >= 2) { Reason(a, 4, "Flächen-Kills lösen deine On-Kill-Items aus (" + Names(list6) + ").", "Area kills trigger your on-kill items (" + Names(list6) + ").", german); } } if ((trait & Trait.OnKill) != Trait.None && (trait & Trait.Aoe) == 0) { if (list5.Count >= 2) { Reason(a, 6, "Dein Flächenschaden (" + Names(list5) + ") tötet Gruppen – mehr Auslöser.", "Your area damage (" + Names(list5) + ") kills groups – more triggers.", german); } else if (SingleTargetPrimary && list5.Count == 0) { Note(a, -2, "Ohne Flächenschaden tötest du langsam – besser erst Gasoline, Will-o'-the-wisp, Ukulele.", "Without area damage you kill slowly – get Gasoline, Will-o'-the-wisp, Ukulele first.", german); } } } private void Pair(Advice a, Trait t, string item, bool german, Trait wantFlag, Trait giveFlag, List<Src> givers, List<Src> wanters, string de, string en) { if ((t & wantFlag) != Trait.None) { List<Src> list = Others(givers, item, a); if (list.Count > 0) { Reason(a, 10 + 3 * Math.Min(list.Count - 1, 3), "Verstärkt " + de + " von " + Names(list) + ".", "Boosts your " + en + " from " + Names(list) + ".", german); } else if (givers.Count == 0) { Note(a, -8, "Du hast noch keine " + de + "-Quelle – erst ein Item, das " + de + " verursacht.", "You have no " + en + " source yet – get an item that causes " + en + " first.", german); } } if ((t & giveFlag) != Trait.None) { List<Src> list2 = Others(wanters, item, a); if (list2.Count > 0) { Reason(a, 8, Names(list2) + " macht " + de + " stärker.", "Your " + Names(list2) + " boosts this " + en + ".", german); } } } } public static class Palette { public static readonly Color Gold = new Color(1f, 0.8f, 0.15f, 1f); public static readonly Color LightGold = new Color(1f, 0.93f, 0.55f, 0.75f); public static readonly Color Turquoise = new Color(0.25f, 0.95f, 0.9f, 1f); public static readonly Color Orange = new Color(1f, 0.55f, 0.1f, 1f); public static readonly Color Red = new Color(0.95f, 0.15f, 0.12f, 1f); public static readonly Color Panel = new Color(0.06f, 0.07f, 0.09f, 0.88f); public static Color ForTier(int tier) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (tier < 2) { return (Color)(tier switch { -1 => Orange, 1 => LightGold, _ => Red, }); } return Gold; } } public sealed class Overlay : MonoBehaviour { private Image tint; private Image frame; private Image star; private Image cross; private Image dot; private Pulse pulse; public string AppendedTooltip; public static Overlay GetOrCreate(GameObject button) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: 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) Transform val = button.transform.Find("ItemRecommenderOverlay"); if (Object.op_Implicit((Object)(object)val)) { return ((Component)val).GetComponent<Overlay>(); } GameObject val2 = new GameObject("ItemRecommenderOverlay", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(button.transform, false); val2.AddComponent<LayoutElement>().ignoreLayout = true; Ui.Place((RectTransform)val2.transform, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero); Overlay overlay = val2.AddComponent<Overlay>(); overlay.tint = Ui.MakeImage(val2.transform, "Tint", Sprites.Fill); Ui.Place(((Graphic)overlay.tint).rectTransform, Vector2.zero, Vector2.one, new Vector2(2f, 2f), new Vector2(-2f, -2f)); overlay.frame = Ui.MakeImage(val2.transform, "Frame", Sprites.Frame); overlay.frame.type = (Type)1; overlay.frame.preserveAspect = false; Ui.Place(((Graphic)overlay.frame).rectTransform, Vector2.zero, Vector2.one, new Vector2(-3f, -3f), new Vector2(3f, 3f)); overlay.dot = Ui.MakeImage(val2.transform, "SynergyDot", Sprites.Dot); Ui.Place(((Graphic)overlay.dot).rectTransform, new Vector2(-0.06f, 0.7f), new Vector2(0.26f, 1.02f), Vector2.zero, Vector2.zero); overlay.star = Ui.MakeImage(val2.transform, "Star", Sprites.Star); Ui.Place(((Graphic)overlay.star).rectTransform, new Vector2(0.56f, 0.56f), new Vector2(1.08f, 1.08f), Vector2.zero, Vector2.zero); overlay.pulse = ((Component)overlay.star).gameObject.AddComponent<Pulse>(); overlay.cross = Ui.MakeImage(val2.transform, "Cross", Sprites.Cross); Ui.Place(((Graphic)overlay.cross).rectTransform, new Vector2(0.58f, 0.58f), new Vector2(1.06f, 1.06f), Vector2.zero, Vector2.zero); return overlay; } public void Show(Advice advice, bool showGoodTier, bool isBest) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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) ((Component)this).transform.SetAsLastSibling(); int num = advice?.Tier ?? 0; bool flag = num >= 2 || num < 0 || (num == 1 && showGoodTier); ((Component)this).gameObject.SetActive(flag); if (flag) { Color val = Palette.ForTier(num); ((Graphic)frame).color = val; frame.pixelsPerUnitMultiplier = ((num == 1) ? 1.8f : 1f); ((Component)star).gameObject.SetActive(num >= 2); ((Graphic)star).color = Palette.Gold; ((Behaviour)pulse).enabled = isBest; if (!isBest) { ((Transform)((Graphic)star).rectTransform).localScale = Vector3.one; } ((Component)cross).gameObject.SetActive(num < 0); ((Graphic)cross).color = val; ((Component)tint).gameObject.SetActive(num < 0); ((Graphic)tint).color = new Color(val.r, val.g, val.b, (num == -2) ? 0.28f : 0.18f); ((Component)dot).gameObject.SetActive((advice.SynergyReasons.Count > 0 || advice.Bonus >= 6) && num > 0); ((Graphic)dot).color = Palette.Turquoise; } } } public sealed class Legend : MonoBehaviour { private const float Width = 300f; private const float RowH = 26f; private const float Pad = 10f; private RectTransform anchorRect; private HGTextMeshProUGUI title; private HGTextMeshProUGUI[] labels; public static Legend GetOrCreate(PickupPickerPanel panel) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)panel).transform.Find("ItemRecommenderLegend"); if (Object.op_Implicit((Object)(object)val)) { return ((Component)val).GetComponent<Legend>(); } GameObject val2 = new GameObject("ItemRecommenderLegend", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(((Component)panel).transform, false); val2.AddComponent<LayoutElement>().ignoreLayout = true; Legend legend = val2.AddComponent<Legend>(); legend.Build(panel.buttonContainer); return legend; } private void Build(RectTransform anchor) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: 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_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) anchorRect = anchor; RectTransform val = (RectTransform)((Component)this).transform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); val.anchorMax = val2; val.anchorMin = val2; val.pivot = new Vector2(0f, 1f); val.sizeDelta = new Vector2(300f, 206f); Image obj = Ui.MakeImage(((Component)this).transform, "Bg", Sprites.Fill); ((Graphic)obj).color = Palette.Panel; obj.preserveAspect = false; Ui.Place(((Graphic)obj).rectTransform, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero); Image obj2 = Ui.MakeImage(((Component)this).transform, "Border", Sprites.Frame); obj2.type = (Type)1; obj2.preserveAspect = false; obj2.pixelsPerUnitMultiplier = 2.5f; ((Graphic)obj2).color = new Color(1f, 0.8f, 0.15f, 0.5f); Ui.Place(((Graphic)obj2).rectTransform, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero); title = Ui.MakeText(((Component)this).transform, "Title", 17f, Palette.Gold); Row(((TMP_Text)title).rectTransform, 0, 0f); labels = (HGTextMeshProUGUI[])(object)new HGTextMeshProUGUI[6]; for (int i = 0; i < labels.Length; i++) { labels[i] = Ui.MakeText(((Component)this).transform, "Label" + i, 15f, (Color)((i == 5) ? new Color(0.7f, 0.7f, 0.7f) : Color.white)); Row(((TMP_Text)labels[i]).rectTransform, i + 1, (i == 5) ? 0f : 34f); } Icon(1, Palette.Gold, 1f, Sprites.Star, Palette.Gold, badgeLeft: false); Icon(2, Palette.LightGold, 1.8f, null, default(Color), badgeLeft: false); Icon(3, Palette.Gold, 1f, Sprites.Dot, Palette.Turquoise, badgeLeft: true); Icon(4, Palette.Orange, 1f, Sprites.Cross, Palette.Orange, badgeLeft: false); Icon(5, Palette.Red, 1f, Sprites.Cross, Palette.Red, badgeLeft: false); } private static float RowTop(int row) { return -10f - 26f * (float)row - ((row > 0) ? 4f : 0f); } private static void Row(RectTransform r, int row, float indent) { //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_0053: 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) r.anchorMin = new Vector2(0f, 1f); r.anchorMax = new Vector2(1f, 1f); r.pivot = new Vector2(0f, 1f); r.offsetMin = new Vector2(10f + indent, RowTop(row) - 26f); r.offsetMax = new Vector2(-10f, RowTop(row)); } private void Icon(int row, Color frameColor, float thin, Sprite badge, Color badgeColor, bool badgeLeft) { //IL_0050: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) float num = 22f; float num2 = RowTop(row) - 2f; Image obj = Ui.MakeImage(((Component)this).transform, "IconFrame" + row, Sprites.Frame); obj.type = (Type)1; obj.preserveAspect = false; obj.pixelsPerUnitMultiplier = thin * 2.2f; ((Graphic)obj).color = frameColor; Ui.Fixed(((Graphic)obj).rectTransform, new Vector2(12f, num2), new Vector2(num, num)); if (!((Object)(object)badge == (Object)null)) { Image obj2 = Ui.MakeImage(((Component)this).transform, "IconBadge" + row, badge); ((Graphic)obj2).color = badgeColor; float num3 = num * 0.62f; Ui.Fixed(((Graphic)obj2).rectTransform, new Vector2(12f + (badgeLeft ? (-3f) : (num - num3 + 3f)), num2 + 3f), new Vector2(num3, num3)); } } public void SetTexts(string survivor, bool german) { ((TMP_Text)title).text = (string.IsNullOrEmpty(survivor) ? "ItemRecommender" : ("ItemRecommender – " + survivor)); string[] array = ((!german) ? new string[6] { "Core item – build it!", "Good pick", "Synergy with your items", "Rather not", "Don't build / destroys items", "Hover/inspect shows the reason" } : new string[6] { "Kern-Item – bauen!", "Gute Wahl", "Synergie mit deinen Items", "Eher nicht", "Nicht bauen / zerstört Items", "Hover/Inspect zeigt die Begründung" }); for (int i = 0; i < labels.Length; i++) { ((TMP_Text)labels[i]).text = array[i]; } } private void LateUpdate() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)anchorRect)) { Vector3[] array = (Vector3[])(object)new Vector3[4]; anchorRect.GetWorldCorners(array); Vector3 val = ((Transform)(RectTransform)((Component)this).transform.parent).InverseTransformPoint(array[2]); ((Component)this).transform.localPosition = new Vector3(val.x + 48f, val.y + 20f, 0f); } } } public sealed class OrderPanel : MonoBehaviour { private const float Width = 300f; private const float RowH = 24f; private const float Pad = 10f; private RectTransform anchorRect; private HGTextMeshProUGUI title; private readonly List<HGTextMeshProUGUI> rows = new List<HGTextMeshProUGUI>(); public static OrderPanel GetOrCreate(PickupPickerPanel panel) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)panel).transform.Find("ItemRecommenderOrder"); if (Object.op_Implicit((Object)(object)val)) { return ((Component)val).GetComponent<OrderPanel>(); } GameObject val2 = new GameObject("ItemRecommenderOrder", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(((Component)panel).transform, false); val2.AddComponent<LayoutElement>().ignoreLayout = true; OrderPanel orderPanel = val2.AddComponent<OrderPanel>(); orderPanel.Build(panel.buttonContainer); return orderPanel; } private void Build(RectTransform anchor) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_002b: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) anchorRect = anchor; RectTransform val = (RectTransform)((Component)this).transform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); val.anchorMax = val2; val.anchorMin = val2; val.pivot = new Vector