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 DeepTip EpicLoot v1.2.0
DeepTip_EpicLoot.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DeepTip; using EpicLoot; using EpicLoot.Abilities; using EpicLoot.Adventure; using EpicLoot.Biomes; using EpicLoot.Crafting; using EpicLoot.CraftingV2; using EpicLoot.GatedItemType; using EpicLoot.LegendarySystem; using EpicLoot.Magic.MagicItemEffects.Helpers; using EpicLoot.ShardStones; using EpicLoot_UnityLib; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyCompany("Gorduan")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+cee680c46d08ef37c1b926a7ddeecc20cf774f6c")] [assembly: AssemblyProduct("DeepTip EpicLoot")] [assembly: AssemblyTitle("DeepTip_EpicLoot")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 DeepTipEpicLoot { internal static class AdventureGlossary { private sealed class Entry { public readonly string Key; public readonly string Title; public readonly string Short; public readonly string Body; public readonly string[] See; public Entry(string key, string title, string shortText, string body, string[] see) { Key = key; Title = title; Short = shortText; Body = body; See = see; } } private sealed class Lang { public string Code = ""; public CultureInfo Culture = CultureInfo.InvariantCulture; public string Percent = "{0}%"; public string[] RarityNames = new string[6]; [Own] public Dictionary<string, string> Biomes = new Dictionary<string, string>(); public string IronTokens = ""; public string GoldTokens = ""; public string ForestTokens = ""; public string Coins = ""; public string NoReward = ""; public string Minions = ""; public string IronBounty = ""; public string GoldBounty = ""; public string BountyIndexTitle = ""; public string BountyIndexShort = ""; public string BountyIndexIntro = ""; public string BountyIndexLine = ""; public string MapIndexTitle = ""; public string MapIndexShort = ""; public string MapIndexIntro = ""; public string BountyTitle = ""; public string BountyShort = ""; public string BountyIntro = ""; public string IronStrength = ""; public string GoldStrength = ""; public string AddsStrength = ""; public string StrengthNote = ""; public string NoStar = ""; public string OneStar = ""; public string StarsFormat = ""; public string OnlyDiscovered = ""; public string GatedCurrent = ""; public string GatedNext = ""; public string MapTitle = ""; public string MapShort = ""; public string MapIntro = ""; public string MapScaled = ""; public string MapRolls = ""; public string PerRoll = ""; public string MapExtra = ""; public string MapNote = ""; public string Nothing = ""; public string Or = ""; public string UniqueShard = ""; public string Chisel = ""; public string TierGear = ""; public string PricesTitle = ""; public string PricesShort = ""; public string PricesIntro = ""; public string PricesRange = ""; public string PricesMissing = ""; public string TokenPrices = ""; public string TierTitle = ""; public string TierShort = ""; public string TierIntro = ""; public string TierLabel = ""; public string NoPrice = ""; public string EveryDay = ""; public string EveryDays = ""; public string On = ""; public string Off = ""; public string NonMagic = ""; internal static Lang For(string locale) { return Texts.Load<Lang>("adventure", locale); } } private const string Owner = "DeepTip_EpicLoot.Abenteuer"; private const string ValuePrefix = "el_adv_"; private const int MissingGamblePrice = 10000; private static readonly string[] NamePrefixes = new string[3] { "enemy_", "item_", "biome_" }; private static readonly Dictionary<string, Dictionary<string, string>> names = new Dictionary<string, Dictionary<string, string>>(StringComparer.Ordinal); internal static void Hook(Harmony harmony) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown try { AdventureDataManager.OnSetupAdventureData += Rebuild; LootRoller.OnSetupLootTables += Rebuild; BiomeDataManager.OnBiomeDataInitialized += Rebuild; HarmonyMethod val = new HarmonyMethod(typeof(AdventureGlossary), "Refresh", (Type[])null); MethodInfo[] array = new MethodInfo[2] { AccessTools.Method(typeof(Game), "Start", (Type[])null, (Type[])null), AccessTools.Method(typeof(GatedItemTypeHelper), "Initialize", (Type[])null, (Type[])null) }; foreach (MethodInfo methodInfo in array) { if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } RegisterValues(); } catch (Exception arg) { Plugin.Log.LogError((object)$"EpicLoot-Abenteuer: Haken nicht gesetzt: {arg}"); } if (AdventureDataManager.Config != null) { Rebuild(); } } private static void Refresh() { Rebuild(); } internal static void Rebuild() { try { AdventureDataConfig config = AdventureDataManager.Config; if (config == null) { return; } List<string> locales = Texts.Locales; LoadNames(locales.Select(Texts.Language)); List<(Lang, List<Entry>)> list = (from l in locales select Lang.For(l) into l select (l: l, Build(l, config))).ToList(); Api.Unregister("DeepTip_EpicLoot.Abenteuer"); foreach (var (lang, entries) in list) { Api.Register("DeepTip_EpicLoot.Abenteuer", ToJson(lang, entries), lang.Code); } List<Entry> item = list[0].Item2; int num = item.Count((Entry e) => e.Key.StartsWith("epicloot.adventure.bounty.biome.", StringComparison.Ordinal)); int num2 = item.Count((Entry e) => e.Key.StartsWith("epicloot.adventure.treasuremap.biome.", StringComparison.Ordinal)); int num3 = item.Count((Entry e) => e.Key.StartsWith("epicloot.adventure.gamble.prices", StringComparison.Ordinal)); Plugin.Log.LogInfo((object)$"EpicLoot-Abenteuer erklärt: {item.Count} Einträge ({num} Biome mit Kopfgeldern, {num2} mit Schatzkarten, {num3} zu Glücksspiel-Preisen)"); } catch (Exception arg) { Plugin.Log.LogError((object)$"EpicLoot-Abenteuer nicht erklärt: {arg}"); } } private static List<Entry> Build(Lang lang, AdventureDataConfig config) { List<Entry> list = new List<Entry>(); Section(list, "Kopfgelder", () => Bounties(lang, config)); Section(list, "Schatzkarten", () => TreasureMaps(lang, config)); Section(list, "Glücksspiel-Preise", () => GamblePrices(lang, config)); return list; } private static void Section(List<Entry> entries, string name, Func<IEnumerable<Entry>> build) { try { entries.AddRange(build().ToList()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("EpicLoot-Abenteuer, Teil " + name + " übersprungen: " + ex.Message)); } } private static IEnumerable<Entry> Bounties(Lang lang, AdventureDataConfig config) { //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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) BountiesConfig bounties = config.Bounties; if (bounties?.Targets == null) { return Enumerable.Empty<Entry>(); } List<(Biome, BountyTargetConfig)> source = (from t in bounties.Targets where t != null && !string.IsNullOrEmpty(t.TargetID) select (t.GetBiome(), t: t) into x where (int)x.Item1 > 0 select x).ToList(); List<Entry> list = new List<Entry>(); StringBuilder stringBuilder = new StringBuilder(lang.BountyIndexIntro); foreach (Biome biome in InOrder(source.Select<(Biome, BountyTargetConfig), Biome>(((Biome Biome, BountyTargetConfig Target) x) => x.Biome))) { List<BountyTargetConfig> list2 = (from x in source where x.Biome == biome select x.Target).ToList(); Entry entry = BountyEntry(lang, bounties, biome, list2); list.Add(entry); string arg = Range(list2.Select((BountyTargetConfig t) => t.RewardCoins), lang) ?? "0"; stringBuilder.Append("\n- [[").Append(entry.Key).Append('|') .Append(BiomeTitle(biome, lang)) .Append("]]: ") .Append(string.Format(lang.BountyIndexLine, list2.Count, list2.Count((BountyTargetConfig t) => t.RewardGold > 0), arg)); } if (list.Count > 0) { list.Insert(0, new Entry("epicloot.adventure.bounty.biomes", lang.BountyIndexTitle, lang.BountyIndexShort, stringBuilder.ToString(), new string[2] { "epicloot.adventure.bounty.offers", "epicloot.adventure.bounty" })); } return list; } private static Entry BountyEntry(Lang lang, BountiesConfig b, Biome biome, List<BountyTargetConfig> targets) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) string text = BiomeTitle(biome, lang); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(string.Format(lang.BountyIntro, BiomeLink(biome, text), Pct(100f / (float)targets.Count, lang))); foreach (BountyTargetConfig target in targets) { bool flag = target.RewardGold > 0; stringBuilder.Append("\n- **").Append(MonsterName(target.TargetID, lang)).Append("** (") .Append(flag ? lang.GoldBounty : lang.IronBounty) .Append("): "); stringBuilder.Append(Reward(target.RewardIron, target.RewardGold, target.RewardCoins, lang)); List<string> list = (from a in target.Adds ?? new List<BountyTargetAddConfig>() where a != null && a.Count > 0 && !string.IsNullOrEmpty(a.ID) select $"{a.Count}× {MonsterName(a.ID, lang)}").ToList(); if (list.Count > 0) { stringBuilder.Append("; ").Append(lang.Minions).Append(' ') .Append(string.Join(", ", list)); } } List<string> list2 = new List<string>(); if (targets.Any((BountyTargetConfig t) => t.RewardGold <= 0)) { list2.Add(string.Format(lang.IronStrength, Stars(b.IronMinLevel, b.IronMaxLevel, lang), Num(b.IronHealthMultiplier, lang))); } if (targets.Any((BountyTargetConfig t) => t.RewardGold > 0)) { list2.Add(string.Format(lang.GoldStrength, Stars(b.GoldMinLevel, b.GoldMaxLevel, lang), Num(b.GoldHealthMultiplier, lang))); } if (targets.Any((BountyTargetConfig t) => t.Adds?.Any((BountyTargetAddConfig a) => a != null && a.Count > 0) ?? false)) { list2.Add(string.Format(lang.AddsStrength, Stars(b.AddsMinLevel, b.AddsMaxLevel, lang), Num(b.AddsHealthMultiplier, lang))); } stringBuilder.Append("\n\n").Append(string.Join(". ", list2)).Append(". ") .Append(lang.StrengthNote); stringBuilder.Append("\n\n").Append(Gating(lang)); return new Entry("epicloot.adventure.bounty.biome." + Slug(biome), string.Format(lang.BountyTitle, text), Cut(string.Format(lang.BountyShort, targets.Count, text)), stringBuilder.ToString(), new string[3] { "epicloot.adventure.bounty.offers", "epicloot.adventure.bounty.rewards", "epicloot.adventure.bounty.target" }); } private static string Reward(int iron, int gold, int coins, Lang lang) { List<string> list = new List<string>(); if (iron > 0) { list.Add($"{iron} {lang.IronTokens}"); } if (gold > 0) { list.Add($"{gold} {lang.GoldTokens}"); } if (coins > 0) { list.Add($"{coins} {lang.Coins}"); } if (list.Count <= 0) { return lang.NoReward; } return string.Join(", ", list); } private static string Stars(int minLevel, int maxLevel, Lang lang) { int num = Math.Max(0, minLevel - 1); int num2 = Math.Max(num, maxLevel - 1); if (num2 == 0) { return lang.NoStar; } string arg = ((num == num2) ? num.ToString(lang.Culture) : $"{num}–{num2}"); return string.Format((num2 == 1 && num == 1) ? lang.OneStar : lang.StarsFormat, arg); } private static string Gating(Lang lang) { object? obj = ElConfig("BossBountyMode"); string onlyDiscovered = lang.OnlyDiscovered; string text = obj?.ToString(); if (!(text == "BossKillUnlocksCurrentBiomeBounties")) { if (text == "BossKillUnlocksNextBiomeBounties") { return onlyDiscovered + " " + lang.GatedNext; } return onlyDiscovered; } return onlyDiscovered + " " + lang.GatedCurrent; } private static IEnumerable<Entry> TreasureMaps(Lang lang, AdventureDataConfig config) { List<Entry> list = MapEntries(lang, config).ToList(); if (list.Count == 0) { return list; } StringBuilder stringBuilder = new StringBuilder(lang.MapIndexIntro); foreach (Entry item in list) { stringBuilder.Append("\n- [[").Append(item.Key).Append('|') .Append(item.Title) .Append("]]: ") .Append(item.Short); } list.Insert(0, new Entry("epicloot.adventure.treasuremap.biomes", lang.MapIndexTitle, lang.MapIndexShort, stringBuilder.ToString(), new string[2] { "epicloot.adventure.treasuremap", "epicloot.adventure.location" })); return list; } private static IEnumerable<Entry> MapEntries(Lang lang, AdventureDataConfig config) { TreasureMapConfig maps = config.TreasureMap; if (maps?.BiomeInfo == null) { yield break; } float scale = (maps.ScaleRadiiToWorldSize ? RadiusScale() : 1f); float area = Mathf.Max(0f, maps.MinimapAreaRadius) * 2.1f * 0.5f; HashSet<Biome> done = new HashSet<Biome>(); foreach (TreasureMapBiomeInfoConfig item in maps.BiomeInfo) { if (item == null) { continue; } Biome biome = item.GetBiome(); if ((int)biome != 0 && done.Add(biome) && item.Cost > 0) { List<LootTable> lootTable = LootRoller.GetLootTable("TreasureMapChest_" + BiomeDataManager.GetName(biome)); if (lootTable != null && lootTable.Count != 0) { yield return TreasureEntry(lang, maps, item, biome, lootTable[0], scale, area); } } } } private static Entry TreasureEntry(Lang lang, TreasureMapConfig maps, TreasureMapBiomeInfoConfig info, Biome biome, LootTable table, float scale, float area) { //IL_0000: 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_03bc: Unknown result type (might be due to invalid IL or missing references) string text = BiomeTitle(biome, lang); string text2 = Num(Mathf.Min(info.MinRadius, info.MaxRadius) * scale, lang, "0"); string text3 = Num(Mathf.Max(info.MinRadius, info.MaxRadius) * scale, lang, "0"); string text4 = Every(maps.RefreshInterval, lang) ?? ""; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(string.Format(lang.MapIntro, BiomeLink(biome, text), info.Cost, text4, text2, text3, Num(area, lang, "0"))); if (!Mathf.Approximately(scale, 1f)) { stringBuilder.Append(' ').Append(string.Format(lang.MapScaled, Num(scale, lang))); } LeveledLootDef? obj = (from l in table.LeveledLoot?.Where((LeveledLootDef l) => l != null) orderby l.Level select l).FirstOrDefault(); float[][] drops = obj?.Drops ?? table.Drops; object obj2 = obj?.Loot ?? table.Loot; string arg = DropCounts(drops, lang); if (obj2 == null) { obj2 = Array.Empty<LootDrop>(); } List<LootDrop> list = ((IEnumerable<LootDrop>)obj2).Where((LootDrop d) => d != null && !string.IsNullOrEmpty(d.Item) && d.Weight > 0f).ToList(); if (list.Count > 0) { float num = list.Sum((LootDrop d) => d.Weight); stringBuilder.Append("\n\n").Append(string.Format(lang.MapRolls, arg)); foreach (LootDrop item in list) { stringBuilder.Append("\n- ").Append(LootName(item.Item, lang)).Append(": ") .Append(string.Format(lang.PerRoll, Pct(item.Weight / num * 100f, lang))); string text5 = Rarities(item.Rarity, lang); if (text5.Length > 0) { stringBuilder.Append("; ").Append(text5); } } } List<string> list2 = new List<string>(); if (info.ForestTokens > 0) { list2.Add($"{info.ForestTokens} {lang.ForestTokens}"); } if (info.IronTokens > 0) { list2.Add($"{info.IronTokens} {lang.IronTokens}"); } if (info.GoldTokens > 0) { list2.Add($"{info.GoldTokens} {lang.GoldTokens}"); } if (info.Coins > 0) { list2.Add($"{info.Coins} {lang.Coins}"); } stringBuilder.Append("\n\n"); if (list2.Count > 0) { stringBuilder.Append(string.Format(lang.MapExtra, string.Join(", ", list2))).Append(' '); } stringBuilder.Append(lang.MapNote); return new Entry("epicloot.adventure.treasuremap.biome." + Slug(biome), string.Format(lang.MapTitle, text), Cut(string.Format(lang.MapShort, info.Cost, text4, text2, text3)), stringBuilder.ToString(), new string[3] { "epicloot.adventure.treasuremap", "epicloot.adventure.treasurechest", "epicloot.adventure.location" }); } private static string DropCounts(float[][]? drops, Lang lang) { List<(int, float)> list = (from d in drops ?? Array.Empty<float[]>() where d != null && d.Length >= 2 && d[1] > 0f select ((int)d[0], d[1])).ToList(); float total = list.Sum<(int, float)>(((int Count, float Weight) p) => p.Weight); if (list.Count == 0 || total <= 0f) { return "?"; } List<string> list2 = list.Select<(int, float), string>(((int Count, float Weight) p) => ((p.Count == 0) ? lang.Nothing : p.Count.ToString(lang.Culture)) + " (" + Pct(p.Weight / total * 100f, lang) + ")").ToList(); if (list2.Count != 1) { return string.Join(", ", list2.Take(list2.Count - 1)) + " " + lang.Or + " " + list2[list2.Count - 1]; } return list2[0]; } private static string Rarities(float[]? rarity, Lang lang) { if (rarity == null || rarity.Length == 0) { return ""; } float num = rarity.Where((float r) => r > 0f).Sum(); if (num <= 0f) { return ""; } List<string> list = new List<string>(); for (int num2 = 0; num2 < rarity.Length && num2 < lang.RarityNames.Length; num2++) { if (rarity[num2] > 0f) { list.Add(lang.RarityNames[num2] + " " + Pct(rarity[num2] / num * 100f, lang)); } } return string.Join(", ", list); } private static string LootName(string item, Lang lang) { if (item == "ShardUnique") { return lang.UniqueShard; } if (item == "ShardSlotChisel") { return lang.Chisel; } if (item.StartsWith("Tier", StringComparison.Ordinal) && item.EndsWith("Everything", StringComparison.Ordinal)) { string arg = item.Substring(4, item.Length - 4 - "Everything".Length); return string.Format(lang.TierGear, arg) + " (`" + item + "`)"; } return ItemName(item, lang); } private static float RadiusScale() { try { return ((typeof(AdventureDataManager).Assembly.GetType("EpicLoot.Adventure.WorldExtent")?.GetProperty("RadiusScale", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null) is float num && num > 0f) ? num : 1f; } catch { return 1f; } } private static IEnumerable<Entry> GamblePrices(Lang lang, AdventureDataConfig config) { GambleConfig gamble = config.Gamble; if (gamble?.Gambles == null || GatedItemTypeHelper.ItemsByTypeAndBoss == null || GatedItemTypeHelper.ItemsByTypeAndBoss.Count == 0) { yield break; } Dictionary<string, HashSet<string>> dictionary = new Dictionary<string, HashSet<string>>(StringComparer.Ordinal); foreach (string item3 in gamble.Gambles.Where((string t) => !string.IsNullOrEmpty(t)).Distinct()) { if (!GatedItemTypeHelper.ItemsByTypeAndBoss.TryGetValue(item3, out var value) || value == null) { continue; } foreach (KeyValuePair<string, List<string>> item4 in value) { if (item4.Value != null && !string.Equals(item4.Key, "none", StringComparison.OrdinalIgnoreCase)) { if (!dictionary.TryGetValue(item4.Key, out var value2)) { value2 = (dictionary[item4.Key] = new HashSet<string>(StringComparer.Ordinal)); } value2.UnionWith(item4.Value.Where((string i) => !string.IsNullOrEmpty(i))); } } } if (dictionary.Count == 0) { yield break; } Dictionary<string, int> prices = new Dictionary<string, int>(StringComparer.Ordinal); foreach (SecretStashItemConfig item5 in gamble.GambleCosts ?? new List<SecretStashItemConfig>()) { if (item5 != null && !string.IsNullOrEmpty(item5.Item) && !prices.ContainsKey(item5.Item)) { prices[item5.Item] = item5.CoinsCost; } } List<string> list = BossOrder(dictionary.Keys); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(lang.PricesIntro); List<Entry> tiersOut = new List<Entry>(); foreach (string item6 in list) { List<string> list2 = dictionary[item6].Where((string i) => i.Length > 0).ToList(); if (list2.Count == 0) { continue; } (string Slug, string Label) tuple = BossTier(item6, lang); string item = tuple.Slug; string item2 = tuple.Label; string text = "epicloot.adventure.gamble.prices." + item; int value4; List<(string, int, bool)> list3 = (from i in list2 select (ItemName(i, lang), prices.TryGetValue(i, out value4) ? value4 : 10000, !prices.ContainsKey(i)) into r orderby r.Item2 select r).ThenBy<(string, int, bool), string>(((string, int, bool) r) => r.Item1, StringComparer.CurrentCulture).ToList(); int num = list3.Min<(string, int, bool)>(((string Name, int Price, bool Missing) r) => r.Price); int num2 = list3.Max<(string, int, bool)>(((string Name, int Price, bool Missing) r) => r.Price); string text2 = ((num == num2) ? num.ToString(lang.Culture) : $"{num}–{num2}"); stringBuilder.Append("\n- [[").Append(text).Append('|') .Append(item2) .Append("]]: ") .Append(string.Format(lang.PricesRange, text2, list3.Count)); StringBuilder stringBuilder2 = new StringBuilder(); stringBuilder2.Append(string.Format(lang.TierIntro, item2)); foreach (var (value3, num3, flag) in list3) { stringBuilder2.Append("\n- ").Append(value3).Append(": ") .Append(num3.ToString(lang.Culture)) .Append(' ') .Append(lang.Coins); if (flag) { stringBuilder2.Append(' ').Append(lang.NoPrice); } } stringBuilder2.Append("\n\n").Append(TokenPrices(gamble, lang)); tiersOut.Add(new Entry(text, string.Format(lang.TierTitle, item2), Cut(string.Format(lang.TierShort, item2, text2)), stringBuilder2.ToString(), new string[2] { "epicloot.adventure.gamble.prices", "epicloot.adventure.gamble.offers" })); } stringBuilder.Append("\n\n").Append(TokenPrices(gamble, lang)).Append(' ') .Append(string.Format(lang.PricesMissing, 10000.ToString("N0", lang.Culture))); yield return new Entry("epicloot.adventure.gamble.prices", lang.PricesTitle, lang.PricesShort, stringBuilder.ToString(), new string[3] { "epicloot.adventure.gamble.offers", "epicloot.adventure.gamble.chance", "epicloot.loot.gating" }); foreach (Entry item7 in tiersOut) { yield return item7; } } private static string TokenPrices(GambleConfig g, Lang lang) { string text = ((g.ForestTokenGambleCostMin == g.ForestTokenGambleCostMax) ? g.ForestTokenGambleCostMin.ToString(lang.Culture) : $"{g.ForestTokenGambleCostMin}–{g.ForestTokenGambleCostMax}"); return string.Format(lang.TokenPrices, Num(g.ForestTokenGambleCoinsCost, lang), text, Num(g.IronBountyGambleCoinsCost, lang), g.IronBountyGambleCost, Num(g.GoldBountyGambleCoinsCost, lang), g.GoldBountyGambleCost); } private static List<string> BossOrder(IEnumerable<string> keys) { List<string> order = new List<string>(); foreach (BiomeDefinition item in BiomeDataManager.BiomesInOrder ?? Array.Empty<BiomeDefinition>()) { foreach (string item2 in item?.BossDefeatedKeys ?? Array.Empty<string>()) { if (!order.Contains(item2)) { order.Add(item2); } } } HashSet<string> hashSet = new HashSet<string>(keys, StringComparer.Ordinal); return order.Where(hashSet.Contains).Concat(hashSet.Where((string k) => !order.Contains(k)).OrderBy<string, string>((string k) => k, StringComparer.Ordinal)).ToList(); } private static (string Slug, string Label) BossTier(string bossKey, Lang lang) { //IL_0031: 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) BiomeDefinition val = ((IEnumerable<BiomeDefinition>)(BiomeDataManager.BiomesInOrder ?? Array.Empty<BiomeDefinition>())).FirstOrDefault((Func<BiomeDefinition, bool>)((BiomeDefinition d) => d?.BossDefeatedKeys != null && d.BossDefeatedKeys.Contains(bossKey))); if (val != null) { return (Slug: Slug(val.Biome), Label: string.Format(lang.TierLabel, BiomeTitle(val.Biome, lang))); } string text = new string((from c in bossKey.ToLowerInvariant() where char.IsLetterOrDigit(c) || c == '_' || c == '-' select c).ToArray()); return (Slug: (text.Length > 0) ? text : "unknown", Label: bossKey); } private static void RegisterValues() { Value("stash_every", (AdventureDataConfig c, Lang l) => Every(c.SecretStash?.RefreshInterval, l)); Value("gamble_every", (AdventureDataConfig c, Lang l) => Every(c.Gamble?.RefreshInterval, l)); Value("map_every", (AdventureDataConfig c, Lang l) => Every(c.TreasureMap?.RefreshInterval, l)); Value("bounty_every", (AdventureDataConfig c, Lang l) => Every(c.Bounties?.RefreshInterval, l)); Value("stash_prices", StashPrices); Value("runestone_prices", (AdventureDataConfig c, Lang l) => Range((from i in c.TreasureMap?.SaleItems?.Where((SecretStashItemConfig i) => i != null && i.ForestTokenCost > 0) select i.ForestTokenCost), l)); Value("andvaranaut_price", (AdventureDataConfig c, Lang l) => c.SecretStash?.OtherItems?.FirstOrDefault((Func<SecretStashItemConfig, bool>)((SecretStashItemConfig i) => i?.Item == "Andvaranaut"))?.CoinsCost.ToString(l.Culture)); Value("andvaranaut_range", (AdventureDataConfig c, Lang l) => EpicLoot.GetAndvaranautRange().ToString(l.Culture)); Value("gamble_coins_count", (AdventureDataConfig c, Lang l) => c.Gamble?.GamblesCount.ToString(l.Culture)); Value("gamble_forest_count", (AdventureDataConfig c, Lang l) => c.Gamble?.ForestTokenGamblesCount.ToString(l.Culture)); Value("gamble_iron_count", (AdventureDataConfig c, Lang l) => c.Gamble?.IronBountyGamblesCount.ToString(l.Culture)); Value("gamble_gold_count", (AdventureDataConfig c, Lang l) => c.Gamble?.GoldBountyGamblesCount.ToString(l.Culture)); Value("gamble_nonmagic", (AdventureDataConfig c, Lang l) => GambleNonMagic(c.Gamble, l)); Value("gamble_coinfactor", (AdventureDataConfig c, Lang l) => (c.Gamble != null) ? Num(c.Gamble.ForestTokenGambleCoinsCost, l) : null); Value("gamble_forest_cost", (AdventureDataConfig c, Lang l) => (c.Gamble != null) ? ((c.Gamble.ForestTokenGambleCostMin != c.Gamble.ForestTokenGambleCostMax) ? $"{c.Gamble.ForestTokenGambleCostMin}–{c.Gamble.ForestTokenGambleCostMax}" : c.Gamble.ForestTokenGambleCostMin.ToString(l.Culture)) : null); Value("gamble_iron_cost", (AdventureDataConfig c, Lang l) => c.Gamble?.IronBountyGambleCost.ToString(l.Culture)); Value("gamble_gold_cost", (AdventureDataConfig c, Lang l) => c.Gamble?.GoldBountyGambleCost.ToString(l.Culture)); Value("gamble_removepurchased", delegate(AdventureDataConfig c, Lang l) { object obj = ElConfig("RemovePurchasedGambles"); if (!(obj is bool)) { return (string?)null; } return (!(bool)obj) ? l.Off : l.On; }); Value("map_prices", (AdventureDataConfig c, Lang l) => Range((from i in c.TreasureMap?.BiomeInfo?.Where((TreasureMapBiomeInfoConfig i) => i != null && i.Cost > 0) select i.Cost), l)); Value("map_tokens", (AdventureDataConfig c, Lang l) => Range((from i in c.TreasureMap?.BiomeInfo?.Where((TreasureMapBiomeInfoConfig i) => i != null && i.Cost > 0) select i.ForestTokens), l)); Value("bounty_iron_stars", (AdventureDataConfig c, Lang l) => (c.Bounties != null) ? StarCount(c.Bounties.IronMinLevel, c.Bounties.IronMaxLevel, l) : null); Value("bounty_gold_stars", (AdventureDataConfig c, Lang l) => (c.Bounties != null) ? StarCount(c.Bounties.GoldMinLevel, c.Bounties.GoldMaxLevel, l) : null); Value("bounty_iron_health", (AdventureDataConfig c, Lang l) => (c.Bounties != null) ? Num(c.Bounties.IronHealthMultiplier, l) : null); Value("bounty_gold_health", (AdventureDataConfig c, Lang l) => (c.Bounties != null) ? Num(c.Bounties.GoldHealthMultiplier, l) : null); Value("bounty_adds_stars", (AdventureDataConfig c, Lang l) => (c.Bounties != null) ? StarCount(c.Bounties.AddsMinLevel, c.Bounties.AddsMaxLevel, l) : null); Value("bounty_adds_health", (AdventureDataConfig c, Lang l) => (c.Bounties != null) ? Num(c.Bounties.AddsHealthMultiplier, l) : null); Value("bounty_specialname", (AdventureDataConfig c, Lang l) => (c.Bounties?.Names != null) ? Pct(c.Bounties.Names.ChanceForSpecialName * 100f, l) : null); Value("map_area", (AdventureDataConfig c, Lang l) => (c.TreasureMap != null) ? Num(Mathf.Max(0f, c.TreasureMap.MinimapAreaRadius) * 2.1f * 0.5f, l, "0") : null); Value("gamble_chance_coins", (AdventureDataConfig c, Lang l) => Chances(c.Gamble?.GambleRarityChance, l)); Value("gamble_chance_forest", (AdventureDataConfig c, Lang l) => Chances(Row(c.Gamble, (ItemRarity)1), l)); Value("gamble_chance_iron", (AdventureDataConfig c, Lang l) => Chances(Row(c.Gamble, (ItemRarity)2), l)); Value("gamble_chance_gold", (AdventureDataConfig c, Lang l) => Chances(Row(c.Gamble, (ItemRarity)3), l)); Value("bounty_limit", delegate(AdventureDataConfig c, Lang l) { object obj = ElConfig("EnableLimitedBountiesInProgress"); if (!(obj is bool)) { return (string?)null; } return (!(bool)obj || !(ElConfig("MaxInProgressBounties") is int num)) ? l.Off : num.ToString(l.Culture); }); } private static void Value(string name, Func<AdventureDataConfig, Lang, string?> provider) { Api.SetValue("el_adv_" + name, (Func<string>)delegate { AdventureDataConfig config = AdventureDataManager.Config; return ((config == null) ? null : provider(config, Lang.For(Texts.Normalize(Api.Locale)))) ?? "?"; }); } private static string? StashPrices(AdventureDataConfig c, Lang lang) { List<SecretStashItemConfig> list = c.SecretStash?.Materials; if (list == null) { return null; } SortedDictionary<int, List<int>> sortedDictionary = new SortedDictionary<int, List<int>>(); foreach (SecretStashItemConfig item in list) { if (item == null || string.IsNullOrEmpty(item.Item)) { continue; } int? num = StashRarity(item.Item); if (num.HasValue) { int valueOrDefault = num.GetValueOrDefault(); if (!sortedDictionary.TryGetValue(valueOrDefault, out var value)) { value = (sortedDictionary[valueOrDefault] = new List<int>()); } value.Add(item.CoinsCost); } } if (sortedDictionary.Count != 0) { return string.Join(", ", from r in sortedDictionary where r.Key >= 0 && r.Key < lang.RarityNames.Length select lang.RarityNames[r.Key] + " " + Range(r.Value, lang)); } return null; } private static int? StashRarity(string item) { //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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected I4, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected I4, but got Unknown foreach (ItemRarity value in Enum.GetValues(typeof(ItemRarity))) { if (item.EndsWith(((object)value/*cast due to .constrained prefix*/).ToString(), StringComparison.Ordinal)) { return (int)value; } } object obj; if (!((Object)(object)ObjectDB.instance != (Object)null)) { obj = null; } else { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } ItemDrop val2 = (ItemDrop)obj; if (val2?.m_itemData == null) { return null; } try { return (int)ItemDataExtensions.GetRarity(val2.m_itemData); } catch (ArgumentException) { return null; } } private static float[]? Row(GambleConfig? g, ItemRarity rarity) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) float[][] array = g?.GambleRarityChanceByRarity; if (array == null || (int)rarity >= array.Length) { return null; } return array[rarity]; } private static string? Chances(float[]? row, Lang lang) { if (row == null || row.Length == 0) { return null; } float num = row.Where((float r) => r > 0f).Sum(); if (num <= 0f) { return null; } List<string> list = new List<string>(); for (int num2 = 0; num2 < row.Length && num2 <= lang.RarityNames.Length; num2++) { float num3 = row[num2] / num * 100f; if (num3 >= 0.01f) { list.Add(Pct(num3, lang) + " " + ((num2 == 0) ? lang.NonMagic : lang.RarityNames[num2 - 1])); } } return string.Join(", ", list); } private static string? GambleNonMagic(GambleConfig? g, Lang lang) { float[] array = g?.GambleRarityChance; if (array == null || array.Length == 0) { return null; } float num = array.Sum(); if (!(num <= 0f)) { return Pct(array[0] / num * 100f, lang); } return null; } private static string? Range(IEnumerable<int>? values, Lang lang) { List<int> list = values?.ToList() ?? new List<int>(); if (list.Count == 0) { return null; } int num = list.Min(); int num2 = list.Max(); if (num != num2) { return num.ToString(lang.Culture) + "–" + num2.ToString(lang.Culture); } return num.ToString(lang.Culture); } private static string StarCount(int minLevel, int maxLevel, Lang lang) { int num = Math.Max(0, minLevel - 1); int num2 = Math.Max(num, maxLevel - 1); if (num != num2) { return $"{num}–{num2}"; } return num.ToString(lang.Culture); } private static string? Every(int? days, Lang lang) { if (!days.HasValue) { return null; } if (!(days <= 1)) { return string.Format(lang.EveryDays, days.Value); } return lang.EveryDay; } private static object? ElConfig(string field) { try { object? obj = typeof(AdventureDataManager).Assembly.GetType("EpicLoot.Config.ELConfig")?.GetField(field, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); object? obj2 = ((obj is ConfigEntryBase) ? obj : null); return (obj2 != null) ? ((ConfigEntryBase)obj2).BoxedValue : null; } catch { return null; } } private static void LoadNames(IEnumerable<string> languages) { List<string> list = (from l in languages.Distinct() where !names.ContainsKey(l) select l).ToList(); if (list.Count == 0) { return; } foreach (string item in list) { names[item] = new Dictionary<string, string>(StringComparer.Ordinal); } try { LocalizationSettings val = Resources.Load<LocalizationSettings>("LocalizationSettings"); if ((Object)(object)val == (Object)null || val.Localizations == null) { Plugin.Log.LogWarning((object)"Valheims Sprachtabellen nicht gefunden; Namen kommen aus der Spielsprache"); return; } foreach (TextAsset localization in val.Localizations) { if ((Object)(object)localization != (Object)null && !string.IsNullOrEmpty(localization.text)) { ReadNames(localization.text, list); } } Plugin.Log.LogInfo((object)("Namen aus Valheims Sprachtabellen: " + string.Join(", ", list.Select((string l) => $"{names[l].Count} {l}")))); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Valheims Sprachtabellen nicht gelesen (" + ex.Message + "); Namen kommen aus der Spielsprache")); } } private static void ReadNames(string csv, List<string> languages) { int num = csv.IndexOf('\n'); if (num < 0) { return; } string[] header = (from h in csv.Substring(0, num).Split(',') select h.Trim().Trim('"', '*', '\r', ' ')).ToArray(); int english = Array.IndexOf(header, "English"); if (english < 0) { return; } List<(Dictionary<string, string>, int)> list = languages.Select((string l) => (names[l], (l == "English") ? english : Array.IndexOf(header, l))).ToList(); foreach (List<string> item3 in Rows(csv, num + 1)) { if (item3.Count == 0) { continue; } string key = item3[0].Trim(); if (key.Length == 0 || key.StartsWith("//", StringComparison.Ordinal) || !NamePrefixes.Any((string p) => key.StartsWith(p, StringComparison.Ordinal))) { continue; } string text = ((item3.Count > english) ? item3[english].Trim() : ""); foreach (var item4 in list) { Dictionary<string, string> item = item4.Item1; int item2 = item4.Item2; string text2 = ((item2 >= 0 && item3.Count > item2) ? item3[item2].Trim() : ""); if (text2.Length == 0) { text2 = text; } if (text2.Length > 0) { item[key] = text2; } } } } private static IEnumerable<List<string>> Rows(string text, int start) { List<string> list = new List<string>(); StringBuilder cell = new StringBuilder(); bool quoted = false; for (int i = start; i < text.Length; i++) { char c = text[i]; switch (c) { case '"': if (quoted && i + 1 < text.Length && text[i + 1] == '"') { cell.Append('"'); i++; } else { quoted = !quoted; } continue; case ',': if (!quoted) { list.Add(cell.ToString()); cell.Length = 0; continue; } break; } if (c == '\n' && !quoted) { list.Add(cell.ToString()); cell.Length = 0; yield return list; list = new List<string>(); } else { cell.Append(c); } } list.Add(cell.ToString()); yield return list; } private static string Localized(string? token, Lang lang, string fallback) { if (string.IsNullOrEmpty(token)) { return fallback; } if (names.TryGetValue(Texts.Language(lang.Code), out Dictionary<string, string> value) && value.TryGetValue(token.TrimStart('$'), out var value2) && value2.Length > 0) { return EffectGlossary.Plain(value2); } if (Localization.instance != null && token.StartsWith("$", StringComparison.Ordinal)) { string text = Localization.instance.Localize(token); if (text.Length > 0 && !text.StartsWith("[", StringComparison.Ordinal) && !text.Contains("$")) { return EffectGlossary.Plain(text); } } return fallback; } private static string MonsterName(string prefab, Lang lang) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null); return Localized((!((Object)(object)val != (Object)null)) ? null : val.GetComponent<Character>()?.m_name, lang, prefab); } private static string ItemName(string prefab, Lang lang) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefab) : null); return Localized((!((Object)(object)val != (Object)null)) ? null : val.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_name, lang, prefab); } private unsafe static string BiomeTitle(Biome biome, Lang lang) { //IL_0000: 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_0020: Unknown result type (might be due to invalid IL or missing references) string key = Slug(biome); if (lang.Biomes.TryGetValue(key, out string value)) { return value; } string name = BiomeDataManager.GetName(biome); return Localized(BiomeDataManager.GetLocalizationToken(biome), lang, string.IsNullOrEmpty(name) ? ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() : name); } private static string BiomeLink(Biome biome, string title) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) string text = "valheim.biome." + Slug(biome); if (!Api.Has(text)) { return title; } return "[[" + text + "|" + title + "]]"; } private unsafe static string Slug(Biome biome) { //IL_0000: 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_005d: Expected I4, but got Unknown string text = BiomeDataManager.GetName(biome); if (string.IsNullOrEmpty(text)) { text = ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString(); } string text2 = new string((from c in text.ToLowerInvariant() where (c >= 'a' && c <= 'z') || char.IsDigit(c) || c == '_' || c == '-' select c).ToArray()); if (text2.Length <= 0) { return ((int)biome).ToString(CultureInfo.InvariantCulture); } return text2; } private static List<Biome> InOrder(IEnumerable<Biome> biomes) { HashSet<Biome> hashSet = new HashSet<Biome>(biomes); List<Biome> order = (from d in BiomeDataManager.BiomesInOrder ?? Array.Empty<BiomeDefinition>() where d != null select d.Biome).Where(hashSet.Contains).Distinct().ToList(); order.AddRange(from b in hashSet where !order.Contains(b) orderby (int)b select b); return order; } private static string Num(float value, Lang lang, string format = "0.##") { return value.ToString(format, lang.Culture); } private static string Pct(float value, Lang lang) { return string.Format(lang.Percent, value.ToString("0.#", lang.Culture)); } private static string Cut(string text) { if (text.Length > 140) { return text.Substring(0, 137).TrimEnd() + "…"; } return text; } private static string ToJson(Lang lang, List<Entry> entries) { HashSet<string> own = new HashSet<string>(entries.Select((Entry e) => e.Key), StringComparer.Ordinal); StringBuilder stringBuilder = new StringBuilder("{\n\"$locale\": "); stringBuilder.Append(Json.Quote(lang.Code)); foreach (Entry entry in entries) { stringBuilder.Append(",\n").Append(Json.Quote(entry.Key)).Append(": {\"title\": ") .Append(Json.Quote(entry.Title)); stringBuilder.Append(", \"short\": ").Append(Json.Quote(entry.Short)); stringBuilder.Append(", \"body\": ").Append(Json.Quote(entry.Body)); List<string> list = entry.See.Where((string k) => own.Contains(k) || Api.Has(k)).ToList(); if (list.Count > 0) { stringBuilder.Append(", \"see\": [").Append(string.Join(", ", list.Select(Json.Quote))).Append(']'); } stringBuilder.Append('}'); } return stringBuilder.Append("\n}").ToString(); } } internal static class Concepts { private const string Owner = "DeepTip_EpicLoot.Begriffe"; private const string Prefix = "DeepTipEpicLoot.begriffe."; internal static void Register() { List<string> locales = (from n in Assembly.GetExecutingAssembly().GetManifestResourceNames() where n.StartsWith("DeepTipEpicLoot.begriffe.", StringComparison.Ordinal) && n.EndsWith(".json", StringComparison.Ordinal) select n.Substring("DeepTipEpicLoot.begriffe.".Length, n.Length - "DeepTipEpicLoot.begriffe.".Length - ".json".Length)).OrderBy<string, string>((string l) => l, StringComparer.Ordinal).ToList(); foreach (string item in new string[2] { "de", "en" }.Where((string l) => !locales.Contains(l))) { Plugin.Log.LogWarning((object)("begriffe." + item + ".json fehlt in der DLL")); } foreach (string item2 in locales) { string text = Resource("begriffe." + item2 + ".json"); if (text != null) { Api.Register("DeepTip_EpicLoot.Begriffe", text, item2); } } } internal static string? Resource(string file) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DeepTipEpicLoot." + file); if (stream == null) { return null; } using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } } internal static class EffectGlossary { internal sealed class Lang { public string Code = ""; public CultureInfo Culture = CultureInfo.InvariantCulture; public string Percent = "{0}%"; public string[] Rarities = new string[6]; public string Values = ""; public string Steps = ""; public string Appears = ""; public string NotOn = ""; public string NotWith = ""; public string OnlyWith = ""; public string Multiple = ""; public string NoRoll = ""; public string Note = ""; public string Table = ""; public string NoAugment = ""; public string NoDisenchant = ""; public string NoRune = ""; public string SkillWeapons = "{0}"; public string OnlyRarity = "{0}"; public Dictionary<string, string> ItemTypes = new Dictionary<string, string>(); public Dictionary<string, string> Skills = new Dictionary<string, string>(); public Dictionary<string, (string Yes, string No)> Flags = new Dictionary<string, (string, string)>(); public string Pct(string number) { return string.Format(Percent, number); } public string ItemType(string type) { if (!ItemTypes.TryGetValue(type, out string value)) { return type; } return value; } public string Skill(string skill) { if (!Skills.TryGetValue(skill, out string value)) { return skill; } return value; } public string Flag(string field, bool value) { if (!Flags.TryGetValue(field, out (string, string) value2)) { return field + (value ? "" : " = false"); } if (!value) { return value2.Item2; } return value2.Item1; } internal static Lang For(string locale) { return Texts.Load<Lang>("effect", locale); } } private const string Owner = "DeepTip_EpicLoot.Effekte"; private static readonly Regex Placeholder = new Regex("\\{[^}]*\\}"); private static readonly Regex Tags = new Regex("<[^>]+>"); private static readonly Regex Spaces = new Regex("\\s+"); private static readonly Regex Brackets = new Regex("\\([^)]*\\)"); private static readonly char[] NameTrim = new char[22] { ' ', '+', '-', '%', ':', '(', ')', '[', ']', '/', ',', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; private static readonly Regex Markup = new Regex("\\*\\*|\\[\\[(?:[^\\]|]+\\|)?([^\\]]+)\\]\\]"); internal static void Rebuild() { try { List<MagicItemEffectDefinition> list = MagicItemEffectDefinitions.AllDefinitions.Values.Where((MagicItemEffectDefinition d) => d != null).OrderBy<MagicItemEffectDefinition, string>((MagicItemEffectDefinition d) => d.Type, StringComparer.Ordinal).ToList(); List<string> locales = Texts.Locales; Api.Unregister("DeepTip_EpicLoot.Effekte"); foreach (string item in locales) { Api.Register("DeepTip_EpicLoot.Effekte", Build(Lang.For(item), list, Texts.EpicLoot(item), Texts.Effects(item)), item); } int num = list.Count((MagicItemEffectDefinition d) => Texts.Effects(locales[0]).ContainsKey(d.Type)); Plugin.Log.LogInfo((object)$"{list.Count} EpicLoot-Effekte erklärt, davon {num} mit am Code geprüftem Text"); } catch (Exception arg) { Plugin.Log.LogError((object)$"EpicLoot-Effekte nicht erklärt: {arg}"); } } internal static string Key(string type) { return "epicloot.effect." + type.ToLowerInvariant(); } internal static Dictionary<string, object?> EpicLootLanguage(string language) { using Stream stream = typeof(MagicItemEffectDefinitions).Assembly.GetManifestResourceStream("EpicLoot.localizations." + language + ".json"); if (stream == null) { Plugin.Log.LogWarning((object)("EpicLoot hat keine Sprachdatei " + language)); return new Dictionary<string, object>(); } using StreamReader streamReader = new StreamReader(stream); return Json.Parse(streamReader.ReadToEnd()); } private static string Build(Lang lang, List<MagicItemEffectDefinition> defs, Dictionary<string, object?> epicLoot, Dictionary<string, object?> texts) { Dictionary<string, string> dictionary = (from d in defs group d by d.Type).ToDictionary((IGrouping<string, MagicItemEffectDefinition> g) => g.Key, (IGrouping<string, MagicItemEffectDefinition> g) => Title(Display(g.First(), epicLoot))); Dictionary<string, List<string>> dictionary2 = (from d in defs group d by d.Type).ToDictionary((IGrouping<string, MagicItemEffectDefinition> g) => g.Key, (IGrouping<string, MagicItemEffectDefinition> g) => Aliases(g.First(), Display(g.First(), epicLoot), epicLoot)); Dictionary<string, string> owners = Owners(dictionary2); StringBuilder stringBuilder = new StringBuilder("{\n\"$locale\": "); stringBuilder.Append(Json.Quote(lang.Code)); List<string> list = ((IEnumerable<string>)new string[3] { "epicloot.rarity", "epicloot.rollrange", "epicloot.stars" }).Where((Func<string, bool>)Api.Has).ToList(); foreach (MagicItemEffectDefinition def in defs) { string display = Display(def, epicLoot); object value; Dictionary<string, object> text = (texts.TryGetValue(def.Type, out value) ? (value as Dictionary<string, object>) : null); string text2 = Field(text, "text"); string text3 = Field(text, "abweichung"); string text4 = ((text2.Length > 0) ? text2 : Plain(Lookup(epicLoot, DescriptionKey(def)) ?? "")); List<string> list2 = new List<string>(); if (text4.Length > 0) { list2.Add(text4); } if (text3.Length > 0) { list2.Add("**" + lang.Note + "** " + text3); } bool flag = ShardGlossary.IsShardOnly(def); if (!flag) { string text5 = Values(def, display, lang); if (text5 != null) { list2.Add(text5); } } if (!flag) { list2.AddRange(Requirements(def, lang, dictionary)); string text6 = TableFlags(def, lang); if (text6 != null) { list2.Add(text6); } } string text7 = ShardGlossary.StonesLine(def.Type, lang.Code, epicLoot, flag); if (text7 != null) { list2.Add(text7); } stringBuilder.Append(",\n").Append(Json.Quote(Key(def.Type))).Append(": {\"title\": ") .Append(Json.Quote(dictionary[def.Type])); stringBuilder.Append(", \"short\": ").Append(Json.Quote(Short(text4, dictionary[def.Type]))); stringBuilder.Append(", \"body\": ").Append(Json.Quote(string.Join("\n\n", list2))); string value2; List<string> list3 = dictionary2[def.Type].Where((string a) => owners.TryGetValue(a, out value2) && value2 == def.Type).ToList(); if (list3.Count > 0) { stringBuilder.Append(", \"aliases\": [").Append(string.Join(", ", list3.Select(Json.Quote))).Append(']'); } if (list.Count > 0) { stringBuilder.Append(", \"see\": [").Append(string.Join(", ", list.Select(Json.Quote))).Append(']'); } stringBuilder.Append('}'); } return stringBuilder.Append("\n}").ToString(); } internal static string? Lookup(Dictionary<string, object?> table, string key) { if (!table.TryGetValue(key.TrimStart('$'), out object value)) { return null; } return value as string; } private static string DisplayKey(MagicItemEffectDefinition def) { if (!string.IsNullOrEmpty(def.DisplayText)) { return def.DisplayText.TrimStart('$'); } return "mod_epicloot_me_" + def.Type.ToLowerInvariant() + "_display"; } private static string DescriptionKey(MagicItemEffectDefinition def) { if (!string.IsNullOrEmpty(def.Description)) { return def.Description.TrimStart('$'); } string text = DisplayKey(def); return (text.EndsWith("_display") ? text.Substring(0, text.Length - "_display".Length) : text) + "_desc"; } internal static string Display(MagicItemEffectDefinition def, Dictionary<string, object?> table) { string text = Lookup(table, DisplayKey(def)); if (string.IsNullOrEmpty(text) && Localization.instance != null && !string.IsNullOrEmpty(def.DisplayText)) { string text2 = Localization.instance.Localize(def.DisplayText); text = (text2.StartsWith("[") ? null : text2); } if (!string.IsNullOrEmpty(text)) { return text; } return def.Type; } internal static string Plain(string text) { return Spaces.Replace(Tags.Replace(text, ""), " ").Trim(); } internal static string Title(string display) { return Spaces.Replace(Placeholder.Replace(Plain(display), "X"), " ").Trim(); } private static List<string> Aliases(MagicItemEffectDefinition def, string display, Dictionary<string, object?> table) { List<string> list = new List<string>(); Add(list, Name(display)); string text = DisplayKey(def); string arg = (text.EndsWith("_display") ? text.Substring(0, text.Length - "_display".Length) : text); for (int i = 1; i <= 9; i++) { Add(list, Lookup(table, $"{arg}_prefix{i}")); Add(list, Lookup(table, $"{arg}_suffix{i}")); } return list; } internal static string Name(string display) { string text = Brackets.Replace(Plain(display), " "); int num = text.IndexOf('{'); string text2 = ((num >= 0) ? text.Substring(0, num) : text); int num2 = text2.IndexOf(':'); text2 = ((num2 > 0) ? text2.Substring(0, num2) : text2).Trim(NameTrim); string text3; if (text2.Length <= 0) { text3 = (from p in Placeholder.Split(text) select p.Trim(NameTrim) into p orderby p.Length descending select p).FirstOrDefault(); if (text3 == null) { return ""; } } else { text3 = text2; } return text3; } private static Dictionary<string, string> Owners(Dictionary<string, List<string>> candidates) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); foreach (IGrouping<string, string> item in candidates.SelectMany<KeyValuePair<string, List<string>>, (string, string)>((KeyValuePair<string, List<string>> c) => c.Value.Select((string alias) => (alias: alias, type: c.Key))).GroupBy<(string, string), string, string>(((string alias, string type) x) => x.alias, ((string alias, string type) x) => x.type, StringComparer.OrdinalIgnoreCase)) { List<string> types = item.Distinct().ToList(); string text = ((types.Count == 2) ? types.FirstOrDefault((string t) => types.Contains(t + "LowHealth")) : null); if (types.Count == 1 || text != null) { dictionary[item.Key] = text ?? types[0]; } } return dictionary; } private static void Add(List<string> aliases, string? alias) { if (alias != null) { string text = Plain(alias); if (text.Length >= 4 && !aliases.Contains<string>(text, StringComparer.OrdinalIgnoreCase)) { aliases.Add(text); } } } private static string Field(Dictionary<string, object?>? text, string name) { if (text == null || !text.TryGetValue(name, out object value) || !(value is string text2)) { return ""; } return text2.Trim(); } private static string Short(string main, string title) { string text = Markup.Replace(main, (Match m) => (!m.Groups[1].Success) ? "" : m.Groups[1].Value); int num = text.IndexOf(". ", StringComparison.Ordinal); string text2 = ((num > 0) ? text.Substring(0, num + 1) : text).Trim(); if (text2.Length == 0) { return title; } if (text2.Length > 140) { return text2.Substring(0, 137).TrimEnd() + "…"; } return text2; } private static string? Values(MagicItemEffectDefinition def, string display, Lang lang) { if (MagicItemEffectDefinitions.IsValuelessEffect(def.Type) || def.ValuesPerRarity == null) { return null; } ValuesPerRarityDef valuesPerRarity = def.ValuesPerRarity; ValueDef[] array = (ValueDef[])(object)new ValueDef[6] { valuesPerRarity.Magic, valuesPerRarity.Rare, valuesPerRarity.Epic, valuesPerRarity.Legendary, valuesPerRarity.Mythic, valuesPerRarity.Ancient }; bool flag = display.Contains("%"); List<string> list = new List<string>(); float? num = null; bool flag2 = true; for (int i = 0; i < array.Length; i++) { ValueDef val = array[i]; if (val != null) { string text = (Mathf.Approximately(val.MinValue, val.MaxValue) ? Num(val.MinValue, lang) : (Num(val.MinValue, lang) + "–" + Num(val.MaxValue, lang))); list.Add(lang.Rarities[i] + " " + (flag ? lang.Pct(text) : text)); if (!num.HasValue) { num = val.Increment; } else if (!Mathf.Approximately(num.Value, val.Increment)) { flag2 = false; } } } if (list.Count == 0) { return null; } string text2 = "**" + lang.Values + "** " + string.Join(", ", list); if (flag2 && num.HasValue) { float valueOrDefault = num.GetValueOrDefault(); if (valueOrDefault > 0f && !Mathf.Approximately(valueOrDefault, 1f)) { text2 = text2 + " (" + string.Format(lang.Steps, Num(valueOrDefault, lang)) + ")"; } } return text2 + "."; } internal static string Num(float value, Lang lang) { return value.ToString("0.##", lang.Culture); } private unsafe static IEnumerable<string> Requirements(MagicItemEffectDefinition def, Lang lang, Dictionary<string, string> titles) { MagicItemEffectRequirements q = def.Requirements; if (q == null) { yield break; } if (q.NoRoll) { yield return lang.NoRoll; } List<string> list = new List<string>(); List<string> allowedItemTypes = q.AllowedItemTypes; if (allowedItemTypes != null && allowedItemTypes.Count > 0) { list.Add(string.Join(", ", q.AllowedItemTypes.Select(lang.ItemType))); } List<SkillType> allowedSkillTypes = q.AllowedSkillTypes; if (allowedSkillTypes != null && allowedSkillTypes.Count > 0) { list.Add(string.Format(lang.SkillWeapons, string.Join(", ", q.AllowedSkillTypes.Select((SkillType t) => lang.Skill(((object)(*(SkillType*)(&t))/*cast due to .constrained prefix*/).ToString()))))); } List<string> allowedItemNames = q.AllowedItemNames; if (allowedItemNames != null && allowedItemNames.Count > 0) { list.Add(string.Join(", ", q.AllowedItemNames.Select(ItemName))); } List<ItemRarity> allowedRarities = q.AllowedRarities; if (allowedRarities != null && allowedRarities.Count > 0) { list.Add(string.Format(lang.OnlyRarity, string.Join(", ", q.AllowedRarities.Select((ItemRarity r) => lang.Rarities[r])))); } FieldInfo[] fields = typeof(MagicItemEffectRequirements).GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(bool?) && fieldInfo.GetValue(q) is bool value) { list.Add(lang.Flag(fieldInfo.Name, value)); } } if (list.Count > 0) { yield return "**" + lang.Appears + "** " + string.Join("; ", list) + "."; } List<string> list2 = new List<string>(); List<string> excludedItemTypes = q.ExcludedItemTypes; if (excludedItemTypes != null && excludedItemTypes.Count > 0) { list2.Add(string.Join(", ", q.ExcludedItemTypes.Select(lang.ItemType))); } List<SkillType> excludedSkillTypes = q.ExcludedSkillTypes; if (excludedSkillTypes != null && excludedSkillTypes.Count > 0) { list2.Add(string.Format(lang.SkillWeapons, string.Join(", ", q.ExcludedSkillTypes.Select((SkillType t) => lang.Skill(((object)(*(SkillType*)(&t))/*cast due to .constrained prefix*/).ToString()))))); } List<string> excludedItemNames = q.ExcludedItemNames; if (excludedItemNames != null && excludedItemNames.Count > 0) { list2.Add(string.Join(", ", q.ExcludedItemNames.Select(ItemName))); } List<ItemRarity> excludedRarities = q.ExcludedRarities; if (excludedRarities != null && excludedRarities.Count > 0) { list2.Add(string.Format(lang.OnlyRarity, string.Join(", ", q.ExcludedRarities.Select((ItemRarity r) => lang.Rarities[r])))); } if (list2.Count > 0) { yield return "**" + lang.NotOn + "** " + string.Join("; ", list2) + "."; } List<string> exclusiveEffectTypes = q.ExclusiveEffectTypes; if (exclusiveEffectTypes != null && exclusiveEffectTypes.Count > 0) { yield return "**" + lang.NotWith + "** " + string.Join(", ", q.ExclusiveEffectTypes.Select((string t) => Link(t, titles))) + "."; } List<string> mustHaveEffectTypes = q.MustHaveEffectTypes; if (mustHaveEffectTypes != null && mustHaveEffectTypes.Count > 0) { yield return "**" + lang.OnlyWith + "** " + string.Join(", ", q.MustHaveEffectTypes.Select((string t) => Link(t, titles))) + "."; } if (!q.ExclusiveSelf) { yield return lang.Multiple; } } private static string Link(string type, Dictionary<string, string> titles) { if (!titles.TryGetValue(type, out string value)) { return type; } return "[[" + Key(type) + "|" + value + "]]"; } internal static string ItemName(string prefab) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefab) : null); string text = ((!((Object)(object)val != (Object)null)) ? null : val.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_name); if (text == null || Localization.instance == null) { return prefab; } return Localization.instance.Localize(text); } private static string? TableFlags(MagicItemEffectDefinition def, Lang lang) { List<string> list = new List<string>(); if (!def.CanBeAugmented) { list.Add(lang.NoAugment); } if (!def.CanBeDisenchanted) { list.Add(lang.NoDisenchant); } if (!def.CanBeRunified) { list.Add(lang.NoRune); } if (list.Count != 0) { return "**" + lang.Table + "** " + string.Join(", ", list) + "."; } return null; } } internal static class Json { internal static Dictionary<string, object?> Parse(string text) { int i = 0; return (Value(text.TrimStart('\ufeff'), ref i) as Dictionary<string, object>) ?? new Dictionary<string, object>(); } private static void Skip(string s, ref int i) { while (i < s.Length && char.IsWhiteSpace(s[i])) { i++; } } private static object? Value(string s, ref int i) { Skip(s, ref i); if (i >= s.Length) { return null; } switch (s[i]) { case '{': return Object(s, ref i); case '[': return Array(s, ref i); case '"': return String(s, ref i); default: { int num = i; while (i < s.Length && ",}] \t\r\n".IndexOf(s[i]) < 0) { i++; } string text = s.Substring(num, i - num); if (!(text == "null")) { return text; } return null; } } } private static Dictionary<string, object?> Object(string s, ref int i) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); i++; while (true) { Skip(s, ref i); if (i >= s.Length || s[i] == '}') { break; } if (s[i] == ',') { i++; continue; } string key = String(s, ref i); Skip(s, ref i); i++; dictionary[key] = Value(s, ref i); } i++; return dictionary; } private static List<object?> Array(string s, ref int i) { List<object> list = new List<object>(); i++; while (true) { Skip(s, ref i); if (i >= s.Length || s[i] == ']') { break; } if (s[i] == ',') { i++; } else { list.Add(Value(s, ref i)); } } i++; return list; } private static string String(string s, ref int i) { StringBuilder stringBuilder = new StringBuilder(); i++; while (i < s.Length && s[i] != '"') { char c = s[i++]; if (c != '\\' || i >= s.Length) { stringBuilder.Append(c); continue; } char c2 = s[i++]; switch (c2) { case 'n': stringBuilder.Append('\n'); break; case 'r': stringBuilder.Append('\r'); break; case 't': stringBuilder.Append('\t'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'u': { if (i + 4 <= s.Length && int.TryParse(s.Substring(i, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result)) { stringBuilder.Append((char)result); i += 4; } break; } default: stringBuilder.Append(c2); break; } } i++; return stringBuilder.ToString(); } internal static string Quote(string value) { StringBuilder stringBuilder = new StringBuilder("\""); foreach (char c in value) { switch (c) { case '"': stringBuilder.Append("\\\""); continue; case '\\': stringBuilder.Append("\\\\"); continue; case '\n': stringBuilder.Append("\\n"); continue; case '\t': stringBuilder.Append("\\t"); continue; case '\r': continue; } if (c < ' ') { StringBuilder stringBuilder2 = stringBuilder.Append("\\u"); int num = c; stringBuilder2.Append(num.ToString("x4", CultureInfo.InvariantCulture)); } else { stringBuilder.Append(c); } } return stringBuilder.Append('"').ToString(); } } internal static class LegendaryGlossary { private sealed class Counts { public int Uniques; public int Pieces; public int Sets; public int Failed; } private sealed class Entry { public string Title = ""; public string Short = ""; public string Body = ""; public List<string> See = new List<string>(); } private sealed class Words { public EffectGlossary.Lang Lang = new EffectGlossary.Lang(); public string Minutes = "{0} min"; public string Seconds = "{0} s"; public string UniqueIntro = ""; public string UniqueShort = ""; public string PieceIntro = ""; public string PieceShort = ""; public string PieceRoll = ""; public string SetShort = ""; public string SetPieces = ""; public string SetBonuses = ""; public string Base = ""; public string GuaranteedLabel = ""; public string None = ""; public string AllTiers = ""; public string CountLabel = ""; public string CountFixed = ""; public string CountRolled = ""; public string CountRolledPlain = ""; public string CountAtLeast = ""; public string Aura = ""; public string Texture = ""; public string Rivals = ""; public string From = ""; public string Undefined = ""; public string MorePieces = ""; public string Looks = ""; public string AnyItem = ""; public string Except = ""; public string Ability = ""; public string OnKey = ""; public string ByItself = ""; public string Passive = ""; public string Cooldown = ""; public string OwnKey = ""; public string NoKey = ""; public string LookTint = ""; public string LookWeapon = ""; public string LookHands = ""; public string LookArrow = ""; public string LookAura = ""; public string LookParticles = ""; public string UniqueIndexTitle = ""; public string UniqueIndexShort = ""; public string UniqueIndexIntro = ""; public string SetIndexTitle = ""; public string SetIndexShort = ""; public string SetIndexIntro = ""; public string SetIndexLine = ""; internal static Words For(string locale) { Words words = Texts.Load<Words>("legendary", locale); words.Lang = EffectGlossary.Lang.For(locale); return words; } } private const string Owner = "DeepTip_EpicLoot.Legendaer"; private const string UniquePrefix = "epicloot.legendary."; private const string SetPrefix = "epicloot.set."; private const int ShortLength = 140; private static readonly Dictionary<string, string> SetHotkeys = new Dictionary<string, string> { ["OverwhelmingLaunch"] = "OverwhelmingLaunchKey", ["Earthshaker"] = "EarthshakerKey", ["EitrInfusion"] = "EitrInfusionKey", ["ShieldThrow"] = "ShieldThrowKey", ["SpiritAnimal"] = "SpiritAnimalKey" }; private static bool dirty; private static bool builtWithLocalization; private static Type? elConfig; internal static void MarkDirty() { dirty = true; } internal static void Patch(Harmony harmony) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown try { HarmonyMethod val = new HarmonyMethod(typeof(LegendaryGlossary), "MarkDirty", (Type[])null); MethodInfo methodInfo = AccessTools.Method(typeof(UniqueLegendaryHelper), "RefreshDerived", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(AbilityDefinitions), "Initialize", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Plugin.Log.LogWarning((object)"UniqueLegendaryHelper.RefreshDerived fehlt; Unikate und Sets werden nur beim Start erklärt."); } if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception arg) { Plugin.Log.LogError((object)$"Unikat-Erklärungen nicht angemeldet: {arg}"); } MarkDirty(); } internal static void Update() { if (!builtWithLocalization && Localization.instance != null) { dirty = true; } if (dirty) { dirty = false; builtWithLocalization = Localization.instance != null; Rebuild(); } } internal static string UniqueKey(string id) { return "epicloot.legendary." + SafeId(id); } internal static string SetKey(string id) { return "epicloot.set." + SafeId(id); } private static string SafeId(string id) { return new string(id.ToLowerInvariant().Select(delegate(char c) { bool flag; switch (c) { case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '_': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': flag = true; break; default: flag = false; break; } return (!flag) ? '_' : c; }).ToArray()); } private static void Rebuild() { try { if (UniqueLegendaryHelper.AllUniques.Count == 0 && UniqueLegendaryHelper.AllSets.Count == 0) { return; } List<LegendaryInfo> uniques = UniqueLegendaryHelper.AllUniques.Values.Where((LegendaryInfo u) => u != null && !string.IsNullOrEmpty(u.ID)).OrderBy<LegendaryInfo, string>((LegendaryInfo u) => u.ID, StringComparer.Ordinal).ToList(); List<LegendarySetInfo> sets = UniqueLegendaryHelper.AllSets.Values.Where((LegendarySetInfo s) => s != null && !string.IsNullOrEmpty(s.ID)).OrderBy<LegendarySetInfo, string>((LegendarySetInfo s) => s.ID, StringComparer.Ordinal).ToList(); Api.Unregister("DeepTip_EpicLoot.Legendaer"); Counts counts = null; foreach (string locale in Texts.Locales) { Counts counts2 = new Counts(); Api.Register("DeepTip_EpicLoot.Legendaer", Build(Words.For(locale), uniques, sets, Texts.EpicLoot(locale), counts2), locale); if (counts == null) { counts = counts2; } } Counts counts3 = counts ?? new Counts(); Plugin.Log.LogInfo((object)($"{counts3.Uniques} Unikate, {counts3.Pieces} Set-Teile und {counts3.Sets} Sets erklärt" + ((counts3.Failed > 0) ? $", {counts3.Failed} übersprungen (Fehler oben)" : ""))); } catch (Exception arg) { Plugin.Log.LogError((object)$"Unikate und Sets nicht erklärt: {arg}"); } } private static string Build(Words w, List<LegendaryInfo> uniques, List<LegendarySetInfo> sets, Dictionary<string, object?> table, Counts counts) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (LegendaryInfo unique in uniques) { dictionary[UniqueKey(unique.ID)] = Name(unique.Name, unique.ID, table); } foreach (LegendarySetInfo set in sets) { dictionary[SetKey(set.ID)] = Name(set.Name, set.ID, table); } HashSet<string> hashSet = new HashSet<string>(from g in dictionary.Values.GroupBy<string, string>((string n) => n, StringComparer.OrdinalIgnoreCase) where g.Count() > 1 select g.Key, StringComparer.OrdinalIgnoreCase); foreach (MagicItemEffectDefinition item in MagicItemEffectDefinitions.AllDefinitions.Values.Where((MagicItemEffectDefinition d) => d != null)) { hashSet.Add(EffectGlossary.Name(EffectGlossary.Display(item, table))); } Dictionary<string, string> titles = new Dictionary<string, string>(); HashSet<string> own = new HashSet<string>(dictionary.Keys) { "epicloot.legendary.index", "epicloot.set.index" }; StringBuilder stringBuilder = new StringBuilder("{\n\"$locale\": "); stringBuilder.Append(Json.Quote(w.Lang.Code)); float setChance = SetChance(); foreach (LegendaryInfo unique2 in uniques) { try { string key = UniqueKey(unique2.ID); bool num = UniqueLegendaryHelper.IsSetPiece(unique2); Entry e = (num ? Piece(w, unique2, dictionary, table, setChance, titles) : Unique(w, unique2, uniques, dictionary, table, titles)); Append(stringBuilder, key, e, dictionary[key], hashSet, own); if (num) { counts.Pieces++; } else { counts.Uniques++; } } catch (Exception ex) { counts.Failed++; Plugin.Log.LogWarning((object)("Unikat " + unique2.ID + " nicht erklärt: " + ex.Message)); } } foreach (LegendarySetInfo set2 in sets) { try { string key2 = SetKey(set2.ID); Append(stringBuilder, key2, Set(w, set2, dictionary, table, titles), dictionary[key2], hashSet, own); counts.Sets++; } catch (Exception ex2) { counts.Failed++; Plugin.Log.LogWarning((object)("Set " + set2.ID + " nicht erklärt: " + ex2.Message)); } } Append(stringBuilder, "epicloot.legendary.index", UniqueIndex(w, uniques, dictionary), null, hashSet, own); Append(stringBuilder, "epicloot.set.index", SetIndex(w, sets, dictionary), null, hashSet, own); return stringBuilder.Append("\n}").ToString(); } private static void Append(StringBuilder json, string key, Entry e, string? alias, HashSet<string> shared, HashSet<string> own) { json.Append(",\n").Append(Json.Quote(key)).Append(": {\"title\": ") .Append(Json.Quote(e.Title)); json.Append(", \"short\": ").Append(Json.Quote(Clamp(e.Short))); json.Append(", \"body\": ").Append(Json.Quote(e.Body)); if (alias != null && alias.Length >= 4 && !shared.Contains(alias)) { json.Append(", \"aliases\": [").Append(Json.Quote(alias)).Append(']'); } List<string> list = e.See.Where((string k) => own.Contains(k) || Api.Has(k)).Distinct().ToList(); if (list.Count > 0) { json.Append(", \"see\": [").Append(string.Join(", ", list.Select(Json.Quote))).Append(']'); } json.Append('}'); } private static Entry Unique(Words w, LegendaryInfo u, List<LegendaryInfo> all, Dictionary<string, string> names, Dictionary<string, object?> table, Dictionary<string, string> titles) { string text = names[UniqueKey(u.ID)]; List<ItemRarity> tiers = UniqueLegendaryHelper.GetRarities(u); string text2 = Tiers(tiers, w); string text3 = Basis(u.Requirements, w); List<string> list = GuaranteedTitles(u, table, titles); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(string.Format(w.UniqueIntro, Esc(text), text2)).Append('\n'); stringBuilder.Append("**" + w.Base + "** ").Append(Esc(text3)).Append('.'); stringBuilder.Append("\n\n").Append(Guaranteed(w, u, tiers, table, titles)); stringBuilder.Append('\n').Append(EffectCount(w, u, tiers)).Append(Looks(w, u)); string signature = Signature(u.Requirements); List<string> list2 = (from o in all where o != u && !UniqueLegendaryHelper.IsSetPiece(o) && Signature(o.Requirements) == signature && UniqueLegendaryHelper.GetRarities(o).Intersect(tiers).Any() select "[[" + UniqueKey(o.ID) + "|" + Label(names[UniqueKey(o.ID)]) + "]]").ToList(); if (list2.Count > 0) { stringBuilder.Append(' ').Append(string.Format(w.Rivals, string.Join(", ", list2))); } return new Entry { Title = text, Short = string.Format(w.UniqueShort, text2, text3, (list.Count > 0) ? string.Join(", ", list) : w.None), Body = stringBuilder.ToString(), See = new List<string> { "epicloot.unique", "epicloot.unique.roll", "epicloot.unique.guaranteed", "epicloot.legendary.index" } }; } private static Entry Piece(Words w, LegendaryInfo u, Dictionary<string, string> names, Dictionary<string, object?> table, float setChance, Dictionary<string, string> titles) { string text = names[UniqueKey(u.ID)]; string text2 = UniqueLegendaryHelper.GetSetForLegendaryItem(u) ?? ""; string text3 = SetKey(text2); string value; string text4 = (names.TryGetValue(text3, out value) ? value : text2); List<ItemRarity> rarities = UniqueLegendaryHelper.GetRarities(u); string text5 = Tiers(rarities, w); string text6 = Basis(u.Requirements, w); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(string.Format(w.PieceIntro, Esc(text), "[[" + text3 + "|" + Label(text4) + "]]", text5)).Append('\n'); stringBuilder.Append("**" + w.Base + "** ").Append(Esc(text6)).Append('.'); stringBuilder.Append("\n\n").Append(Guaranteed(w, u, rarities, table, titles)); stringBuilder.Append('\n').Append(EffectCount(w, u, rarities)).Append(Looks(w, u)); stringBuilder.Append("\n\n").Append(string.Format(w.PieceRoll, Pct(setChance, w))); return new Entry { Title = text, Short = string.Format(w.PieceShort, text4, text5, text6), Body = stringBuilder.ToString(), See = new List<string> { text3, "epicloot.sets", "epicloot.sets.roll", "epicloot.unique.guaranteed" } }; } private static Entry Set(Words w, LegendarySetInfo s, Dictionary<string, string> names, Dictionary<string, object?> table, Dictionary<string, string> titles) { string title = names[SetKey(s.ID)]; List<ItemRarity> rarities = UniqueLegendaryHelper.GetRarities(s); string text = Tiers(rarities, w); int fullSetCount = UniqueLegendaryHelper.GetFullSetCount(s); List<string> list = (s.LegendaryIDs ?? new List<string>()).Where((string id) => !string.IsNullOrEmpty(id)).Distinct().ToList(); List<SetBonusInfo> list2 = (from b in s.SetBonuses ?? new List<SetBonusInfo>() where b?.Effect != null && !string.IsNullOrEmpty(b.Effect.Type) orderby b.Count select b).ToList(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(string.Format(w.SetPieces, fullSetCount)); foreach (string item in list) { stringBuilder.Append("\n- "); if (UniqueLegendaryHelper.AllUniques.TryGetValue(item, out var value) && value != null) { stringBuilder.Append("[[" + UniqueKey(item) + "|" + Label(names[UniqueKey(item)]) + "]] – ").Append(Esc(Basis(value.Requirements, w))); } else { stringBuilder.Append(Esc(item)).Append(' ').Append(w.Undefined); } } stringBuilder.Append("\n\n").Append(w.SetBonuses); foreach (SetBonusInfo item2 in list2) { stringBuilder.Append("\n- ").Append(string.Format(w.From, item2.Count)).Append(' ') .Append(Bonus(w, item2, rarities, table, titles)); } string text2 = SetLooks(w, s); bool flag = fullSetCount > 0 && list.Count > fullSetCount; if (text2.Length > 0 || flag) { stringBuilder.Append("\n\n").Append(text2); if (flag) { stringBuilder.Append((text2.Length > 0) ? " " : "").Append(string.Format(w.MorePieces, list.Count, fullSetCount)); } } string text3 = string.Join(", ", list2.Select((SetBonusInfo b) => b.Count).Distinct()); Entry entry = new Entry(); entry.Title = title; entry.Short = string.Format(w.SetShort, list.Count, text, fullSetCount, (text3.Length > 0) ? text3 : "–"); entry.Body = stringBuilder.ToString(); entry.See = new List<string> { "epicloot.sets", "epicloot.sets.bonus", "epicloot.sets.count", "epicloot.sets.values", "epicloot.set.index" }; return entry; } private static Entry UniqueIndex(Words w, List<LegendaryInfo> uniques, Dictionary<string, string> names) { List<LegendaryInfo> list = uniques.Where((LegendaryInfo u) => !UniqueLegendaryHelper.IsSetPiece(u)).OrderBy<LegendaryInfo, string>((LegendaryInfo u) => names[UniqueKey(u.ID)], StringComparer.CurrentCultureIgnoreCase).ToList(); StringBuilder stringBuilder = new StringBuilder(string.Format(w.UniqueIndexIntro, list.Count)); foreach (LegendaryInfo item in list) { stringBuilder.Append("\n- ").Append("[[" + UniqueKey(item.ID) + "|" + Label(names[UniqueKey(item.ID)]) + "]] – ").Append(Esc(Basis(item.Requirements, w))) .Append(" (") .Append(Tiers(UniqueLegendaryHelper.GetRarities(item), w)) .Append(')'); } return new Entry { Title = w.UniqueIndexTitle, Short = string.Format(w.UniqueIndexShort, list.Count), Body = stringBuilder.ToString(), See = new List<string> { "epicloot.unique", "epicloot.set.index" } }; } private static Entry SetIndex(Words w, List<LegendarySetInfo> sets, Dictionary<string, string> names) { StringBuilder stringBuilder = new StringBuilder(string.Format(w.SetIndexIntro, sets.Count)); foreach (LegendarySetInfo item in sets.OrderBy<LegendarySetInfo, string>((LegendarySetInfo s) => names[SetKey(s.ID)], StringComparer.CurrentCultureIgnoreCase)) { int num = (item.LegendaryIDs ?? new List<string>()).Where((string id) => !string.IsNullOrEmpty(id)).Distinct().Count(); stringBuilder.Append("\n- ").Append("[[" + SetKey(item.ID) + "|" + Label(names[SetKey(item.ID)]) + "]] – ").Append(string.Format(w.SetIndexLine, num, Tiers(UniqueLegendaryHelper.GetRarities(item), w))); } return new Entry { Title = w.SetIndexTitle, Short = string.Format(w.SetIndexShort, sets.Count), Body = stringBuilder.ToString(), See = new List<string> { "epicloot.sets", "epicloot.legendary.index" } }; } private static string Guaranteed(Words w, LegendaryInfo u, List<ItemRarity> tiers, Dictionary<string, object?> table, Dictionary<string, string> titles) { //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) List<GuaranteedMagicEffect> list = (u.GuaranteedMagicEffects ?? new List<GuaranteedMagicEffect>()).Where((GuaranteedMagicEffect g) => g != null && !string.IsNullOrEmpty(g.Type)).ToList(); if (list.Count == 0) { return "**" + w.GuaranteedLabel + "** " + w.None + "."; } StringBuilder stringBuilder = new StringBuilder("**" + w.GuaranteedLabel + "**"); MagicItemEffectDefinition val = default(MagicItemEffectDefinition); foreach (GuaranteedMagicEffect item in list) { stringBuilder.Append("\n- "); if (!MagicItemEffectDefinitions.TryGet(item.Type, ref val)) { stringBuilder.Append(Esc(item.Type)); continue; } string text = EffectGlossary.Display(val, table); stringBuilder.Append("[[" + EffectGlossary.Key(val.Type) + "|" + Label(EffectTitle(val, table, titles)) + "]]"); if (!text.Contains("{")) { continue; } bool percent = text.Contains("%"); List<string> list2 = new List<string>(); List<string> list3 = new List<string>(); foreach (ItemRarity tier in tiers) { ValueDef rollRange = MagicItemEffectDefinitions.GetRollRange(val, tier, u.ID, (ValueDef)null); if (rollRange != null) { string text2 = Range(rollRange.MinValue, rollRange.MaxValue, percent, w); list3.Add(text2); list2.Add(w.Lang.Rarities[tier] + " " + text2); } } if (list2.Count > 0) { stringBuilder.Append(": ").Append((list3.Distinct().Count() == 1 && list2.Count > 1) ? (list3[0] + " " + w.AllTiers) : string.Join(", ", list2)); } } return stringBuilder.ToString(); } private static string EffectCount(Words w, LegendaryInfo u, List<ItemRarity> tiers) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) if (u.GuaranteedEffectCount > 0) { return "**" + w.CountLabel + "** " + string.Format(w.CountFixed, u.GuaranteedEffectCount) + "."; } int num = u.GuaranteedMagicEffects?.Count((GuaranteedMagicEffect g) => g != null) ?? 0; List<string> list = new List<string>(); int num2 = int.MaxValue; foreach (ItemRarity tier in tiers) { List<int> list2; try { list2 = (from c in LootRoller.GetEffectCountsPerRarity(tier, false) where c.Value > 0f select c.Key).ToList(); } catch (Exception) { continue; } if (list2.Count != 0) { num2 = Math.Min(num2, list2.Min()); list.Add(w.Lang.Rarities[tier] + " " + ((list2.Min() == list2.Max()) ? list2.Min().ToString() : (list2.Min() + "–" + list2.Max()))); } } string text = "**" + w.CountLabel + "** " + ((list.Count > 0) ? string.Format(w.CountRolled, string.Join(", ", list)) : w.CountRolledPlain); if (num > 0 && num > ((num2 != int.MaxValue) ? num2 : 0)) { text += string.Format(w.CountAtLeast, num); } return text + "."; } private static string Looks(Words w, LegendaryInfo u) { string text = ""; if (!string.IsNullOrEmpty(u.EquipFx)) { text = text + " " + w.Aura; } List<TextureReplacement> textureReplacements = u.TextureReplacements; if (textureReplacements != null && textureReplacements.Count > 0) { text = text + " " + w.Texture; } return text; } private unsafe static string Bonus(Words w, SetBonusInfo bonus, List<ItemRarity> tiers, Dictionary<string, object?> table, Dictionary<string, string> titles) { //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: 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_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Invalid comparison between Unknown and I4 //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Invalid comparison between Unknown and I4 MagicItemEffectDefinition val = default(MagicItemEffectDefinition); if (!MagicItemEffectDefinitions.TryGet(bonus.Effect.Type, ref val)) { return Esc(bonus.Effect.Type); } StringBuilder stringBuilder = new StringBuilder("[[" + EffectGlossary.Key(val.Type) + "|" + Label(EffectTitle(val, table, titles)) + "]]"); if (EffectGlossary.Display(val, table).Contains("{") && tiers.Count > 0) { List<float> values = tiers.Select((ItemRarity r) => SetBonusEvaluator.GetBonusValue(bonus, r)).ToList(); stringBuilder.Append(", X = "); stringBuilder.Append((values.Distinct().Count() == 1) ? EffectGlossary.Num(values[0], w.Lang) : string.Join(" / ", tiers.Select((ItemRarity r, int i) => w.Lang.Rarities[r] + " " + EffectGlossary.Num(values[i], w.Lang)))); } AbilityDefinition val2 = default(AbilityDefinition); string value3; if (!string.IsNullOrEmpty(val.Ability) && AbilityDefinitions.TryGetAbilityDef(val.Ability, ref val2) && val2 != null) { string text = "epicloot.ability." + SafeId(val2.ID); string value = "[[" + (Api.Has(text) ? text : "epicloot.ability") + "|" + w.Ability + "]]"; AbilityActivationMode activationMode = val2.ActivationMode; string text2 = (((int)activationMode == 1) ? w.ByItself : (((int)activationMode != 2) ? w.Passive : string.Format(w.OnKey, AbilityKeys()))); string value2 = text2; stringBuilder.Append("; ").Append(value).Append(", ") .Append(value2); if (val2.Cooldown > 0f) { stringBuilder.Append(", ").Append(string.Format(w.Cooldown, Duration(val2.Cooldown, w))); } } else if (SetHotkeys.TryGetValue(val.Type, out value3)) { string arg = ((ConfigValue(value3) is KeyCode val3 && (int)val3 != 0) ? ((object)(*(KeyCode*)(&val3))/*cast due to .constrained prefix*/).ToString() : w.NoKey); stringBuilder.Append("; ").Append(string.Format(w.OwnKey, arg)); } return stringBuilder.ToString(); } private static string SetLooks(Words w, LegendarySetInfo s) { List<string> list = new List<string>(); if (s.ArmorTint != null) { list.Add(w.LookTint); } if (s.WeaponGlow != null) { list.Add(w.LookWeapon); } if (s.HandGlow != null) { list.Add(w.LookHands); } if (s.DrawArrow != null) { list.Add(w.LookArrow); } if (s.BodyAura != null) { list.Add(w.LookAura); } List<string> fullSetFx = s.FullSetFx; if (fullSetFx != null && fullSetFx.Count > 0) { list.Add(w.LookParticles); } if (list.Count != 0) { return string.Format(w.Looks, string.Join(", ", list)); } return ""; } private unsafe static string Basis(MagicItemEffectRequirements? q, Words w) { if (q == null) { return w.AnyItem; } EffectGlossary.Lang lang = w.Lang; List<string> list = new List<string>(); List<string> allowedItemTypes = q.AllowedItemTypes; string text = ((allowedItemTypes != null && allowedItemTypes.Count > 0) ? string.Join(", ", q.AllowedItemTypes.Distinct().Select(lang.ItemType)) : ""); List<SkillType> allowedSkillTypes = q.AllowedSkillTypes; string text2 = ((allowedSkillTypes != null && allowedSkillTypes.Count > 0) ? string.Join(", ", from t in q.AllowedSkillTypes.Distinct() select lang.Skill(((object)(*(SkillType*)(&t))/*cast due to .constrained prefix*/).ToString())) : ""); if (text.Length > 0) { list.Add((text2.Length > 0) ? (text + " (" + text2 + ")") : text); } else if (text2.Length > 0) { list.Add(string.Format(lang.SkillWeapons, text2)); } List<string> allowedItemNames = q.AllowedItemNames; if (allowedItemNames != null && allowedItemNames.Count > 0) { list.Add(string.Join(", ", q.AllowedItemNames.Select(ItemName))); } List<ItemRarity> allowedRarities = q.AllowedRarities; if (allowedRarities != null && allowedRarities.Count > 0) { list.Add(string.Format(lang.OnlyRarity, string.Join(", ", q.AllowedRarities.Select((ItemRarity r) => lang.Rarities[r])))); } FieldInfo[] fields = typeof(MagicItemEffectRequirements).GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(bool?) && fieldInfo.GetValue(q) is bool value) { list.Add(lang.Flag(fieldInfo.Name, value)); } } string text3 = ((list.Count > 0) ? string.Join("; ", list) : w.AnyItem); List<string> list2 = new List<string>(); List<string> excludedItemTypes = q.ExcludedItemTypes; if (excludedItemTypes != null && excludedItemTypes.Count > 0) { list2.Add(string.Join(", ", q.ExcludedItemTypes.Select(lang.ItemType))); } List<SkillType> excludedSkillTypes = q.ExcludedSkillTypes; if (excludedSkillTypes != null && excludedSkillTypes.Count > 0) { list2.Add(string.Join(", ", q.ExcludedSkillTypes.Select((SkillType t) => lang.Skill(((object)(*(SkillType*)(&t))/*cast due to .constrained prefix*/).ToString())))); } List<string> excludedItemNames = q.ExcludedItemNames; if (excludedItemNames != null && excludedItemNames.Count > 0) { list2.Add(string.Join(", ", q.ExcludedItemNames.Select(ItemName))); } if (list2.Count <= 0) { return text3; } return text3 + "; " + w.Except + " " + string.Join(", ", list2); } private static string Signature(MagicItemEffectRequirements? q) { if (q == null) { return ""; } StringBuilder stringBuilder = new StringBuilder(); FieldInfo[] fields = typeof(MagicItemEffectRequirements).GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { object value = fieldInfo.GetValue(q); string text = ((value == null) ? "" : ((value is string text2) ? text2 : ((!(value is IEnumerable source)) ? value.ToString() : string.Join(",", (from object o in source select o?.ToString() ?? "").OrderBy<string, string>((string x) => x, StringComparer.Ordinal))))); string value2 = text; stringBuilder.Append(fieldInfo.Name).Append('=').Append(value2) .Append(';'); } return stringBuilder.ToString(); } private static string ItemName(string item) { if (item.StartsWith("$") && Localization.instance != null) { string text = Localization.instance.Localize(item); if (!text.StartsWith("[")) { return text; } return item; } return EffectGlossary.ItemName(item); } private static string Name(string? token, string id, Dictionary<string, object?> table) { if (string.IsNullOrEmpty(token)) { return id; } string text = EffectGlossary.Lookup(table, token); if (string.IsNullOrEmpty(text) && Localization.instance != null) { string text2 = Localization.instance.Localize(token); text = (text2.StartsWith("[") ? null : text2); } if (string.IsNullOrEmpty(text)) { text = (token.StartsWith("$") ? id : token); } string text3 = EffectGlossary.Plain(text); if (text3.Length <= 0) { return id; } return text3; } private static string EffectTitle(MagicItemEffectDefinition def, Dictionary<string, object?> table, Dictionary<string, string> titles) { if (!titles.TryGetValue(def.Type, out string value)) { value = EffectGlossary.Title(EffectGlossary.Display(def, table)); titles[def.Type] = value; } return value; } private static List<string> GuaranteedTitles(LegendaryInfo u, Dictionary<string, object?> table, Dictionary<string, string> titles) { MagicItemEffectDefinition def = default(MagicItemEffectDefinition); return (from g in u.GuaranteedMagicEffects ?? new List<GuaranteedMagicEffect>() where g != null && !string.IsNullOrEmpty(g.Type) select (!MagicItemEffectDefinitions.TryGet(g.Type, ref def)) ? g.Type : EffectTitle(def, table, titles)).ToList(); } private static string Tiers(List<ItemRarity> tiers, Words w) { if (tiers.Count != 0) { return string.Join(", ", tiers.Select((ItemRarity r) => w.Lang.Rarities[r])); } return "–"; } private static string Range(float min, float max, bool percent, Words w) { string text = (Mathf.Approximately(min, max) ? EffectGlossary.Num(min, w.Lang) : (EffectGlossary.Num(min, w.Lang) + "–" + EffectGlossary.Num(max, w.Lang))); if (!percent) { return text; } return w.Lang.Pct(text); } private static string Pct(float fraction, Words w) { return w.Lang.Pct(EffectGlossary.Num(fraction * 100f, w.Lang)); } private static string Duration(float seconds, Words w) { if (!(seconds >= 120f) || !Mathf.Approximately(seconds % 60f, 0f)) { return string.Format(w.Seconds, EffectGlossary.Num(seconds, w.Lang)); } return string.Format(w.Minutes, EffectGlossary.Num(seconds / 60f, w.Lang)); } private static string AbilityKeys() { try { if ((object)elConfig == null) { elConfig = AccessTools.TypeByName("EpicLoot.Config.ELConfig"); } if (elConfig != null && AccessTools.Field(elConfig, "AbilityKeyCodes")?.GetValue(null) is Array source) { List<string> list = (from k in source.Cast<object>().Select(delegate(object e) { object obj = ((e is ConfigEntryBase) ? e : null); return ((obj != null) ? ((ConfigEntryBase)obj).BoxedValue : null) as string; }) where !string.IsNullOrEmpty(k) select k.ToUpperInvariant()).ToList(); if (list.Count > 0) { return string.Join("/", list); } } } catch (Exception) { } return "G/H/J"; } private static object? ConfigValue(string field) { try { if ((object)elConfig == null) { elConfig = AccessTools.TypeByName("EpicLoot.Config.ELConfig"); } object result; if (!(elConfig == null)) { object? obj = AccessTools.Field(elConfig, field)?.GetValue(null); object? obj2 = ((obj is ConfigEntryBase) ? obj : null); result = ((obj2 != null) ? ((ConfigEntryBase)obj2).BoxedValue : null); } else { result = null; } return result; } catch (Exception) { return null; } } private static float SetChance() { object obj = ConfigValue("SetItemDropChance"); if (obj is float) { return (float)obj; } return 0.15f; } private static string Label(string text) { return text.Replace('[', '(').Replace(']', ')').Replace('|', '/'); } private static string Esc(string text) { StringBuilder stringBuilder = new StringBuilder(text.Length); foreach (char value in text) { if ("\\*`[]{}|".IndexOf(value) >= 0) { stringBuilder.Append('\\'); } stringBuilder.Append(value); } return stringBuilder.ToString(); } private static string Clamp(string text) { string text2 = EffectGlossary.Plain(text); if (text2.Length > 140) { return text2.Substring(0, 137).TrimEnd() + "…"; } return text2; } } [BepInPlugin("gorduan.deeptip.epicloot", "DeepTip EpicLoot", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "gorduan.deeptip.epicloot"; public const string Name = "DeepTip EpicLoot"; public const string Version = "1.2.0"; private const string EpicLootGuid = "randyknapp.mods.epicloot"; internal static ManualLogSource Log; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing