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 ValheimUltimateUpgrades v0.8.0
plugins/ValheimUltimateUpgrades.dll
Decompiled 23 minutes ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyVersion("0.8.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimUltimateUpgrades { [BepInPlugin("local.valheim.ultimateupgrades", "Valheim Ultimate Upgrades", "0.8.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { private sealed class RefComparer : IEqualityComparer<object> { public new bool Equals(object x, object y) { return x == y; } public int GetHashCode(object x) { return RuntimeHelpers.GetHashCode(x); } } private sealed class Snapshot { public int MaxQuality; public float Durability; public float DurabilityPerLevel; public float ArmorPerLevel; public float BlockPerLevel; public object DamagePerLevel; public int MinStation; } [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyAfter(new string[] { "org.bepinex.helpers.ItemManager" })] private static class PatchAwake { private static void Postfix(ObjectDB __instance) { if ((Object)(object)Instance != (Object)null) { Instance.Apply(__instance); } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] [HarmonyAfter(new string[] { "org.bepinex.helpers.ItemManager" })] private static class PatchCopy { private static void Postfix(ObjectDB __instance) { if ((Object)(object)Instance != (Object)null) { Instance.Apply(__instance); } } } internal static Plugin Instance; private ConfigEntry<int> globalCap; private ConfigEntry<float> materialCostGrowth; private ConfigEntry<bool> perItemConfig; private ConfigEntry<bool> enabled; private ConfigEntry<float> weaponsDamage; private ConfigEntry<float> armorGrowth; private ConfigEntry<float> shieldGrowth; private ConfigEntry<float> durability; private ConfigEntry<int> minimumStation; private readonly Dictionary<object, Snapshot> original = new Dictionary<object, Snapshot>(new RefComparer()); private readonly HashSet<string> seen = new HashSet<string>(); private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private void Awake() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Expected O, but got Unknown Instance = this; enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable equipment tuning and station requirement limits. Restart the game after changing this setting.\n(Включает изменение характеристик снаряжения и ограничение требований к станциям. После изменения перезапустите игру.)"); globalCap = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaximumItemLevel", 100, new ConfigDescription("Maximum equipment quality, from 1 to 100. Separate station settings limit the required station level. Restart the game after changes.\n(Максимальное качество снаряжения: от 1 до 100. Требуемый уровень станции ограничивается отдельными настройками станций. После изменения перезапустите игру.)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); perItemConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "CreatePerItemOverrides", false, "Off by default: use global settings only. Enabling creates thousands of per-item settings and can severely slow the settings menu. Old per-item values stay on disk but apply only when enabled. Restart after changes.\n(По умолчанию выключено: используются общие настройки. Включение создаёт тысячи индивидуальных параметров и может сильно замедлить меню. Старые значения сохраняются в файле, но применяются только при включении. После изменения перезапустите игру.)"); materialCostGrowth = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "OriginalMaterialsCostMultiplierPerLevel", 1f, "Reserved setting; currently has no effect on material costs. Forge of Potential idol costs remain controlled by ReforgedPotential.\n(Резервная настройка: сейчас не влияет на стоимость материалов. Стоимость идолов Кузницы потенциала по-прежнему регулируется ReforgedPotential.)"); weaponsDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Growth", "WeaponDamagePerLevelMultiplier", 1f, "Multiplier for the original weapon damage gain per quality level. 1 keeps the original gain; 2 doubles it. Restart the game after changes.\n(Множитель исходного прироста урона оружия за уровень качества. 1 сохраняет исходный прирост, 2 удваивает его. После изменения перезапустите игру.)"); armorGrowth = ((BaseUnityPlugin)this).Config.Bind<float>("Growth", "ArmorPerLevelMultiplier", 1f, "Multiplier for the original armor gain per quality level. 1 keeps the original gain; 2 doubles it. Restart the game after changes.\n(Множитель исходного прироста брони за уровень качества. 1 сохраняет исходный прирост, 2 удваивает его. После изменения перезапустите игру.)"); shieldGrowth = ((BaseUnityPlugin)this).Config.Bind<float>("Growth", "ShieldBlockPerLevelMultiplier", 1f, "Block armor (damage resistance while blocking) gain multiplier for eligible shields and weapons. Also scales the added gain when the original gain is missing. 1 means normal gain; 0 disables this gain. Restart after changes.\n(Множитель прироста сопротивления урону при блокировании для подходящих щитов и оружия. Также влияет на добавленный прирост, если исходного нет. 1 — обычный прирост, 0 — без этого прироста. После изменения перезапустите игру.)"); durability = ((BaseUnityPlugin)this).Config.Bind<float>("Durability", "StartingDurabilityPercent", 100f, "Base durability as a percentage of the original value. 100 keeps the original durability; 200 doubles it. Durability gained per quality level is unchanged. Restart after changes.\n(Базовая прочность в процентах от исходной. 100 сохраняет исходную прочность, 200 удваивает её. Прирост прочности за уровень качества не меняется. После изменения перезапустите игру.)"); minimumStation = ((BaseUnityPlugin)this).Config.Bind<int>("Stations", "MinimumStationLevel", 1, "Legacy minimum station level: only applies if the item data supports it. It does not cap recipe requirements. Use each station's Maximum station level setting to remove impossible upgrade requirements. Restart after changes.\n(Устаревшая настройка минимального уровня станции: действует только при поддержке в данных предмета. Она не ограничивает требования рецептов. Для устранения недостижимых требований используйте «Максимальный уровень станции» у каждой станции. После изменения перезапустите игру.)"); StationLimits.Initialize(((BaseUnityPlugin)this).Config); Harmony val = new Harmony("local.valheim.ultimateupgrades"); val.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Ultimate Upgrades 0.8.0 started. ReforgedPotential Forge of Potential mechanics are left intact."); } private static FieldInfo Field(object o, string name) { return o?.GetType().GetField(name, Flags); } private static float Float(object o, string field, float fallback = 0f) { FieldInfo fieldInfo = Field(o, field); return (fieldInfo != null) ? Convert.ToSingle(fieldInfo.GetValue(o), CultureInfo.InvariantCulture) : fallback; } private static int Int(object o, string field, int fallback = 0) { FieldInfo fieldInfo = Field(o, field); return (fieldInfo != null) ? Convert.ToInt32(fieldInfo.GetValue(o), CultureInfo.InvariantCulture) : fallback; } private static void Set(object o, string field, object value) { FieldInfo fieldInfo = Field(o, field); if (fieldInfo != null) { fieldInfo.SetValue(o, Convert.ChangeType(value, fieldInfo.FieldType, CultureInfo.InvariantCulture)); } } private static string Safe(string s) { char[] array = s.ToCharArray(); for (int i = 0; i < array.Length; i++) { if (!char.IsLetterOrDigit(array[i]) && array[i] != '_' && array[i] != '-') { array[i] = '_'; } } return new string(array); } private static object ScaleDamage(object dmg, float factor) { if (dmg == null) { return null; } object obj = (dmg.GetType().IsValueType ? RuntimeHelpers.GetObjectValue(dmg) : Activator.CreateInstance(dmg.GetType())); FieldInfo[] fields = dmg.GetType().GetFields(Flags); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(float)) { fieldInfo.SetValue(obj, (float)fieldInfo.GetValue(dmg) * factor); } } return obj; } private void ApplyCore(ObjectDB db) { //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Expected O, but got Unknown if ((Object)(object)db == (Object)null || db.m_items == null || !enabled.Value) { return; } int num = 0; foreach (GameObject item in db.m_items) { if (!Object.op_Implicit((Object)(object)item)) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { continue; } object shared = component.m_itemData.m_shared; string text = Field(shared, "m_itemType")?.GetValue(shared)?.ToString() ?? ""; if (!IsEligibleEquipment(text, Int(shared, "m_maxStackSize"), Int(shared, "m_destroyBroken", 1))) { continue; } bool flag = text.Contains("OneHandedWeapon") || text.Contains("TwoHandedWeapon") || text.Contains("Bow") || text.Contains("Ammo") || text.Contains("Torch"); bool flag2 = text.Contains("Shield"); bool flag3 = text.Contains("Chest") || text.Contains("Legs") || text.Contains("Helmet") || text.Contains("Shoulder"); bool flag4 = text.Contains("Tool"); if (flag || flag2 || flag3 || flag4) { if (!original.TryGetValue(shared, out var value)) { value = new Snapshot { MaxQuality = Int(shared, "m_maxQuality", 1), Durability = Float(shared, "m_maxDurability"), DurabilityPerLevel = Float(shared, "m_durabilityPerLevel"), ArmorPerLevel = Float(shared, "m_armorPerLevel"), BlockPerLevel = Float(shared, "m_blockPowerPerLevel"), DamagePerLevel = Field(shared, "m_damagesPerLevel")?.GetValue(shared), MinStation = Int(shared, "m_minStationLevel", 1) }; original.Add(shared, value); } string text2 = "Item." + Safe(((Object)item).name); bool flag5 = true; int value2 = globalCap.Value; float value3 = weaponsDamage.Value; float value4 = armorGrowth.Value; float value5 = shieldGrowth.Value; float value6 = durability.Value; int value7 = minimumStation.Value; if (perItemConfig.Value) { flag5 = ((BaseUnityPlugin)this).Config.Bind<bool>(text2, "EnableUpgrades", true, "Use the custom maximum quality for this item. When disabled, its original quality cap is used; other per-item tuning still applies. Restart after changes.\n(Использовать заданный максимальный уровень качества этого предмета. При отключении действует исходный предел качества; остальные индивидуальные настройки продолжают применяться. После изменения перезапустите игру.)").Value; value2 = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "MaxLevel", globalCap.Value, new ConfigDescription("Maximum quality for this item, from 1 to 100. Requires EnableUpgrades for this item. Restart after changes.\n(Максимальное качество этого предмета: от 1 до 100. Требует включённого EnableUpgrades для этого предмета. После изменения перезапустите игру.)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())).Value; value3 = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "DamageGrowthMultiplier", weaponsDamage.Value, "Multiplier for this item's original damage gain per quality level. 1 keeps the original gain. Restart after changes.\n(Множитель исходного прироста урона этого предмета за уровень качества. 1 сохраняет исходный прирост. После изменения перезапустите игру.)").Value; value4 = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "ArmorGrowthMultiplier", armorGrowth.Value, "Multiplier for this item's original armor gain per quality level. 1 keeps the original gain. Restart after changes.\n(Множитель исходного прироста брони этого предмета за уровень качества. 1 сохраняет исходный прирост. После изменения перезапустите игру.)").Value; value5 = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "BlockGrowthMultiplier", shieldGrowth.Value, "Block armor gain multiplier for this item. Also scales the added gain when the original gain is missing. 1 means normal gain; 0 disables this gain. Restart after changes.\n(Множитель прироста сопротивления урону при блокировании для этого предмета. Также влияет на добавленный прирост, если исходного нет. 1 — обычный прирост, 0 — без этого прироста. После изменения перезапустите игру.)").Value; value6 = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "StartingDurabilityPercent", durability.Value, "Base durability for this item as a percentage of the original value. 100 keeps the original value. Durability gain per quality level is unchanged. Restart after changes.\n(Базовая прочность этого предмета в процентах от исходной. 100 сохраняет исходное значение. Прирост прочности за уровень качества не меняется. После изменения перезапустите игру.)").Value; value7 = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "MinimumStationLevel", minimumStation.Value, "Legacy minimum station level for this item, only where supported by item data. Use the separate station maximum settings to cap recipe requirements. Restart after changes.\n(Устаревшая настройка минимального уровня станции для этого предмета, действующая только при поддержке в его данных. Для ограничения требований рецептов используйте отдельные настройки максимального уровня станций. После изменения перезапустите игру.)").Value; } Set(shared, "m_maxQuality", flag5 ? Math.Max(1, Math.Min(100, value2)) : value.MaxQuality); Set(shared, "m_maxDurability", value.Durability * Math.Max(0f, value6) / 100f); Set(shared, "m_durabilityPerLevel", value.DurabilityPerLevel); Set(shared, "m_armorPerLevel", value.ArmorPerLevel * Math.Max(0f, value4)); Set(shared, "m_blockPowerPerLevel", value.BlockPerLevel * Math.Max(0f, value5)); ResistanceGrowth.Apply((SharedData)shared, value5); FieldInfo fieldInfo = Field(shared, "m_damagesPerLevel"); if (fieldInfo != null && value.DamagePerLevel != null) { fieldInfo.SetValue(shared, ScaleDamage(value.DamagePerLevel, Math.Max(0f, value3))); } if (Field(shared, "m_minStationLevel") != null) { Set(shared, "m_minStationLevel", Math.Max(value.MinStation, value7)); } if (seen.Add(((Object)item).name)) { num++; } } } if (num > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Discovered " + num + " equipment prefabs. Global settings apply by default. Advanced per-item settings require an explicit opt-in; restart after changes.")); } } private void Apply(ObjectDB db) { try { ConfigFile config = ((BaseUnityPlugin)this).Config; bool saveOnConfigSet = config.SaveOnConfigSet; try { config.SaveOnConfigSet = false; ApplyCore(db); StationLimits.Discover(db); } finally { config.SaveOnConfigSet = saveOnConfigSet; } if (saveOnConfigSet) { config.Save(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } private static bool IsEligibleEquipment(string itemType, int maxStackSize, int destroyBroken) { if (maxStackSize == 1 && destroyBroken == 0) { switch (itemType) { case "OneHandedWeapon": case "TwoHandedWeapon": case "TwoHandedWeaponLeft": case "Bow": case "Shield": case "Helmet": case "Chest": case "Legs": case "Shoulder": case "Tool": case "Torch": return true; } } return false; } } internal static class StationLimits { private sealed class HiddenSetting { public bool Browsable; } [HarmonyPatch(typeof(Recipe), "GetRequiredStationLevel", new Type[] { typeof(int) })] private static class RecipeStationPatch { [HarmonyPriority(0)] [HarmonyPostfix] [HarmonyAfter(new string[] { "org.bepinex.helpers.ItemManager" })] private static void Postfix(Recipe __instance, int __0, ref int __result) { if (config == null || enabled == null || !enabled.Value || __0 <= 1 || !Eligible(__instance)) { return; } CraftingStation requiredStation = __instance.GetRequiredStation(__0); if (Object.op_Implicit((Object)(object)requiredStation)) { ConfigEntry<int> val = Entry(requiredStation); if (val != null) { __result = ClampRequirement(__result, __instance.m_minStationLevel, val.Value); } } } } private static ConfigFile config; private static ConfigEntry<bool> enabled; private static readonly Dictionary<string, ConfigEntry<int>> entries = new Dictionary<string, ConfigEntry<int>>(StringComparer.Ordinal); internal static void Initialize(ConfigFile file) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown config = file; enabled = file.Bind<bool>("General", "Enabled", true, "Enable equipment tuning and station requirement limits. Restart the game after changing this setting.\n(Включает изменение характеристик снаряжения и ограничение требований к станциям. После изменения перезапустите игру.)"); bool saveOnConfigSet = file.SaveOnConfigSet; try { file.SaveOnConfigSet = false; ResistanceGrowth.Initialize(file); ProtectionIdols.Initialize(file); string[] array = new string[5] { "piece_workbench", "forge", "blackforge", "piece_magetable", "piece_artisanstation" }; foreach (string id in array) { Entry(id); } ConfigEntry<bool> val = file.Bind<bool>("Advanced", "WorkbenchCapMigration077", false, new ConfigDescription("Internal migration marker.", (AcceptableValueBase)null, new object[1] { new HiddenSetting() })); if (!val.Value) { ConfigEntry<int> val2 = Entry("piece_workbench"); if (val2.Value == 5) { val2.Value = 4; } val.Value = true; } ConfigEntry<bool> val3 = file.Bind<bool>("Advanced", "BlackForgeCapMigration078", false, new ConfigDescription("Internal migration marker.", (AcceptableValueBase)null, new object[1] { new HiddenSetting() })); if (!val3.Value) { ConfigEntry<int> val4 = Entry("blackforge"); if (val4.Value == 6) { val4.Value = 2; } val3.Value = true; } ConfigEntry<bool> val5 = file.Bind<bool>("Advanced", "GaldrCapMigration079", false, new ConfigDescription("Internal migration marker.", (AcceptableValueBase)null, new object[1] { new HiddenSetting() })); if (!val5.Value) { ConfigEntry<int> val6 = Entry("piece_magetable"); if (val6.Value == 5) { val6.Value = 3; } val5.Value = true; } } finally { file.SaveOnConfigSet = saveOnConfigSet; } if (saveOnConfigSet) { file.Save(); } } private static bool Eligible(Recipe recipe) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)recipe) || !Object.op_Implicit((Object)(object)recipe.m_item) || recipe.m_item.m_itemData == null) { return false; } SharedData shared = recipe.m_item.m_itemData.m_shared; if (shared == null || shared.m_maxStackSize != 1 || shared.m_destroyBroken) { return false; } switch (((object)shared.m_itemType).ToString()) { case "OneHandedWeapon": case "TwoHandedWeapon": case "TwoHandedWeaponLeft": case "Bow": case "Shield": case "Helmet": case "Chest": case "Legs": case "Shoulder": case "Tool": case "Torch": return true; default: return false; } } private static ConfigEntry<int> Entry(CraftingStation station) { if (!Object.op_Implicit((Object)(object)station) || config == null) { return null; } return Entry(((Object)((Component)station).gameObject).name.Replace("(Clone)", "").Trim()); } private static int DefaultCap(string id) { return id switch { "piece_workbench" => 4, "forge" => 7, "blackforge" => 2, "piece_magetable" => 3, "piece_artisanstation" => 2, _ => 0, }; } private static string LegacyLabel(string id) { return id switch { "piece_workbench" => "Верстак", "forge" => "Кузница", "blackforge" => "Чёрная кузница", "piece_magetable" => "Стол гальдра", "piece_artisanstation" => "Стол ремесленника", _ => id, }; } private static string Label(string id) { string text; switch (id) { case "piece_workbench": text = "Workbench"; break; case "forge": text = "Forge"; break; case "blackforge": text = "Black Forge"; break; case "piece_magetable": text = "Galdr Table"; break; case "piece_artisanstation": text = "Artisan Table"; break; default: return id; } return text + " (" + LegacyLabel(id) + ")"; } private static ConfigEntry<int> Entry(string id) { //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown switch (id) { case "piece_cauldron": case "piece_stonecutter": case "piece_preptable": case "piece_MeadCauldron": return null; default: { if (entries.TryGetValue(id, out var value)) { return value; } string text = Label(id).Replace("[", "_").Replace("]", "_").Replace("=", "_") .Replace("\n", "_") .Replace("\r", "_"); int num = DefaultCap(id); string text2 = "Станция: " + LegacyLabel(id).Replace("[", "_").Replace("]", "_").Replace("=", "_") .Replace("\n", "_") .Replace("\r", "_"); ConfigEntry<int> val = config.Bind<int>(text2, "Максимальный уровень станции", num, ""); num = val.Value; if (id == "piece_workbench" && num == 5) { num = 4; } if (id == "blackforge" && num == 6) { num = 2; } if (id == "piece_magetable" && num == 5) { num = 3; } config.Remove(((ConfigEntryBase)val).Definition); value = config.Bind<int>("Station: " + text, "Maximum station level (Максимальный уровень станции)", num, new ConfigDescription("Maximum required station level for equipment upgrades. 0 disables the cap. For example, 6 allows quality 100 equipment upgrades at station level 6. The recipe's base station requirement is preserved. Changes apply immediately.\n(Максимальный требуемый уровень станции для улучшения снаряжения. 0 отключает ограничение. Например, 6 позволяет улучшать предмет до качества 100 на станции уровня 6. Базовое требование рецепта сохраняется. Изменения действуют сразу.)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[0])); entries.Add(id, value); return value; } } } internal static void Discover(ObjectDB db) { AntlerRecipe.Apply(db); if (config == null || !Object.op_Implicit((Object)(object)db) || db.m_recipes == null) { return; } foreach (Recipe recipe in db.m_recipes) { if (Eligible(recipe)) { Entry(recipe.GetRequiredStation(2)); } } } internal static int ClampRequirement(int required, int minimum, int cap) { if (cap <= 0) { return required; } return Math.Min(required, Math.Max(Math.Max(1, minimum), cap)); } } internal static class ResistanceGrowth { private static ConfigEntry<float> fallbackPercent; internal static void Initialize(ConfigFile config) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown ConfigEntry<float> val = config.Bind<float>("Growth", "Запасной прирост сопротивления урону (%)", 10f, ""); float value = val.Value; config.Remove(((ConfigEntryBase)val).Definition); ConfigEntry<float> val2 = config.Bind<float>("Growth", "Fallback block armor growth % (Запасной прирост сопротивления урону, %)", value, ""); value = val2.Value; config.Remove(((ConfigEntryBase)val2).Definition); ConfigEntry<float> val3 = config.Bind<float>("Growth", "Minimum block armor growth % (Минимальный прирост сопротивления урону, %)", value, ""); value = val3.Value; config.Remove(((ConfigEntryBase)val3).Definition); fallbackPercent = config.Bind<float>("Growth", "Block armor growth per upgrade % (Прирост сопротивления урону за улучшение, %)", value, new ConfigDescription("Compound block armor growth per future quality upgrade. 30 means current block armor times 1.30 per level. Existing equipment is anchored at its current quality; prior upgrades are not recalculated. 0 uses linear growth. Skill and battle idol multipliers apply separately. Restart after changes. Each upgrade rounds to the nearest integer.\n(Процентный прирост сопротивления урону при каждом следующем улучшении. 30 означает умножение текущего значения на 1,30 за уровень. Для существующего предмета сохраняется база на его текущем качестве; прежние улучшения не пересчитываются. 0 включает линейный прирост. Навык и идол сражения учитываются отдельно. После изменения перезапустите игру. Каждый шаг округляется до ближайшего целого числа.)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0])); BlockGrowth.Percent = fallbackPercent; BlockGrowth.Enabled = config.Bind<bool>("General", "Enabled", true, ""); } private static bool Finite(float x) { if (!float.IsNaN(x)) { return !float.IsInfinity(x); } return false; } internal static float Compute(float block, float force, float forceStep, float currentStep, float multiplier, float fallback) { if (!Finite(block) || !Finite(force) || !Finite(forceStep) || !Finite(currentStep) || !Finite(multiplier) || !Finite(fallback)) { return currentStep; } if (block <= 0f || force <= 0f || multiplier <= 0f) { return currentStep; } float num = Math.Max(0f, fallback) / 100f; if (currentStep <= 0f && forceStep > 0f) { num = Math.Max(num, forceStep / force); } float num2 = block * num * multiplier; if (!Finite(num2) || !(num2 > 0f)) { return currentStep; } return Math.Max(currentStep, num2); } internal static void Apply(SharedData shared, float multiplier) { if (shared != null && fallbackPercent != null) { shared.m_blockPowerPerLevel = Compute(shared.m_blockPower, shared.m_deflectionForce, shared.m_deflectionForcePerLevel, shared.m_blockPowerPerLevel, multiplier, fallbackPercent.Value); } } } internal static class ProtectionRules { internal const string Key = "local.valheim.ultimateupgrades.protection.v1"; internal static readonly string[] Types = new string[8] { "Pierce", "Slash", "Blunt", "Poison", "Fire", "Frost", "Lightning", "Spirit" }; internal static readonly string[] TypeLabels = new string[8] { "Pierce (Колющий)", "Slash (Рассекающий)", "Blunt (Дробящий)", "Poison (Яд)", "Fire (Огонь)", "Frost (Лёд)", "Lightning (Молния)", "Spirit (Дух)" }; internal static readonly int[][] LegacySlots = new int[8][] { new int[1] { 7 }, new int[2] { 7, 7 }, new int[1] { 1 }, new int[2] { 1, 1 }, new int[3] { 5, 1, 7 }, new int[4] { 5, 5, 7, 7 }, new int[5] { 5, 5, 1, 7, 7 }, new int[3] { 5, 5, 5 } }; internal static readonly int[][] Slots = new int[8][] { new int[1] { 7 }, new int[2] { 7, 7 }, new int[1] { 1 }, new int[2] { 1, 1 }, new int[4] { 1, 1, 7, 7 }, new int[1] { 5 }, new int[3] { 5, 1, 1 }, new int[3] { 5, 5, 5 } }; internal static readonly string[] Names = new string[8] { "Wood (Дерево)", "Bronze (Бронза)", "Iron (Железо)", "Silver (Серебро)", "Black metal (Чёрный металл)", "Black marble (Чёрный мрамор)", "Flametal (Огнеметалл)", "Bloodgold (Кровавое золото)" }; internal static readonly string[] Stations = new string[8] { "piece_workbench", "forge", "forge", "forge", "forge", "blackforge", "blackforge", "blackforge" }; internal static readonly int[] Levels = new int[8] { 3, 3, 5, 6, 7, 1, 4, 6 }; internal static readonly string[][] Materials = new string[8][] { new string[3] { "LeatherScraps:5", "DeerHide:3", "Wood:10" }, new string[4] { "Bronze:5", "Copper:3", "Tin:3", "HardAntler:1" }, new string[5] { "Iron:7", "ElderBark:10", "Ooze:5", "SurtlingCore:1", "CryptKey:1" }, new string[3] { "Silver:20", "Obsidian:15", "DragonTear:1" }, new string[3] { "BlackMetal:30", "Tar:15", "YagluthDrop:1" }, new string[5] { "BlackCore:1", "BlackMarble:80", "Eitr:20", "YggdrasilWood:30", "QueenDrop:1" }, new string[4] { "MoltenCore:3", "FlametalNew:50", "Grausten:100", "FaderDrop:1" }, new string[4] { "Gold:50", "Ice:100", "OrbFrostFire:1", "OrbThunderBlood:1" } }; internal static string Idol(int tier) { return "Upgrader" + tier + "Armor"; } internal static string Degree(int n) { return n switch { 1 => "Resistant (Обычное)", 7 => "Slight (Лёгкое)", _ => "Strong (Сильное)", }; } internal static bool Valid(int tier, int[] choices) { if (tier >= 0 && tier < 8 && choices != null && choices.Length == Slots[tier].Length && choices.All((int x) => x >= 0 && x < Types.Length)) { return choices.Distinct().Count() == choices.Length; } return false; } internal static string Encode(int tier, int[] choices) { if (!Valid(tier, choices)) { throw new ArgumentException("Invalid resistance selection"); } return "2|" + tier + "|" + string.Join(",", choices.Select((int x) => Types[x]).ToArray()); } internal static bool Decode(string text, out int tier, out int[] choices) { int[] degrees; return Decode(text, out tier, out choices, out degrees); } internal static bool Decode(string text, out int tier, out int[] choices, out int[] degrees) { tier = -1; choices = null; degrees = null; if (string.IsNullOrEmpty(text) || text.Length > 160) { return false; } string[] array = text.Split(new char[1] { '|' }); if (array.Length != 3 || (array[0] != "1" && array[0] != "2") || !int.TryParse(array[1], out tier) || tier < 0 || tier >= 8) { return false; } choices = (from x in array[2].Split(new char[1] { ',' }) select Array.IndexOf(Types, x)).ToArray(); int[] array2 = ((array[0] == "1") ? LegacySlots[tier] : Slots[tier]); if (choices.Length != array2.Length || choices.Any((int x) => x < 0 || x >= Types.Length) || choices.Distinct().Count() != choices.Length) { return false; } degrees = (int[])array2.Clone(); return true; } } public enum ProtectionInterface { Vanilla = 1, SeneaLUI } internal static class ProtectionIdols { internal sealed class UpgradeState { internal Inventory Inventory; internal ItemData Original; internal HashSet<ItemData> Before; internal string Stamp; internal string StampKey; internal string GrowthStamp; internal string Prefab; internal int X; internal int Y; internal int Variant; } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] private static class PreserveUpgrade { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(InventoryGui __instance, Player __0, out UpgradeState __state) { __state = CaptureUpgrade(__instance, __0); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(UpgradeState __state) { RestoreUpgrade(__state); } } [HarmonyPatch(typeof(InventoryGui), "Show")] private static class ShowUI { [HarmonyPriority(0)] [HarmonyPostfix] private static void Postfix() { EnsureUI(); Player localPlayer = Player.m_localPlayer; CraftingStation val = (Object.op_Implicit((Object)(object)localPlayer) ? localPlayer.GetCurrentCraftingStation() : null); if (SupportedStation(val)) { Debug.LogWarning((object)("[Valheim Ultimate Upgrades] Protection UI: station=" + ((Object)val).name + ", enabled=" + Active + ", combat=" + CombatReady + ", available=" + AtForge() + ", host=" + Object.op_Implicit((Object)(object)ProtectionIdolUI.Instance))); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class SceneReady { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix() { Recipes(); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class DatabaseReady { [HarmonyPriority(0)] [HarmonyPostfix] private static void Postfix() { Recipes(); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private static class DatabaseCopied { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix() { Recipes(); } } [HarmonyPatch(typeof(Player), "ApplyArmorDamageMods")] private static class ArmorMods { [HarmonyPostfix] private static void Postfix(Player __instance, ref DamageModifiers __0) { if (!Active) { return; } foreach (ItemData equippedItem in ((Humanoid)__instance).GetInventory().GetEquippedItems()) { if (Armor(equippedItem)) { ((DamageModifiers)(ref __0)).Apply(Added(equippedItem)); } } } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] private static class BlockMods { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); FieldInfo fieldInfo = AccessTools.Field(typeof(ItemData), "m_shared"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(SharedData), "m_damageModifiers"); int num = 0; for (int i = 0; i + 1 < list.Count; i++) { if (CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false) && CodeInstructionExtensions.LoadsField(list[i + 1], fieldInfo2, false)) { CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ProtectionIdols), "BlockingModifiers", (Type[])null, (Type[])null)); val.labels.AddRange(list[i].labels); val.labels.AddRange(list[i + 1].labels); val.blocks.AddRange(list[i].blocks); val.blocks.AddRange(list[i + 1].blocks); list[i] = val; list.RemoveAt(i + 1); num++; } } CombatReady = num == 2; if (!CombatReady) { throw new InvalidOperationException("Protection idol block integration: expected 2 field accesses, found " + num); } return list; } } [HarmonyPatch(typeof(ItemData), "AddBlockTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(StringBuilder) })] private static class BlockTooltip { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return Tooltip.Transpiler(instructions); } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) })] private static class Tooltip { [HarmonyTranspiler] internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); FieldInfo fieldInfo = AccessTools.Field(typeof(ItemData), "m_shared"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(SharedData), "m_damageModifiers"); int num = 0; for (int i = 0; i + 1 < list.Count; i++) { if (CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false) && CodeInstructionExtensions.LoadsField(list[i + 1], fieldInfo2, false)) { CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ProtectionIdols), "BlockingModifiers", (Type[])null, (Type[])null)); val.labels.AddRange(list[i].labels); val.labels.AddRange(list[i + 1].labels); val.blocks.AddRange(list[i].blocks); val.blocks.AddRange(list[i + 1].blocks); list[i] = val; list.RemoveAt(i + 1); num++; } } if (num != 1) { throw new InvalidOperationException("Protection idol tooltip integration: expected 1 field access, found " + num); } return list; } [HarmonyPostfix] private static void Postfix(ItemData __0, ref string __result) { if (Bound(__0)) { if (!ProtectionRules.Decode(__0.m_customData["local.valheim.ultimateupgrades.protection.v1"], out var tier, out var _)) { __result += "\n<color=orange>Protection mark unreadable; rebinding blocked. (Метка защиты не прочитана; повторное наложение запрещено.)</color>"; return; } __result = __result + "\n\n<color=orange>Permanent protection (Постоянная защита): " + ProtectionRules.Names[tier] + "</color>"; __result += (Armor(__0) ? "\nWhile worn (Пока надето)" : "\nOnly when this item blocks (Только при блокировании этим предметом)"); } } } [HarmonyPatch(typeof(Player), "TakeInput")] private static class InputGuard { [HarmonyPrefix] private static bool Prefix(ref bool __result) { if (!ProtectionIdolUI.Open) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] private static class CraftGuard { [HarmonyPrefix] private static bool Prefix() { return !ProtectionIdolUI.Open; } } internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<ProtectionInterface> Interface; internal static bool CombatReady; private static bool committing; private static readonly HashSet<string> warned = new HashSet<string>(); private static readonly FieldInfo CraftTimer = AccessTools.Field(typeof(InventoryGui), "m_craftTimer"); internal static bool Active { get { if (Enabled != null) { return Enabled.Value; } return false; } } internal static void Initialize(ConfigFile config) { Enabled = config.Bind<bool>("Protection idols (Идолы защиты)", "Enabled (Включено)", true, "Enable permanent protection and battle idol effects, and recipes for all eight protection and eight battle idols. All players must use this mod for consistent effects. Restart after changes.\n(Включает постоянные эффекты идолов защиты и сражения, а также рецепты восьми идолов защиты и восьми идолов сражения. Для одинакового действия эффектов мод нужен всем игрокам. После изменения перезапустите игру.)"); Interface = config.Bind<ProtectionInterface>("Protection idols (Идолы защиты)", "Interface (Интерфейс)", ProtectionInterface.SeneaLUI, "Choose the idol interface: 1 — Vanilla, 2 — SeneaL UI. Changes apply immediately and close the protection window. This setting does not enable or disable other UI mods.\n(Выберите интерфейс идолов: 1 — ванильная игра, 2 — SeneaL UI. Изменение действует сразу и закрывает окно защиты. Эта настройка не включает и не отключает другие моды интерфейса.)"); L10n.Words(); L10n.PatchSettings(); EnsureUI(); } internal static void EnsureUI() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!Application.isBatchMode && !Object.op_Implicit((Object)(object)ProtectionIdolUI.Instance)) { GameObject val = new GameObject("VUU Protection Idols"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<ProtectionIdolUI>(); } } internal static bool SupportedStation(CraftingStation station) { if (!Object.op_Implicit((Object)(object)station)) { return false; } switch ((((Object)station).name ?? "").Replace("(Clone)", "").Trim()) { default: return IdolFusion.Station(station); case "piece_workbench": case "forge": case "blackforge": return true; } } internal static string StationRequirement(int tier) { object obj; switch (tier) { default: return "Invalid idol (Неизвестный идол)"; case 5: case 6: case 7: obj = "Black forge (Чёрная кузница)"; break; case 1: case 2: case 3: case 4: obj = "Forge (Кузница)"; break; case 0: obj = "Workbench (Верстак)"; break; } string text = (string)obj; return text + " · Level (Уровень) " + ProtectionRules.Levels[tier]; } internal static bool CanUseIdol(CraftingStation station, int tier) { if (!Object.op_Implicit((Object)(object)station) || tier < 0 || tier >= 8) { return false; } string text = (((Object)station).name ?? "").Replace("(Clone)", "").Trim(); if (text == ProtectionRules.Stations[tier]) { return station.GetLevel(true) >= ProtectionRules.Levels[tier]; } return false; } internal static int[] VisibleTiers(CraftingStation station) { return (from x in Enumerable.Range(0, 8) where CanUseIdol(station, x) select x).ToArray(); } internal static bool Armor(ItemData item) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (item == null || item.m_shared == null) { return false; } string text = ((object)item.m_shared.m_itemType).ToString(); switch (text) { default: return text == "Shoulder"; case "Helmet": case "Chest": case "Legs": return true; } } internal static bool Eligible(ItemData item) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (item == null || item.m_shared == null || item.m_stack != 1 || item.m_shared.m_maxStackSize != 1 || item.m_shared.m_destroyBroken) { return false; } if (Armor(item)) { return true; } string text = ((object)item.m_shared.m_itemType).ToString(); switch (text) { default: return text == "Shield"; case "OneHandedWeapon": case "TwoHandedWeapon": case "TwoHandedWeaponLeft": case "Bow": return true; } } internal static bool Bound(ItemData item) { if (item != null && item.m_customData != null) { return item.m_customData.ContainsKey("local.valheim.ultimateupgrades.protection.v1"); } return false; } internal static bool AnyBound(ItemData item) { if (!Bound(item)) { return BattleIdols.Bound(item); } return true; } internal static string Prefab(ItemData item) { if (item == null || !Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return ""; } return ((Object)item.m_dropPrefab).name; } internal static bool AtForge() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Active || !CombatReady || !Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || !InventoryGui.IsVisible()) { return false; } CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); if (SupportedStation(currentCraftingStation)) { return Vector3.Distance(((Component)localPlayer).transform.position, ((Component)currentCraftingStation).transform.position) <= currentCraftingStation.m_useDistance + 1f; } return false; } internal static bool Busy() { InventoryGui instance = InventoryGui.instance; if (Object.op_Implicit((Object)(object)instance) && CraftTimer != null) { return (float)CraftTimer.GetValue(instance) >= 0f; } return false; } internal static List<DamageModPair> Added(ItemData item) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) List<DamageModPair> list = new List<DamageModPair>(); if (!Active || !Eligible(item) || !Bound(item)) { return list; } if (!ProtectionRules.Decode(item.m_customData["local.valheim.ultimateupgrades.protection.v1"], out var _, out var choices, out var degrees)) { return list; } for (int i = 0; i < choices.Length; i++) { list.Add(new DamageModPair { m_type = (DamageType)Enum.Parse(typeof(DamageType), ProtectionRules.Types[choices[i]]), m_modifier = (DamageModifier)degrees[i] }); } return list.Where((DamageModPair x) => Rank(x.m_modifier) > Rank(Existing(item, x.m_type))).ToList(); } internal static int Rank(DamageModifier value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Expected I4, but got Unknown return (int)value switch { 6 => -3, 2 => -2, 8 => -1, 0 => 0, 7 => 1, 1 => 2, 5 => 3, 3 => 4, 4 => 5, _ => int.MaxValue, }; } internal static DamageModifier Existing(ItemData item, DamageType type) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) List<DamageModPair> list = item.m_shared.m_damageModifiers.Where((DamageModPair x) => x.m_type == type).ToList(); if (list.Count != 0) { return list.OrderByDescending((DamageModPair x) => Rank(x.m_modifier)).First().m_modifier; } return (DamageModifier)0; } internal static bool Improves(ItemData item, int tier, int[] choices) { //IL_0027: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!ProtectionRules.Valid(tier, choices)) { return false; } for (int i = 0; i < choices.Length; i++) { DamageType type = (DamageType)Enum.Parse(typeof(DamageType), ProtectionRules.Types[choices[i]]); if (Rank((DamageModifier)ProtectionRules.Slots[tier][i]) <= Rank(Existing(item, type))) { return false; } } return true; } public static List<DamageModPair> BlockingModifiers(ItemData item) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) List<DamageModPair> damageModifiers = item.m_shared.m_damageModifiers; if (!Active || !Bound(item)) { return damageModifiers; } List<DamageModPair> list = new List<DamageModPair>(); foreach (DamageModPair pair in damageModifiers.Concat(Added(item))) { Predicate<DamageModPair> match = (DamageModPair x) => x.m_type == pair.m_type; int num = list.FindIndex(match); if (num < 0) { list.Add(pair); } else if (Rank(pair.m_modifier) > Rank(list[num].m_modifier)) { list[num] = pair; } } return list; } internal static bool Apply(ItemData target, int tier, int[] choices, out string error, bool blood = false) { error = ""; if (committing) { error = "Please wait (Подождите)"; return false; } if (!AtForge() || Busy()) { error = "Open a workbench, forge or black forge and stop crafting. (Откройте верстак, кузницу или Чёрную кузницу и завершите изготовление.)"; return false; } Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (!Eligible(target) || target.m_quality < 4 || !inventory.GetAllItems().Contains(target) || AnyBound(target) || !ProtectionRules.Valid(tier, choices)) { error = "Item or selection is no longer valid. (Предмет или выбор больше не подходит.)"; return false; } if (!Improves(target, tier, choices)) { error = "Choose stronger resistance or another damage type. (Выберите более сильное сопротивление или другой тип урона.)"; return false; } if (!CanUseIdol(Player.m_localPlayer.GetCurrentCraftingStation(), tier)) { error = "Requires (Требуется): " + StationRequirement(tier); return false; } ItemData val = ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => Prefab(x) == IdolChance.Id(ProtectionRules.Idol(tier), blood) && x.m_stack > 0)); if (val == null) { error = "The selected protection idol is missing. (Выбранного идола защиты нет.)"; return false; } string stamp = ProtectionRules.Encode(tier, choices); committing = true; try { return IdolChance.Attempt(Player.m_localPlayer, target, val, "local.valheim.ultimateupgrades.protection.v1", stamp, out error); } finally { committing = false; } } internal static void Recipes() { //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown if (!Active || !Object.op_Implicit((Object)(object)ObjectDB.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } ObjectDB instance = ObjectDB.instance; for (int i = 0; i < 8; i++) { for (int j = 0; j < 2; j++) { string text = ((j == 0) ? ProtectionRules.Idol(i) : BattleIdols.Idol(i)); GameObject itemPrefab = instance.GetItemPrefab(text); if (!Object.op_Implicit((Object)(object)itemPrefab)) { continue; } ItemDrop originalIdol = itemPrefab.GetComponent<ItemDrop>(); GameObject val = IdolChance.Register(itemPrefab); ItemDrop idol = val.GetComponent<ItemDrop>(); GameObject prefab = ZNetScene.instance.GetPrefab(ProtectionRules.Stations[i]); if (!Object.op_Implicit((Object)(object)idol) || !Object.op_Implicit((Object)(object)prefab)) { continue; } CraftingStation component = prefab.GetComponent<CraftingStation>(); if (!Object.op_Implicit((Object)(object)component)) { continue; } List<Requirement> list = new List<Requirement>(); bool flag = true; string[] array = ProtectionRules.Materials[i]; foreach (string text2 in array) { string[] array2 = text2.Split(new char[1] { ':' }); GameObject itemPrefab2 = instance.GetItemPrefab(array2[0]); if (!Object.op_Implicit((Object)(object)itemPrefab2) || !Object.op_Implicit((Object)(object)itemPrefab2.GetComponent<ItemDrop>())) { flag = false; if (warned.Add(array2[0])) { Debug.LogWarning((object)("[Valheim Ultimate Upgrades] Missing idol ingredient: " + array2[0])); } break; } Requirement val2 = new Requirement(); val2.m_resItem = itemPrefab2.GetComponent<ItemDrop>(); val2.m_amount = int.Parse(array2[1]); val2.m_amountPerLevel = 0; val2.m_recover = true; list.Add(val2); } List<Recipe> list2 = instance.m_recipes.Where((Recipe r) => Object.op_Implicit((Object)(object)r) && ((Object)(object)r.m_item == (Object)(object)idol || (Object)(object)r.m_item == (Object)(object)originalIdol)).ToList(); if (!flag) { foreach (Recipe item in list2) { item.m_enabled = false; } continue; } if (list2.Count == 0) { Recipe val3 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val3).name = "VUU_" + text; val3.m_item = idol; instance.m_recipes.Add(val3); list2.Add(val3); } foreach (Recipe item2 in list2) { item2.m_item = idol; item2.m_enabled = true; item2.m_amount = 1; item2.m_qualityResultAmountMultiplier = 0f; item2.m_noCraftOnlyUpgrade = false; item2.m_requireOnlyOneIngredient = false; item2.m_craftingStation = component; item2.m_minStationLevel = ProtectionRules.Levels[i]; item2.m_resources = list.ToArray(); } } } } internal static UpgradeState CaptureUpgrade(InventoryGui gui, Player player) { if (!Object.op_Implicit((Object)(object)gui) || !Object.op_Implicit((Object)(object)player)) { return null; } FieldInfo fieldInfo = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem"); ItemData val = (ItemData)((fieldInfo == null) ? null : /*isinst with value type is only supported in some contexts*/); if (val == null) { return null; } BlockGrowth.Value(val, val.m_quality, BlockGrowth.Native(val, val.m_quality)); string value; bool flag = val.m_customData != null && val.m_customData.TryGetValue("local.valheim.ultimateupgrades.blockgrowth.v1", out value); if (!AnyBound(val) && !flag) { return null; } Inventory inventory = ((Humanoid)player).GetInventory(); if (!inventory.GetAllItems().Contains(val)) { return null; } UpgradeState upgradeState = new UpgradeState(); upgradeState.Inventory = inventory; upgradeState.Original = val; upgradeState.Before = new HashSet<ItemData>(inventory.GetAllItems()); upgradeState.StampKey = ((!AnyBound(val)) ? null : (Bound(val) ? "local.valheim.ultimateupgrades.protection.v1" : "local.valheim.ultimateupgrades.battle.v1")); upgradeState.Stamp = (AnyBound(val) ? val.m_customData[Bound(val) ? "local.valheim.ultimateupgrades.protection.v1" : "local.valheim.ultimateupgrades.battle.v1"] : null); upgradeState.GrowthStamp = (flag ? val.m_customData["local.valheim.ultimateupgrades.blockgrowth.v1"] : null); upgradeState.Prefab = Prefab(val); upgradeState.X = val.m_gridPos.x; upgradeState.Y = val.m_gridPos.y; upgradeState.Variant = val.m_variant; return upgradeState; } internal static void RestoreUpgrade(UpgradeState state) { if (state == null) { return; } List<ItemData> allItems = state.Inventory.GetAllItems(); ItemData val = null; if (allItems.Contains(state.Original)) { val = state.Original; } else { List<ItemData> list = allItems.Where((ItemData x) => !state.Before.Contains(x) && Prefab(x) == state.Prefab && x.m_gridPos.x == state.X && x.m_gridPos.y == state.Y && x.m_variant == state.Variant && x.m_stack == 1).ToList(); if (list.Count == 1) { val = list[0]; } } if (val != null) { if (val.m_customData == null) { val.m_customData = new Dictionary<string, string>(); } if (state.StampKey != null && !val.m_customData.ContainsKey(state.StampKey)) { val.m_customData[state.StampKey] = state.Stamp; } if (state.GrowthStamp != null) { val.m_customData["local.valheim.ultimateupgrades.blockgrowth.v1"] = state.GrowthStamp; } MethodInfo methodInfo = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(state.Inventory, new object[2] { false, false }); } } } } public class ProtectionIdolUI : MonoBehaviour { public static bool Open; internal static ProtectionIdolUI Instance; private GameObject canvas; private GameObject modal; private GameObject launch; private GameObject underline; private GameObject damagePicker; private ScrollRect pickerParentScroll; private bool pickerScrollWasEnabled; private RectTransform stationTabRoot; private RectTransform vanillaRoot; private ProtectionInterface currentInterface; private TMP_FontAsset uiFont; private ItemData selected; private int tier; private int filter; private int[] choices; private bool confirm; private bool battle; private bool blood; private readonly List<CanvasGroup> hiddenUnderlines; private float nextRecipes; private float nextStationButton; private float nextInterfaceProbe; private ProtectionInterface detectedInterface; private string languageRussian; private string message; private string query; private string stationState; private Transform panel; private Transform listContent; private Transform details; private readonly Color gold; private readonly Color ink; private readonly Color muted; private bool fusionHelp; private void Awake() { Instance = this; languageRussian = L10n.Language; L10n.Words(); } private void Update() { //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_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime >= nextInterfaceProbe) { nextInterfaceProbe = Time.unscaledTime + 1f; L10n.PatchSettings(); detectedInterface = ((ProtectionIdols.Interface == null) ? ProtectionInterface.SeneaLUI : ProtectionIdols.Interface.Value); if (detectedInterface == ProtectionInterface.SeneaLUI && InventoryGui.IsVisible() && !Object.op_Implicit((Object)(object)FindActiveSeneaPanel())) { detectedInterface = ProtectionInterface.Vanilla; } } if (languageRussian != L10n.Language) { languageRussian = L10n.Language; L10n.Words(); if (Object.op_Implicit((Object)(object)launch)) { FitTabLabel(); } if (Open) { Render(); } } ProtectionInterface protectionInterface = detectedInterface; if (protectionInterface != currentInterface) { Close(); if (Object.op_Implicit((Object)(object)modal)) { Object.Destroy((Object)(object)modal); modal = null; panel = null; details = null; listContent = null; } if (Object.op_Implicit((Object)(object)launch)) { Object.Destroy((Object)(object)launch); launch = null; } stationTabRoot = null; vanillaRoot = null; underline = null; uiFont = TMP_Settings.defaultFontAsset; currentInterface = protectionInterface; nextStationButton = 0f; } if (Time.unscaledTime >= nextRecipes) { nextRecipes = Time.unscaledTime + 10f; ProtectionIdols.Recipes(); } bool flag = ProtectionIdols.AtForge(); if (!flag && Open) { Close(); } if (!Object.op_Implicit((Object)(object)canvas) && flag) { Build(); } if (flag && Time.unscaledTime >= nextStationButton) { nextStationButton = Time.unscaledTime + 1f; AttachStationButton(); CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation(); string text = ((Object)currentCraftingStation).name + ":" + currentCraftingStation.GetLevel(true); if (text != stationState) { stationState = text; if (Open) { confirm = false; Render(); } } } if (Object.op_Implicit((Object)(object)launch)) { launch.SetActive(flag); } if (flag && Input.GetKeyDown((KeyCode)289)) { if (Open) { Close(); } else { OpenWindow(); } } if (Open && Input.GetKeyDown((KeyCode)27)) { if (Object.op_Implicit((Object)(object)damagePicker)) { CloseDamagePicker(); } else { Close(); } } if (Open && Object.op_Implicit((Object)(object)vanillaRoot) && Object.op_Implicit((Object)(object)modal) && Input.GetMouseButtonDown(0) && RectTransformUtility.RectangleContainsScreenPoint(vanillaRoot, Vector2.op_Implicit(Input.mousePosition), CameraFor((Transform)(object)vanillaRoot)) && !RectTransformUtility.RectangleContainsScreenPoint(modal.GetComponent<RectTransform>(), Vector2.op_Implicit(Input.mousePosition), CameraFor((Transform)(object)vanillaRoot)) && (!Object.op_Implicit((Object)(object)launch) || !RectTransformUtility.RectangleContainsScreenPoint(launch.GetComponent<RectTransform>(), Vector2.op_Implicit(Input.mousePosition), CameraFor((Transform)(object)vanillaRoot)))) { Close(); } if (!Open || !Object.op_Implicit((Object)(object)stationTabRoot) || !Input.GetMouseButtonDown(0)) { return; } for (int i = 0; i < 8; i++) { Transform obj = ((Transform)stationTabRoot).Find("tab" + i); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(val, Vector2.op_Implicit(Input.mousePosition), CameraFor((Transform)(object)val))) { Close(); break; } } } private Camera CameraFor(Transform t) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)t).GetComponentInParent<Canvas>(); if (!Object.op_Implicit((Object)(object)componentInParent) || (int)componentInParent.renderMode == 0) { return null; } return componentInParent.worldCamera; } private void LateUpdate() { if (!Open || !Object.op_Implicit((Object)(object)modal)) { return; } if (Object.op_Implicit((Object)(object)vanillaRoot) && !((Component)vanillaRoot).gameObject.activeInHierarchy) { Close(); return; } if (Object.op_Implicit((Object)(object)stationTabRoot) && !((Component)stationTabRoot).gameObject.activeInHierarchy) { Close(); return; } modal.transform.SetAsLastSibling(); if (Object.op_Implicit((Object)(object)launch)) { launch.transform.SetAsLastSibling(); } if (Object.op_Implicit((Object)(object)stationTabRoot)) { for (int i = 0; i < 8; i++) { Transform val = ((Transform)stationTabRoot).Find("tab" + i + "/u"); if (Object.op_Implicit((Object)(object)val)) { CanvasGroup val2 = ((Component)val).GetComponent<CanvasGroup>(); if (!Object.op_Implicit((Object)(object)val2)) { val2 = ((Component)val).gameObject.AddComponent<CanvasGroup>(); hiddenUnderlines.Add(val2); } if (hiddenUnderlines.Contains(val2)) { val2.alpha = 0f; } } } } Fit(); } private void OnDestroy() { Close(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } Open = false; if (Object.op_Implicit((Object)(object)launch)) { Object.Destroy((Object)(object)launch); } if (Object.op_Implicit((Object)(object)modal)) { Object.Destroy((Object)(object)modal); } if (Object.op_Implicit((Object)(object)canvas)) { Object.Destroy((Object)(object)canvas); } } private void Build() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown canvas = new GameObject("VUU Protection UI", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); Object.DontDestroyOnLoad((Object)(object)canvas); Canvas component = canvas.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 32760; CanvasScaler component2 = canvas.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); uiFont = TMP_Settings.defaultFontAsset; launch = ((Component)Button(canvas.transform, "Protection (Защита) [F8]", new Rect(720f, 25f, 480f, 45f), new UnityAction(OpenWindow))).gameObject; AttachStationButton(); } private RectTransform FindActiveSeneaPanel() { RectTransform[] array = Resources.FindObjectsOfTypeAll<RectTransform>(); foreach (RectTransform val in array) { if (((Object)val).name.Length == 4 && ((Object)val).name.StartsWith("tab", StringComparison.Ordinal) && ((Object)val).name[3] >= '0' && ((Object)val).name[3] <= '7' && ((Component)val).gameObject.activeInHierarchy && Object.op_Implicit((Object)(object)((Transform)val).parent) && Object.op_Implicit((Object)(object)((Transform)val).parent.Find("tab0")) && Object.op_Implicit((Object)(object)((Transform)val).parent.Find("tab1")) && Object.op_Implicit((Object)(object)((Transform)val).parent.Find("tabline"))) { Transform parent = ((Transform)val).parent; return (RectTransform)(object)((parent is RectTransform) ? parent : null); } } return null; } private void AttachStationButton() { //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Expected O, but got Unknown //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)canvas)) { return; } if (currentInterface == ProtectionInterface.Vanilla) { AttachVanillaButton(); return; } if (Object.op_Implicit((Object)(object)stationTabRoot) && !((Component)stationTabRoot).gameObject.activeInHierarchy) { stationTabRoot = null; } if (!Object.op_Implicit((Object)(object)stationTabRoot)) { RectTransform[] array = Resources.FindObjectsOfTypeAll<RectTransform>(); foreach (RectTransform val in array) { if (((Object)val).name.Length == 4 && ((Object)val).name.StartsWith("tab", StringComparison.Ordinal) && ((Object)val).name[3] >= '0' && ((Object)val).name[3] <= '7' && ((Component)val).gameObject.activeInHierarchy && Object.op_Implicit((Object)(object)((Transform)val).parent) && Object.op_Implicit((Object)(object)((Transform)val).parent.Find("tab0")) && Object.op_Implicit((Object)(object)((Transform)val).parent.Find("tab1")) && Object.op_Implicit((Object)(object)((Transform)val).parent.Find("tabline"))) { ref RectTransform reference = ref stationTabRoot; Transform parent = ((Transform)val).parent; reference = (RectTransform)(object)((parent is RectTransform) ? parent : null); TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { uiFont = ((TMP_Text)componentInChildren).font; } break; } } } if (!Object.op_Implicit((Object)(object)stationTabRoot)) { if (!Object.op_Implicit((Object)(object)launch)) { launch = ((Component)Button(canvas.transform, "Protection (Защита) [F8]", new Rect(720f, 25f, 480f, 45f), new UnityAction(OpenWindow))).gameObject; } return; } if (!Object.op_Implicit((Object)(object)launch) || (Object)(object)launch.transform.parent != (Object)(object)stationTabRoot) { if (Object.op_Implicit((Object)(object)launch)) { Object.Destroy((Object)(object)launch); } launch = ((Component)Button((Transform)(object)stationTabRoot, "IDOLS\n(ИДОЛЫ)", new Rect(0f, 0f, 150f, 36f), new UnityAction(OpenWindow))).gameObject; ((Object)launch).name = "VUU_ProtectionTab"; FitTabLabel(); ((Graphic)launch.GetComponent<Image>()).color = Color.clear; underline = Box(launch.transform, new Rect(0f, 35f, 150f, 2f), gold); ((Graphic)underline.GetComponent<Image>()).raycastTarget = false; underline.SetActive(Open); } float num = 0f; float num2 = 0f; for (int j = 0; j < 8; j++) { Transform obj = ((Transform)stationTabRoot).Find("tab" + j); RectTransform val2 = (RectTransform)(object)((obj is RectTransform) ? obj : null); if (Object.op_Implicit((Object)(object)val2) && ((Component)val2).gameObject.activeSelf) { float num3 = num; float x = val2.anchoredPosition.x; Rect rect = val2.rect; num = Mathf.Max(num3, x + ((Rect)(ref rect)).width); num2 = 0f - val2.anchoredPosition.y; } } Position(launch, new Rect(num + 8f, num2, 150f, 36f)); } private void FitTabLabel() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI componentInChildren = launch.GetComponentInChildren<TextMeshProUGUI>(); ((TMP_Text)componentInChildren).text = L10n.Text(L10n.Choose("IDOLS", "ИДОЛЫ")); ((TMP_Text)componentInChildren).enableAutoSizing = true; ((TMP_Text)componentInChildren).fontSizeMin = 8f; ((TMP_Text)componentInChildren).fontSizeMax = 15f; ((TMP_Text)componentInChildren).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)componentInChildren).overflowMode = (TextOverflowModes)0; ((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)514; ((TMP_Text)componentInChildren).margin = Vector4.zero; ((TMP_Text)componentInChildren).lineSpacing = 0f; ((TMP_Text)componentInChildren).paragraphSpacing = 0f; ((TMP_Text)componentInChildren).characterSpacing = 0f; RectTransform rectTransform = ((TMP_Text)componentInChildren).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = new Vector2(3f, 1f); rectTransform.offsetMax = new Vector2(-3f, -1f); } private void AttachVanillaButton() { //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } object? value = AccessTools.Field(typeof(InventoryGui), "m_crafting").GetValue(instance); RectTransform val = (RectTransform)((value is RectTransform) ? value : null); object? value2 = AccessTools.Field(typeof(InventoryGui), "m_tabUpgrade").GetValue(instance); Button val2 = (Button)((value2 is Button) ? value2 : null); vanillaRoot = ((Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy) ? val : null); Transform val3 = (Transform)(Object.op_Implicit((Object)(object)vanillaRoot) ? ((object)vanillaRoot) : ((object)canvas.transform)); if (Object.op_Implicit((Object)(object)launch) && (Object)(object)launch.transform.parent == (Object)(object)val3) { PositionVanillaTab(val2); launch.transform.SetAsLastSibling(); return; } if (Object.op_Implicit((Object)(object)launch)) { Object.Destroy((Object)(object)launch); } if (Object.op_Implicit((Object)(object)val2)) { TMP_Text componentInChildren = ((Component)val2).GetComponentInChildren<TMP_Text>(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { uiFont = componentInChildren.font; } } launch = ((Component)Button(val3, "IDOLS\n(ИДОЛЫ)", new Rect(0f, 0f, 180f, 42f), new UnityAction(OpenWindow))).gameObject; ((Object)launch).name = "VUU_VanillaProtection"; FitTabLabel(); if (Object.op_Implicit((Object)(object)val2)) { Graphic targetGraphic = ((Selectable)val2).targetGraphic; Image val4 = (Image)(object)((targetGraphic is Image) ? targetGraphic : null); Image component = launch.GetComponent<Image>(); if (Object.op_Implicit((Object)(object)val4)) { component.sprite = val4.sprite; component.type = val4.type; ((Graphic)component).color = ((Graphic)val4).color; } ((Selectable)launch.GetComponent<Button>()).colors = ((Selectable)val2).colors; } RectTransform component2 = launch.GetComponent<RectTransform>(); Vector2 anchorMin = (component2.anchorMax = new Vector2(1f, 1f)); component2.anchorMin = anchorMin; component2.pivot = new Vector2(1f, 1f); component2.anchoredPosition = (((Object)(object)val3 == (Object)(object)val) ? new Vector2(-12f, -70f) : new Vector2(-30f, -25f)); PositionVanillaTab(val2); launch.transform.SetAsLastSibling(); } private void PositionVanillaTab(Button source) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)vanillaRoot) && Object.op_Implicit((Object)(object)source) && Object.op_Implicit((Object)(object)launch)) { Vector3[] array = (Vector3[])(object)new Vector3[4]; ((Component)source).GetComponent<RectTransform>().GetWorldCorners(array); Vector3 val = ((Transform)vanillaRoot).InverseTransformPoint(array[1]); RectTransform component = launch.GetComponent<RectTransform>(); float y = val.y; Rect rect = vanillaRoot.rect; component.anchoredPosition = new Vector2(-12f, y - ((Rect)(ref rect)).yMax); Rect rect2 = ((Component)source).GetComponent<RectTransform>().rect; component.sizeDelta = new Vector2(180f, Mathf.Max(42f, ((Rect)(ref rect2)).height)); } } private void OpenWindow() { if (ProtectionIdols.AtForge() && !ProtectionIdols.Busy()) { if (!Object.op_Implicit((Object)(object)canvas)) { Build(); } AttachStationButton(); Open = true; confirm = false; message = ""; query = ""; filter = 0; List<ItemData> allItems = ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems(); selected = ((IEnumerable<ItemData>)allItems).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => ProtectionIdols.Eligible(x) && x.m_quality >= 4 && !ProtectionIdols.AnyBound(x))); tier = Enumerable.Range(0, 8).FirstOrDefault((int x) => Count(x) > 0 && ProtectionIdols.CanUseIdol(Player.m_localPlayer.GetCurrentCraftingStation(), x)); int[] array; if (!battle) { array = Enumerable.Range(0, ProtectionRules.Slots[tier].Length).ToArray(); } else { int[] array2 = new int[1]; array = array2; } choices = array; Render(); } } private void Close() { CloseDamagePicker(); foreach (CanvasGroup hiddenUnderline in hiddenUnderlines) { if (Object.op_Implicit((Object)(object)hiddenUnderline)) { hiddenUnderline.alpha = 1f; Object.Destroy((Object)(object)hiddenUnderline); } } hiddenUnderlines.Clear(); Open = false; confirm = false; if (Object.op_Implicit((Object)(object)modal)) { modal.SetActive(false); } if (Object.op_Implicit((Object)(object)underline)) { underline.SetActive(false); } } private GameObject Box(Transform parent, Rect r, Color color) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Panel", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(parent, false); Position(val, r); ((Graphic)val.GetComponent<Image>()).color = color; return val; } private void Position(GameObject go, Rect r) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent<RectTransform>(); Vector2 anchorMin = (component.anchorMax = new Vector2(0f, 1f)); component.anchorMin = anchorMin; component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(((Rect)(ref r)).x, 0f - ((Rect)(ref r)).y); component.sizeDelta = new Vector2(((Rect)(ref r)).width, ((Rect)(ref r)).height); } private TextMeshProUGUI Text(Transform parent, string value, Rect r, float size) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Text", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val.transform.SetParent(parent, false); Position(val, r); TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).font = uiFont; ((TMP_Text)component).fontSize = size * ((currentInterface == ProtectionInterface.Vanilla && Object.op_Implicit((Object)(object)details) && parent.IsChildOf(details)) ? 1.55f : 1f); ((Graphic)component).color = gold; ((TMP_Text)component).text = L10n.Text(value); ((TMP_Text)component).richText = false; ((Graphic)component).raycastTarget = false; ((TMP_Text)component).overflowMode = (TextOverflowModes)(currentInterface != ProtectionInterface.Vanilla); if (currentInterface == ProtectionInterface.Vanilla) { ((TMP_Text)component).textWrappingMode = (TextWrappingModes)1; } if (currentInterface == ProtectionInterface.Vanilla) { Button val2 = NativeSource(action: false); TMP_Text val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponentInChildren<TMP_Text>(true) : null); if (Object.op_Implicit((Object)(object)val3)) { ((TMP_Text)component).font = val3.font; ((TMP_Text)component).fontSharedMaterial = val3.fontSharedMaterial; ((Graphic)component).color = ((Graphic)val3).color; } } return component; } private Button Button(Transform parent, string label, Rect r, UnityAction action) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) GameObject val = Box(parent, r, new Color(0.18f, 0.15f, 0.1f, 1f)); if (currentInterface != ProtectionInterface.Vanilla) { IdolSkin.Frame(val, new Color(0.46f, 0.37f, 0.2f, 1f)); } Button val2 = val.AddComponent<Button>(); ((Selectable)val2).targetGraphic = (Graphic)(object)val.GetComponent<Image>(); ColorBlock colors = ((Selectable)val2).colors; ((ColorBlock)(ref colors)).highlightedColor = new Color(1.3f, 1.2f, 0.9f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.8f, 0.7f, 0.5f, 1f); ((ColorBlock)(ref colors)).disabledColor = new Color(0.5f, 0.5f, 0.5f, 0.65f); ((Selectable)val2).colors = colors; ((UnityEvent)val2.onClick).AddListener(action); TextMeshProUGUI val3 = Text(val.transform, label, new Rect(6f, 2f, ((Rect)(ref r)).width - 12f, ((Rect)(ref r)).height - 4f), (((Rect)(ref r)).height < 40f) ? 15 : 18); ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; if (currentInterface == ProtectionInterface.Vanilla) { NativeButton(val2, action: false); } return val2; } private void Icon(Transform parent, ItemData item, Rect r) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) GameObject val = Box(parent, r, new Color(0.1f, 0.085f, 0.06f, 1f)); if (currentInterface != ProtectionInterface.Vanilla) { IdolSkin.Frame(val, new Color(0.46f, 0.37f, 0.2f, 1f)); } if (item != null) { Image component = Box(val.transform, new Rect(4f, 4f, ((Rect)(ref r)).width - 8f, ((Rect)(ref r)).height - 8f), Color.white).GetComponent<Image>(); component.sprite = item.GetIcon(); component.preserveAspect = true; ((Graphic)component).raycastTarget = false; } } private string CurrentIdol(int n) { return IdolChance.Id(battle ? BattleIdols.Idol(n) : ProtectionRules.Idol(n), blood); } private void SetBattle(bool value) { battle = value; confirm = false; message = ""; int[] array; if (!battle) { array = Enumerable.Range(0, ProtectionRules.Slots[tier].Length).ToArray(); } else { int[] array2 = new int[1]; array = array2; } choices = array; Render(); } private ItemData IdolDisplay(int n) { ObjectDB instance = ObjectDB.instance; GameObject val = (Object.op_Implicit((Object)(object)instance) ? instance.GetItemPrefab(CurrentIdol(n)) : null); ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null); if (Object.op_Implicit((Object)(object)val2)) { return val2.m_itemData; } return ((IEnumerable<ItemData>)((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => ProtectionIdols.Prefab(x) == CurrentIdol(n))); } private int Count(int n) { return (from x in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems() where ProtectionIdols.Prefab(x) == CurrentIdol(n) select x).Sum((ItemData x) => x.m_stack); } private string ItemName(ItemData item) { return L10n.Text(Localization.instance.Localize(item.m_shared.m_name)); } private string Local(string token) { return Localization.instance.Localize(token); } private string Damage(int n) { if (battle) { return Local(BattleIdols.Tokens[n]); } return Local("$inventory_" + ProtectionRules.Types[n].ToLowerInvariant()); } private string Degree(int n) { return Local(n switch { 5 => "$inventory_veryresistant", 1 => "$inventory_resistant", 7 => "$inventory_slightlyresistant", _ => "$inventory_normal", }); } private void Fit() { //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)modal) || !Object.op_Implicit((Object)(object)panel)) { return; } RectTransform component = modal.GetComponent<RectTransform>(); if (currentInterface == ProtectionInterface.Vanilla && ((Object)modal).name != "VUU_IdolFusion") { Rect rect = component.rect; float num = Mathf.Max(0.1f, ((Rect)(ref rect)).width / 940f); Rect rect2 = component.rect; float num2 = ((Rect)(ref rect2)).height / num; panel.localScale = Vector3.one * num; ((Component)panel).GetComponent<RectTransform>().sizeDelta = new Vector2(940f, num2); string[] array = new string[2] { "VanillaSidebar", "VanillaMain" }; foreach (string text in array) { Transform obj = panel.Find(text); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if (Object.op_Implicit((Object)(object)val)) { val.sizeDelta = new Vector2(val.sizeDelta.x, num2); } } Transform obj2 = panel.Find("VanillaClose"); RectTransform val2 = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null); if (Object.op_Implicit((Object)(object)val2)) { val2.anchoredPosition = new Vector2(8f, 0f - Mathf.Max(0f, num2 - 65f)); } Transform obj3 = panel.Find("VanillaDetailsViewport"); RectTransform val3 = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null); if (Object.op_Implicit((Object)(object)val3)) { val3.sizeDelta = new Vector2(695f, Mathf.Max(1f, num2 - 214f)); } } else { Rect rect3 = component.rect; float num3 = ((Rect)(ref rect3)).width / 940f; Rect rect4 = component.rect; float num4 = Mathf.Min(num3, ((Rect)(ref rect4)).height / 900f); panel.localScale = Vector3.one * Mathf.Max(0.1f, num4); } } private void Render() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected O, but got Unknown //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Expected O, but got Unknown //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Expected O, but got Unknown //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_0400: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Unknown result type (might be due to invalid IL or missing references) if (!ProtectionIdols.AtForge()) { Close(); return; } if (IdolFusion.Station(Player.m_localPlayer.GetCurrentCraftingStation())) { RenderFusion(); return; } if (currentInterface == ProtectionInterface.Vanilla) { RenderVanilla(); return; } if (Object.op_Implicit((Object)(object)modal)) { modal.SetActive(false); Object.Destroy((Object)(object)modal); } Transform parent = (Transform)(Object.op_Implicit((Object)(object)stationTabRoot) ? ((object)stationTabRoot) : ((object)canvas.transform)); modal = Box(parent, new Rect(0f, 0f, 940f, 900f), ink); ((Object)modal).name = "VUU_ProtectionContent"; RectTransform component = modal.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = (Object.op_Implicit((Object)(object)stationTabRoot) ? new Vector2(12f, 12f) : new Vector2(400f, 60f)); float num = ((Object.op_Implicit((Object)(object)stationTabRoot) && Object.op_Implicit((Object)(object)launch)) ? (0f - launch.GetComponent<RectTransform>().anchoredPosition.y + 45f) : 60f); component.offsetMax = (Object.op_Implicit((Object)(object)stationTabRoot) ? new Vector2(-12f, 0f - num) : new Vector2(-400f, -60f)); panel = Box(modal.transform, new Rect(0f, 0f, 940f, 900f), ink).transform; RectTransform component2 = ((Component)panel).GetComponent<RectTransform>(); Vector2 anchorMin = (component2.anchorMax = new Vector2(0.5f, 1f)); component2.anchorMin = anchorMin; component2.pivot = new Vector2(0.5f, 1f); component2.anchoredPosition = Vector2.zero; Search(); string[] array = new string[3] { "All (Все)", "Weapons (Оружие)", "Armor (Броня)" }; for (int i = 0; i < 3; i++) { int f = i; Button val2 = Button(panel, array[i], new Rect((float)(i * 155), 50f, 145f, 32f), (UnityAction)delegate { filter = f; Render(); }); if (i == filter) { ((Graphic)((Component)val2).GetComponent<Image>()).color = new Color(0.35f, 0.29f, 0.17f, 1f); } } Button(panel, battle ? "Battle (Сражение) ⇄" : "Protection (Защита) ⇄", new Rect(475f, 50f, 285f, 32f), (UnityAction)delegate { SetBattle(!battle); }); Button(panel, "Close (Закрыть)", new Rect(775f, 50f, 165f, 32f), new UnityAction(Close)); ((Graphic)Box(panel, new Rect(309f, 100f, 2f, 790f), gold).GetComponent<Image>()).raycastTarget = false; GameObject val3 = Box(panel, new Rect(0f, 100f, 299f, 790f), ink); val3.AddComponent<RectMask2D>(); ScrollRect val4 = val3.AddComponent<ScrollRect>(); val4.horizontal = false; val4.movementType = (MovementType)2; val4.scrollSensitivity = 32f; val4.viewport = val3.GetComponent<RectTransform>(); listContent = Box(val3.transform, new Rect(0f, 0f, 288f, 790f), ink).transform; val4.content = ((Component)listContent).GetComponent<RectTransform>(); GameObject val5 = Box(panel, new Rect(330f, 100f, 610f, 790f), ink); val5.AddComponent<RectMask2D>(); ScrollRect val6 = val5.AddComponent<ScrollRect>(); val6.horizontal = false; val6.movementType = (MovementType)2; val6.scrollSensitivity = 3