using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: AssemblyDescription("Additional Epic Loot legendary sets for Orgetorix")] [assembly: AssemblyCompany("Orgetorix")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTitle("Orgetorix.MoreSetItems")] [assembly: AssemblyProduct("Orgetorix.MoreSetItems")] [assembly: AssemblyCopyright("Copyright © Orgetorix 2026")] [assembly: ComVisible(false)] [assembly: Guid("b2c3d4e5-f6a7-8901-bcde-f23456789012")] [assembly: AssemblyFileVersion("0.1.7.0")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.1.7.0")] namespace Orgetorix.MoreSetItems; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Orgetorix.MoreSetItems", "Orgetorix - More Set Items", "0.1.7")] public class MoreSetItemsPlugin : BaseUnityPlugin { public const string PluginGUID = "Orgetorix.MoreSetItems"; public const string PluginName = "Orgetorix - More Set Items"; public const string PluginVersion = "0.1.7"; internal static ManualLogSource Log; private float _regenAcc; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; InstallPatches(); new Harmony("Orgetorix.MoreSetItems").PatchAll(); AddLocalizations(); Log.LogInfo((object)"Orgetorix - More Set Items v0.1.7 loaded."); } private void Start() { AddLocalizations(); } private void Update() { _regenAcc += Time.deltaTime; if (!(_regenAcc < 1f)) { _regenAcc = 0f; TickSummonRegen(); } } private static void TickSummonRegen() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } int helPieces = HelSummonSupport.GetHelPieces(localPlayer); if (helPieces < 2) { return; } List allCharacters = Character.GetAllCharacters(); if (allCharacters == null) { return; } for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if ((Object)(object)val == (Object)null || !HelSummonSupport.IsPlayerSummon(val) || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val).transform.position) > 80f) { continue; } HelSummonSupport.TryApplyHp(val, helPieces); if (helPieces >= 4) { float health = val.GetHealth(); float maxHealth = val.GetMaxHealth(); if (!(health <= 0f) && !(health >= maxHealth)) { val.SetHealth(Mathf.Min(maxHealth, health + 8f)); } } } } private void InstallPatches() { try { string text = Path.Combine(Paths.ConfigPath, "EpicLoot", "patches", "Orgetorix", "MoreSetItems"); Directory.CreateDirectory(text); WriteResource("legendaries.json", Path.Combine(text, "legendaries.json")); string path = Path.Combine(text, "translations.json"); if (File.Exists(path)) { File.Delete(path); } Log.LogInfo((object)("Epic Loot patches written to: " + text)); } catch (Exception ex) { Log.LogError((object)("Failed to install Epic Loot patches: " + ex)); } } private static void AddLocalizations() { try { Type type = FindType("Localization"); if (type == null) { Log.LogWarning((object)"Localization type not found."); return; } PropertyInfo property = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public); object obj = ((property != null) ? property.GetValue(null, null) : null); if (obj != null) { MethodInfo method = type.GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public); if (!(method == null)) { Add(method, obj, "mod_orgetorix_set_gullveig", "Gullveig"); Add(method, obj, "mod_orgetorix_l_gullveigstaff", "Staff of Three Winters"); Add(method, obj, "mod_orgetorix_l_gullveigstaff_desc", "A two-handed staff that drinks fire, frost and storm."); Add(method, obj, "mod_orgetorix_l_gullveighelmet", "Circlet of Cinders"); Add(method, obj, "mod_orgetorix_l_gullveighelmet_desc", "Seidr burns behind the brow."); Add(method, obj, "mod_orgetorix_l_gullveigchest", "Robe of the Wildfire"); Add(method, obj, "mod_orgetorix_l_gullveigchest_desc", "Cloth that remembers the first spark."); Add(method, obj, "mod_orgetorix_l_gullveigcape", "Sash of the Storm"); Add(method, obj, "mod_orgetorix_l_gullveigcape_desc", "Wind and thunder follow the hem."); Add(method, obj, "mod_orgetorix_set_hel", "Hel"); Add(method, obj, "mod_orgetorix_l_helstaff", "Crook of the Dead"); Add(method, obj, "mod_orgetorix_l_helstaff_desc", "A two-handed staff that calls what should stay buried."); Add(method, obj, "mod_orgetorix_l_helhelmet", "Mask of the Barrow"); Add(method, obj, "mod_orgetorix_l_helhelmet_desc", "The dead know this face."); Add(method, obj, "mod_orgetorix_l_helchest", "Shroud of Helheim"); Add(method, obj, "mod_orgetorix_l_helchest_desc", "A burial wrap that still walks."); Add(method, obj, "mod_orgetorix_l_hellegs", "Bindings of the Grave"); Add(method, obj, "mod_orgetorix_l_hellegs_desc", "Strips of shroud knotted for the living."); Add(method, obj, "mod_orgetorix_set_ullr", "Ullr"); Add(method, obj, "mod_orgetorix_set_eir", "Eir"); Add(method, obj, "mod_orgetorix_set_mimir", "Mimir"); } } } catch (Exception ex) { Log.LogWarning((object)("Localization add failed: " + ex.Message)); } } private static void Add(MethodInfo addWord, object inst, string key, string value) { addWord.Invoke(inst, new object[2] { key, value }); } private static Type FindType(string name) { Type type = Type.GetType(name); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { try { type = assemblies[i].GetType(name); if (type != null) { return type; } } catch { } } return null; } private static void WriteResource(string fileName, string destPath) { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine((directoryName != null) ? directoryName : ".", "patches", fileName); if (!File.Exists(text)) { text = Path.Combine((directoryName != null) ? directoryName : ".", fileName); } if (File.Exists(text)) { File.Copy(text, destPath, overwrite: true); } else { Log.LogWarning((object)("Patch file not found next to DLL: " + fileName)); } } } public static class HelSummonSupport { public const float HpMul2 = 2f; public const float HpMul3 = 2.5f; public const float HpMul4 = 3f; public const float GolemHpMul2 = 4f; public const float GolemHpMul3 = 5.5f; public const float GolemHpMul4 = 7f; public const float DmgTaken3 = 0.7f; public const float DmgTaken4 = 0.55f; public const float RegenPerSec4 = 8f; public static readonly HashSet BuffedIds = new HashSet(); public static void TryApplyHp(Character ch, int pieces) { if ((Object)(object)ch == (Object)null || pieces < 2) { return; } int instanceID = ((Object)ch).GetInstanceID(); if (BuffedIds.Contains(instanceID)) { return; } float maxHealth = ch.GetMaxHealth(); if (!(maxHealth < 2f)) { float num = HpMultiplier(pieces, ch); ch.SetMaxHealth(maxHealth * num); ch.SetHealth(ch.GetMaxHealth()); BuffedIds.Add(instanceID); if (MoreSetItemsPlugin.Log != null) { MoreSetItemsPlugin.Log.LogInfo((object)("Hel summon HP x" + num + " on " + ((Object)ch).name + " base=" + maxHealth)); } } } public static int GetHelPieces(Player player) { if ((Object)(object)player == (Object)null) { return 0; } int count = 0; TryEpicLootSetCount(player, out count); int num = CountByJson(player); if (num > count) { count = num; } return count; } private static bool TryEpicLootSetCount(Player player, out int count) { count = 0; try { Type type = FindType("EpicLoot.API"); if (type == null) { return false; } MethodInfo method = type.GetMethod("HasLegendarySet", BindingFlags.Static | BindingFlags.Public); if (method == null) { return false; } object[] array = new object[3] { player, "Hel", 0 }; method.Invoke(null, array); if (array[2] is int) { count = (int)array[2]; } return true; } catch { return false; } } private static int CountByJson(Player player) { int num = 0; try { Type type = FindType("EpicLoot.API"); if (type == null) { return 0; } MethodInfo method = type.GetMethod("GetMagicItemJson", BindingFlags.Static | BindingFlags.Public); if (method == null) { return 0; } List equippedItems = ((Humanoid)player).GetInventory().GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { string text = method.Invoke(null, new object[1] { equippedItems[i] }) as string; if (!string.IsNullOrEmpty(text) && (text.IndexOf("HelStaff") >= 0 || text.IndexOf("HelHelmet") >= 0 || text.IndexOf("HelChest") >= 0 || text.IndexOf("HelLegs") >= 0)) { num++; } } } catch { } return num; } public static bool IsPlayerSummon(Character ch) { if ((Object)(object)ch == (Object)null || ch.IsPlayer()) { return false; } string text = ((ch.m_name != null) ? ch.m_name : ""); string text2 = ((((Object)ch).name != null) ? ((Object)ch).name : ""); string text3 = (text + " " + text2).ToLowerInvariant(); if (text3.IndexOf("summonedgolem") >= 0) { return true; } if (text3.IndexOf("tarmancer") >= 0) { return true; } if (text3.IndexOf("targolem") >= 0) { return true; } if (text3.IndexOf("tar golem") >= 0) { return true; } if (text3.IndexOf("helimp") >= 0) { return true; } if (text3.IndexOf("summoned") >= 0) { return true; } if (text3.IndexOf("summon") >= 0 && text3.IndexOf("_tw") >= 0) { return true; } if (text3.IndexOf("root") >= 0 && text3.IndexOf("_tw") >= 0) { return true; } if (!ch.IsTamed()) { return false; } if (text3.IndexOf("skeleton") >= 0) { return true; } if (text3.IndexOf("skelett") >= 0) { return true; } if (text3.IndexOf("draugr") >= 0) { return true; } if (text3.IndexOf("golem") >= 0) { return true; } if (text3.IndexOf("skel") >= 0) { return true; } return false; } public static Player FindOwner(Character ch) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) Player closestPlayer = Player.GetClosestPlayer(((Component)ch).transform.position, 80f); if ((Object)(object)closestPlayer != (Object)null) { return closestPlayer; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)ch).transform.position) < 80f) { return localPlayer; } return closestPlayer; } public static bool IsTarGolem(Character ch) { if ((Object)(object)ch == (Object)null) { return false; } string text = (((ch.m_name != null) ? ch.m_name : "") + " " + ((((Object)ch).name != null) ? ((Object)ch).name : "")).ToLowerInvariant(); if (text.IndexOf("summonedgolem") >= 0) { return true; } if (text.IndexOf("tarmancer") >= 0) { return true; } if (text.IndexOf("targolem") >= 0) { return true; } if (text.IndexOf("tar golem") >= 0) { return true; } return false; } public static float HpMultiplier(int pieces, Character ch) { bool flag = IsTarGolem(ch); if (pieces >= 4) { if (!flag) { return 3f; } return 7f; } if (pieces >= 3) { if (!flag) { return 2.5f; } return 5.5f; } if (pieces >= 2) { if (!flag) { return 2f; } return 4f; } return 1f; } public static float DamageTakenMul(int pieces) { if (pieces >= 4) { return 0.55f; } if (pieces >= 3) { return 0.7f; } return 1f; } private static Type FindType(string full) { Type type = Type.GetType(full + ", EpicLoot"); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { try { if (assemblies[i].GetName().Name == "EpicLoot") { type = assemblies[i].GetType(full); if (type != null) { return type; } } } catch { } } return null; } } [HarmonyPatch(typeof(Character), "Awake")] public static class Character_Awake_Hel { [HarmonyPostfix] public static void Postfix(Character __instance) { if (HelSummonSupport.IsPlayerSummon(__instance)) { Player player = HelSummonSupport.FindOwner(__instance); int helPieces = HelSummonSupport.GetHelPieces(player); if (helPieces >= 2) { HelSummonSupport.TryApplyHp(__instance, helPieces); } } } } [HarmonyPatch(typeof(Character), "Damage")] public static class Character_Damage_Hel { [HarmonyPrefix] public static void Prefix(Character __instance, HitData hit) { if (hit != null && HelSummonSupport.IsPlayerSummon(__instance)) { Player player = HelSummonSupport.FindOwner(__instance); int helPieces = HelSummonSupport.GetHelPieces(player); float num = HelSummonSupport.DamageTakenMul(helPieces); if (!(num >= 0.99f)) { ((DamageTypes)(ref hit.m_damage)).Modify(num); } } } }