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 NokepArmorSets v1.0.0
plugins\JotunnModStub.dll
Decompiled a day agousing System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("JotunnModStub")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("JotunnModStub")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.3.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.0.0")] namespace JotunnModStub; internal static class Armor { public static void AddAll() { foreach (ArmorSet set in Plugin.Sets) { AddEffect(set); AddPart(set, set.HelmetPrefab, set.VanillaHelmet, set.BaseName + " шлем: " + set.DisplayName.ToLower(), set.CfgHelmet.Value, set.IconName("Helmet")); AddPart(set, set.ChestPrefab, set.VanillaChest, set.BaseName + " нагрудник: " + set.DisplayName.ToLower(), set.CfgChest.Value, set.IconName("Chest")); AddPart(set, set.LegsPrefab, set.VanillaLegs, set.BaseName + " штаны: " + set.DisplayName.ToLower(), set.CfgLegs.Value, set.IconName("Legs")); } } private static void AddEffect(ArmorSet set) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = set.EffectName; ((StatusEffect)val).m_name = set.DisplayName; ((StatusEffect)val).m_tooltip = BuildTooltip(set); if (set.Bonus == "Armored") { val.m_addArmor = set.CfgBonus.Value; } if (set.CfgSpeed != null && set.CfgSpeed.Value != 0f) { if (set.Bonus == "Stamina") { val.m_runStaminaDrainModifier = set.CfgSpeed.Value / 100f; } else { val.m_speedModifier = set.CfgSpeed.Value / 100f; } } set.Effect = val; set.EffectHash = ((StatusEffect)val).NameHash(); ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false)); } private static string BuildTooltip(ArmorSet set) { float value = set.CfgBonus.Value; string text; switch (set.Bonus) { case "Vitality": text = $"+{value:0} к максимальному здоровью"; break; case "Armored": text = $"+{value:0} к броне"; break; case "Magic": text = $"+{value:0} к максимальному эйтру"; break; case "Stamina": text = $"+{value:0} к максимальной выносливости"; break; default: return ""; } if (set.CfgSpeed != null && set.CfgSpeed.Value != 0f) { float value2 = set.CfgSpeed.Value; text = ((!(set.Bonus == "Stamina")) ? (text + $"\n{value2:+0;-0}% к скорости передвижения") : (text + $"\n{value2:+0;-0}% к расходу выносливости на бег")); } return text; } private static void AddPart(ArmorSet set, string prefabName, string vanillaPrefab, string displayName, string recipeFromConfig, string iconName) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown CustomItem val = new CustomItem(prefabName, vanillaPrefab); val.ItemDrop.m_itemData.m_shared.m_name = displayName; val.ItemDrop.m_itemData.m_shared.m_description = "Часть комплекта: " + set.DisplayName.ToLower() + "."; Sprite val2 = Icons.Get(iconName); if ((Object)(object)val2 != (Object)null) { val.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 }; } val.ItemDrop.m_itemData.m_shared.m_setName = set.SetName; val.ItemDrop.m_itemData.m_shared.m_setSize = 3; val.ItemDrop.m_itemData.m_shared.m_setStatusEffect = (StatusEffect)(object)set.Effect; if (!ItemManager.Instance.AddItem(val)) { Logger.LogError((object)("Не удалось добавить " + prefabName)); } else { Recipes.Add(set, prefabName, vanillaPrefab, recipeFromConfig); } } } internal static class Recipes { private static readonly Dictionary<string, string> Sources = new Dictionary<string, string>(); private static readonly Dictionary<string, Dictionary<string, int>> Extras = new Dictionary<string, Dictionary<string, int>>(); public static void Add(ArmorSet set, string prefabName, string vanillaPrefab, string recipeFromConfig) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown RecipeConfig val = new RecipeConfig(); val.Name = "Recipe_" + prefabName; val.Item = prefabName; val.CraftingStation = "piece_nokep_leatherbench"; val.MinStationLevel = 1; Dictionary<string, int> dictionary = Utils.ParseRecipe(recipeFromConfig); if (dictionary.Count > 0) { foreach (KeyValuePair<string, int> item in dictionary) { val.AddRequirement(item.Key, item.Value, 0); } } else { val.AddRequirement("Wood", 1, 0); Sources[prefabName] = vanillaPrefab; Dictionary<string, int> dictionary2 = Utils.ParseRecipe(set.CfgExtra.Value); if (dictionary2.Count > 0) { Extras[prefabName] = dictionary2; } } ItemManager.Instance.AddRecipe(new CustomRecipe(val)); } public static void FillFromVanilla() { if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { return; } foreach (KeyValuePair<string, string> source in Sources) { Recipe val = Find(source.Key); Recipe val2 = Find(source.Value); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)("Не нашёл свой рецепт для " + source.Key)); continue; } if ((Object)(object)val2 == (Object)null || val2.m_resources == null) { Logger.LogWarning((object)("Не нашёл ванильный рецепт " + source.Value)); continue; } List<Requirement> list = new List<Requirement>(val2.m_resources); if (Extras.TryGetValue(source.Key, out var value)) { AddExtras(list, value); } val.m_resources = list.ToArray(); Logger.LogInfo((object)$"{source.Key}: {val.m_resources.Length} требований"); } } private static void AddExtras(List<Requirement> list, Dictionary<string, int> extra) { //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) //IL_0066: 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_007f: Expected O, but got Unknown foreach (KeyValuePair<string, int> item in extra) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key); if ((Object)(object)itemPrefab == (Object)null) { Logger.LogWarning((object)("Не нашёл ресурс " + item.Key + " — проверь написание в настройках")); continue; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null)) { list.Add(new Requirement { m_resItem = component, m_amount = item.Value, m_recover = true }); } } } private static Recipe Find(string itemPrefabName) { foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && ((Object)((Component)recipe.m_item).gameObject).name == itemPrefabName) { return recipe; } } return null; } } internal static class Table { public const string PrefabName = "piece_nokep_leatherbench"; public static void Add() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown PieceConfig val = new PieceConfig(); val.Name = ModConfig.TableName.Value; val.Description = "Здесь шьют особую кожаную броню."; val.PieceTable = "Hammer"; val.Category = "Crafting"; foreach (KeyValuePair<string, int> item in Utils.ParseRecipe(ModConfig.TableRecipe.Value)) { val.AddRequirement(item.Key, item.Value, true); } CustomPiece val2 = new CustomPiece("piece_nokep_leatherbench", "piece_workbench", val); CraftingStation component = val2.PiecePrefab.GetComponent<CraftingStation>(); if ((Object)(object)component != (Object)null) { component.m_name = ModConfig.TableName.Value; component.m_craftRequireRoof = ModConfig.RequireRoof.Value; component.m_craftRequireFire = ModConfig.RequireFire.Value; component.m_showBasicRecipies = false; } else { Logger.LogError((object)"На верстаке нет компонента CraftingStation"); } PieceManager.Instance.AddPiece(val2); } } internal class ArmorSet { public string Id; public string DisplayName; public string BaseName; public string Bonus; public string VanillaHelmet; public string VanillaChest; public string VanillaLegs; public string IconFolder = ""; public string IconPrefix = ""; public string EffectName; public int EffectHash; public SE_Stats Effect; public ConfigEntry<float> CfgBonus; public ConfigEntry<float> CfgSpeed; public ConfigEntry<string> CfgExtra; public ConfigEntry<string> CfgHelmet; public ConfigEntry<string> CfgChest; public ConfigEntry<string> CfgLegs; public string HelmetPrefab => "Nokep_Helmet_" + Id; public string ChestPrefab => "Nokep_Chest_" + Id; public string LegsPrefab => "Nokep_Legs_" + Id; public string SetName => "Nokep_Set_" + Id; public string IconName(string part) { string text = (string.IsNullOrEmpty(IconPrefix) ? (Bonus + "_" + part) : (IconPrefix + "_" + Bonus + "_" + part)); if (!string.IsNullOrEmpty(IconFolder)) { return IconFolder + "/" + text; } return text; } } internal static class Icons { private static readonly Dictionary<string, Sprite> cache = new Dictionary<string, Sprite>(); public static Sprite Get(string name) { if (cache.TryGetValue(name, out var value)) { return value; } Sprite val = Load(name); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)("Иконка " + name + " не загрузилась")); } cache[name] = val; return val; } private static Sprite Load(string name) { //IL_008b: 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) Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "NokepArmorSets.Assets." + name.Replace("/", ".") + ".png"; using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { Logger.LogWarning((object)("Не нашёл ресурс " + text)); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = AssetUtils.LoadImage(array); if ((Object)(object)val == (Object)null) { return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } public static void LogResourceNames() { string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); Logger.LogInfo((object)("Встроенные ресурсы: " + string.Join(", ", manifestResourceNames))); } } internal static class ModConfig { public static ConfigEntry<string> TableName; public static ConfigEntry<string> TableRecipe; public static ConfigEntry<bool> RequireRoof; public static ConfigEntry<bool> RequireFire; private static ConfigFile file; public static void Bind(ConfigFile config) { file = config; TableName = config.Bind<string>("0. Верстак", "Название", "Верстак скорняка", "Как называется верстак в игре. Применяется после перезапуска."); TableRecipe = config.Bind<string>("0. Верстак", "Рецепт", "Wood:10", "Из чего строится верстак. Формат: Предмет:Количество, через запятую."); RequireRoof = config.Bind<bool>("0. Верстак", "Нужна крыша", true, "Требовать крышу для работы верстака."); RequireFire = config.Bind<bool>("0. Верстак", "Нужен огонь", false, "Требовать огонь рядом для работы верстака."); BindSet("Vitality", "1. Луга — живучесть", 15f, 0f, "BoneFragments:8, LeatherScraps:6"); BindSet("Armored", "1. Луга — прочность", 3f, 0f, "Flint:8, LeatherScraps:6"); BindSet("Magic", "1. Луга — магия", 10f, 0f, "Feathers:10, Wood:10"); BindSet("Stamina", "1. Луга — выносливость", 15f, 0f, "Resin:10, Wood:10"); BindSet("Troll_Vitality", "2. Тролль — живучесть", 25f, 5f, "TrollHide:2, RoundLog:15, Resin:10"); BindSet("Troll_Armored", "2. Тролль — прочность", 5f, 0f, "TrollHide:5, FineWood:10"); BindSet("Troll_Magic", "2. Тролль — магия", 25f, 0f, "TrollHide:2, GreydwarfEye:20, Resin:10"); BindSet("Troll_Stamina", "2. Тролль — выносливость", 25f, -10f, "TrollHide:2, Thistle:10, FineWood:10"); BindSet("Bronze_Vitality", "3. Бронза — живучесть", 35f, 0f, "Bronze:2, Copper:5, RoundLog:15"); BindSet("Bronze_Armored", "3. Бронза — прочность", 8f, -5f, "Bronze:6, Coal:10"); BindSet("Bronze_Magic", "3. Бронза — магия", 20f, 0f, "Bronze:2, SurtlingCore:5, Coal:10"); BindSet("Bronze_Stamina", "3. Бронза — выносливость", 25f, 0f, "Bronze:2, Tin:5, RoundLog:15"); } private static void BindSet(string setId, string section, float bonus, float speed, string extraDefault) { ArmorSet armorSet = Plugin.Sets.Find((ArmorSet s) => s.Id == setId); if (armorSet == null) { Logger.LogError((object)("Нет комплекта " + setId + " — настройки не привязаны")); return; } armorSet.CfgBonus = file.Bind<float>(section, "Бонус", bonus, BonusHint(armorSet.Bonus)); armorSet.CfgSpeed = file.Bind<float>(section, "Доп. бонус", speed, (armorSet.Bonus == "Stamina") ? "Изменение расхода выносливости на бег, в процентах. Минус — экономия." : "Изменение скорости передвижения, в процентах. 0 — без изменений."); armorSet.CfgExtra = file.Bind<string>(section, "Доп. ресурс", extraDefault, "Что добавляется к ванильному рецепту каждой вещи. Формат: Предмет:Количество. Пусто — ничего не добавлять."); armorSet.CfgHelmet = file.Bind<string>(section, "Рецепт шлема", "", "Свой рецепт вместо ванильного. Формат: Предмет:Количество, через запятую. Пусто — ванильный рецепт плюс доп. ресурс."); armorSet.CfgChest = file.Bind<string>(section, "Рецепт нагрудника", "", "Свой рецепт вместо ванильного. Формат: Предмет:Количество, через запятую. Пусто — ванильный рецепт плюс доп. ресурс."); armorSet.CfgLegs = file.Bind<string>(section, "Рецепт штанов", "", "Свой рецепт вместо ванильного. Формат: Предмет:Количество, через запятую. Пусто — ванильный рецепт плюс доп. ресурс."); } private static string BonusHint(string bonus) { return bonus switch { "Vitality" => "Сколько максимального здоровья даёт полный комплект.", "Armored" => "Сколько брони даёт полный комплект.", "Magic" => "Сколько максимального эйтра даёт полный комплект.", "Stamina" => "Сколько максимальной выносливости даёт полный комплект.", _ => "", }; } } [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] internal static class FoodValuePatch { private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr) { if ((Object)(object)__instance == (Object)null) { return; } SEMan sEMan = ((Character)__instance).GetSEMan(); if (sEMan == null) { return; } foreach (ArmorSet set in Plugin.Sets) { if (!((Object)(object)set.Effect == (Object)null) && sEMan.HaveStatusEffect(set.EffectHash)) { float value = set.CfgBonus.Value; switch (set.Bonus) { case "Vitality": hp += value; break; case "Stamina": stamina += value; break; case "Magic": eitr += value; break; } } } } } [BepInPlugin("nokep.valheim.armorsets", "NokepArmorSets", "0.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class Plugin : BaseUnityPlugin { public const string PluginGUID = "nokep.valheim.armorsets"; public const string PluginName = "NokepArmorSets"; public const string PluginVersion = "0.3.0"; public static readonly List<ArmorSet> Sets = new List<ArmorSet>(); private Harmony harmony; private void Awake() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown Sets.AddRange(Meadows.GetSets()); Sets.AddRange(BlackForest.GetSets()); ModConfig.Bind(((BaseUnityPlugin)this).Config); harmony = new Harmony("nokep.valheim.armorsets"); harmony.PatchAll(); PrefabManager.OnVanillaPrefabsAvailable += AddContent; ItemManager.OnItemsRegistered += Recipes.FillFromVanilla; } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private void AddContent() { Table.Add(); Armor.AddAll(); PrefabManager.OnVanillaPrefabsAvailable -= AddContent; } } internal static class BlackForest { public const string IconFolder = "BlackForest"; public static List<ArmorSet> GetSets() { return new List<ArmorSet> { Troll("Vitality", "Живучесть"), Troll("Armored", "Прочность"), Troll("Magic", "Магия"), Troll("Stamina", "Выносливость"), Bronze("Vitality", "Живучесть"), Bronze("Armored", "Прочность"), Bronze("Magic", "Магия"), Bronze("Stamina", "Выносливость") }; } private static ArmorSet Troll(string bonus, string displayName) { return new ArmorSet { Id = "Troll_" + bonus, Bonus = bonus, DisplayName = displayName, BaseName = "Тролльий", VanillaHelmet = "HelmetTrollLeather", VanillaChest = "ArmorTrollLeatherChest", VanillaLegs = "ArmorTrollLeatherLegs", IconFolder = "BlackForest", IconPrefix = "Troll", EffectName = "Nokep_SetEffect_Troll_" + bonus }; } private static ArmorSet Bronze(string bonus, string displayName) { return new ArmorSet { Id = "Bronze_" + bonus, Bonus = bonus, DisplayName = displayName, BaseName = "Бронзовый", VanillaHelmet = "HelmetBronze", VanillaChest = "ArmorBronzeChest", VanillaLegs = "ArmorBronzeLegs", IconFolder = "BlackForest", IconPrefix = "Bronze", EffectName = "Nokep_SetEffect_Bronze_" + bonus }; } } internal static class Meadows { private const string Helmet = "HelmetLeather"; private const string Chest = "ArmorLeatherChest"; private const string Legs = "ArmorLeatherLegs"; public static List<ArmorSet> GetSets() { return new List<ArmorSet> { Make("Vitality", "Живучесть"), Make("Armored", "Прочность"), Make("Magic", "Магия"), Make("Stamina", "Выносливость") }; } private static ArmorSet Make(string bonus, string displayName) { return new ArmorSet { Id = bonus, Bonus = bonus, DisplayName = displayName, BaseName = "Кожаный", VanillaHelmet = "HelmetLeather", VanillaChest = "ArmorLeatherChest", VanillaLegs = "ArmorLeatherLegs", EffectName = "Nokep_SetEffect_" + bonus }; } } internal static class Utils { public static Dictionary<string, int> ParseRecipe(string text) { Dictionary<string, int> dictionary = new Dictionary<string, int>(); if (string.IsNullOrEmpty(text)) { return dictionary; } string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Trim().Split(new char[1] { ':' }); if (array2.Length == 2) { string text2 = array2[0].Trim(); if (text2.Length != 0 && int.TryParse(array2[1].Trim(), out var result) && result >= 1) { dictionary[text2] = result; } } } return dictionary; } }