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 EpicLoot ProgressionFix v1.24.1
plugins/EpicLootProgressionFix.dll
Decompiled 16 hours 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Sockets; using System.Net.WebSockets; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security.Authentication; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Common; using EpicLoot; using EpicLoot.Adventure; using EpicLoot.Adventure.Feature; using EpicLoot.Biomes; using EpicLoot.Compendium; using EpicLoot.Crafting; using EpicLoot.CraftingV2; using EpicLoot.GatedItemType; using EpicLoot.LegendarySystem; using EpicLoot.LootBeams; using EpicLoot.Magic.MagicItemEffects; using EpicLoot.MagicItemEffects; using EpicLoot.MagicItemEffects.Shards; using EpicLoot.ShardStones; using EpicLoot.Transformation; using EpicLoot.src.Magic.MagicItemEffects.Helpers; using EpicLoot_UnityLib; using HarmonyLib; using HarmonyLib.Public.Patching; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using MonoMod.Cil; using MonoMod.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using SoftReferenceableAssets; using Splatform; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; using Valheim.SettingsGui; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EpicLootProgressionFix { internal static class AchievementAnnouncements { private static readonly HashSet<string> ObservedUnlocks = new HashSet<string>(); private static FieldInfo discordInstance; private static object chat; private static object defaultRoute; private static ManualLogSource logger; [ThreadStatic] private static int suppressedUnlocks; internal static void Initialize(IntegrationPatches harmony, ManualLogSource log) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00bf: Expected O, but got Unknown //IL_00bf: Expected O, but got Unknown if (DiscordBot.Installed) { logger = log; discordInstance = AccessTools.Field(DiscordBot.Discord, "instance"); if (discordInstance == null) { throw new InvalidOperationException("DiscordBot achievement relay API changed."); } chat = Enum.Parse(DiscordBot.Webhook, "Chat"); defaultRoute = Enum.Parse(DiscordBot.WebhookRoute, "Default"); harmony.Patch(AccessTools.Method(typeof(Achievements), "AchievementEvent", (Type[])null, (Type[])null), new HarmonyMethod(typeof(AchievementAnnouncements), "BeforeUnlock", (Type[])null), new HarmonyMethod(typeof(AchievementAnnouncements), "AfterUnlock", (Type[])null), null, new HarmonyMethod(typeof(AchievementAnnouncements), "AfterUnlockTree", (Type[])null)); } } private static void BeforeUnlock(bool synchronize, out int __state) { __state = suppressedUnlocks; if (!synchronize) { suppressedUnlocks++; } } private static void AfterUnlockTree(int __state) { suppressedUnlocks = __state; } private static void AfterUnlock(Achievement ach) { if ((Object)(object)ach == (Object)null || !ObservedUnlocks.Add(ach.m_id) || suppressedUnlocks != 0 || !Plugin.DiscordAchievements.Value || !Plugin.Ready) { return; } Player localPlayer = Player.m_localPlayer; ZRpc val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerRPC() : null); if ((Object)(object)localPlayer == (Object)null || val == null || !val.IsConnected()) { return; } try { object value = discordInstance.GetValue(null); if (value == null) { throw new InvalidOperationException("DiscordBot is not ready to relay the achievement."); } string text = English(ach.m_name); string text2 = English(ach.m_description); if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(text2)) { throw new InvalidOperationException("Achievement " + ach.m_id + " has no English name or requirement description."); } string text3 = PlainText(localPlayer.GetPlayerName()); string text4 = text3 + " earned the achievement \"" + text + "\" [" + text2 + "]"; DiscordBot.SendMessage.Invoke(value, new object[5] { chat, text3, DiscordSystemMessages.Box(text4), null, defaultRoute }); } catch (Exception ex) { logger.LogError((object)("Could not announce achievement " + ach.m_id + ": " + ex.GetBaseException().Message)); } } private static string English(string text) { if (!EnglishText.TryTranslate(text, out var english)) { throw new InvalidOperationException("Missing English achievement text: " + english); } return PlainText(english); } private static string PlainText(string text) { text = DiscordSystemMessages.StripTags(text).Replace("\\n", " "); return Regex.Replace(text, "\\s+", " ").Trim(); } } [HarmonyPatch] internal static class ActiveEffectsPage { private enum Section { Resources, Defense, Movement, Attacks, Skills, Utility, Other } private sealed class Page : MagicTextInfo { internal Page() : base(Localization.instance.Localize("$inventory_activeeffects"), true) { } public override void Build(MagicPages pages) { shownOn = pages; shownRows = null; pages.TitleElement.SetFontSize(30); pages.TitleElement.SetSize(pages.MinWidth, 50f); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { List<(string, string)> tooltips = new List<(string, string)>(); Fill(pages, RowsWithTooltips(Player.m_localPlayer, tooltips), tooltips); } } } private const float RefreshSeconds = 0.5f; private const string ValueColor = "#ffa500"; private const string MutedColor = "#9a9a9a"; private const string HeadingColor = "#ffa626"; private const int TitleFontSize = 30; private const int HeadingFontSize = 20; private const int RowFontSize = 16; private const float TitleHeight = 50f; private const float HeadingHeight = 34f; private const float RowSpacing = 2f; private const float ColumnSpacing = 24f; private static readonly CultureInfo Numbers; private static readonly FieldRef<TextsDialog, List<TextInfo>> Texts; private static readonly FieldRef<Skills, Dictionary<SkillType, Skill>> SkillData; private static readonly FieldRef<Humanoid, float> BlockTimer; private static readonly FieldRef<SE_Demister, GameObject> WispBall; private static readonly Func<Player, float> DodgeStamina; private static readonly Func<Character, float> JogFactor; private static readonly Func<Character, float> RunFactor; private static readonly Action<MagicTextElement, string> SetText; private static readonly FieldRef<MagicTextList, VerticalLayoutGroup> ListLayout; private static readonly FieldRef<MagicTextList, ScrollRect> ListScroll; private static readonly FieldRef<MagicTextElement, GameObject> ElementObject; private static readonly FieldRef<UITooltip> ShownTooltip; private static readonly (DamageType Type, string Name)[] DamageTypes; private static readonly string[] SectionNames; private static readonly HashSet<string> Included; private static readonly Dictionary<string, Section> Sections; private static readonly string[] CriticalHealth; private static readonly string[] Daytime; private static readonly string[] Nighttime; private static readonly string[] WhileRested; private static readonly Dictionary<string, string> EpicLootStatusTexts; private static Page page; private static MagicPages shownOn; private static List<string> shownRows; private static readonly List<UITooltip> statusTooltips; private static GameObject columns; private static float nextRefresh; static ActiveEffectsPage() { Numbers = CultureInfo.InvariantCulture; Texts = AccessTools.FieldRefAccess<TextsDialog, List<TextInfo>>("m_texts"); SkillData = AccessTools.FieldRefAccess<Skills, Dictionary<SkillType, Skill>>("m_skillData"); BlockTimer = AccessTools.FieldRefAccess<Humanoid, float>("m_blockTimer"); WispBall = AccessTools.FieldRefAccess<SE_Demister, GameObject>("m_ballInstance"); DodgeStamina = AccessTools.MethodDelegate<Func<Player, float>>(AccessTools.Method(typeof(Player), "GetDodgeStaminaUse", (Type[])null, (Type[])null), (object)null, true); JogFactor = AccessTools.MethodDelegate<Func<Character, float>>(AccessTools.Method(typeof(Character), "GetJogSpeedFactor", (Type[])null, (Type[])null), (object)null, true); RunFactor = AccessTools.MethodDelegate<Func<Character, float>>(AccessTools.Method(typeof(Character), "GetRunSpeedFactor", (Type[])null, (Type[])null), (object)null, true); SetText = AccessTools.MethodDelegate<Action<MagicTextElement, string>>(AccessTools.Method(typeof(MagicTextElement), "Set", (Type[])null, (Type[])null), (object)null, true); ListLayout = AccessTools.FieldRefAccess<MagicTextList, VerticalLayoutGroup>("_layout"); ListScroll = AccessTools.FieldRefAccess<MagicTextList, ScrollRect>("_scrollRect"); ElementObject = AccessTools.FieldRefAccess<MagicTextElement, GameObject>("_obj"); ShownTooltip = AccessTools.StaticFieldRefAccess<UITooltip>(AccessTools.Field(typeof(UITooltip), "m_current")); DamageTypes = new(DamageType, string)[8] { ((DamageType)1, "Blunt"), ((DamageType)2, "Slash"), ((DamageType)4, "Pierce"), ((DamageType)32, "Fire"), ((DamageType)64, "Frost"), ((DamageType)128, "Lightning"), ((DamageType)256, "Poison"), ((DamageType)512, "Spirit") }; SectionNames = new string[7] { "Health and resources", "Defense", "Movement", "Attacks", "Skills", "Utility", "Other effects" }; Included = new HashSet<string> { MagicEffectType.AddAllSkills, MagicEffectType.Interconnected, MagicEffectType.ConvertHealthToEitr, MagicEffectType.DeepWell, MagicEffectType.SlightlyWeakToFire, MagicEffectType.WeakToFire, MagicEffectType.VeryWeakToFire, MagicEffectType.IncreaseHealth, MagicEffectType.IncreaseStamina, MagicEffectType.IncreaseEitr, MagicEffectType.PercentHealth, MagicEffectType.PercentStamina, MagicEffectType.PercentEitr, MagicEffectType.BulkUp, MagicEffectType.EnergeticEitr, MagicEffectType.HeartyEitr, MagicEffectType.EveryXPointsOfEitrIncreasesStamina, MagicEffectType.GainMaxStaminaBasedOnPlayerMaxHealth, MagicEffectType.StaminaIncreaseForMovementPenalty, MagicEffectType.DartingThoughts, MagicEffectType.ModifyHealthRegen, MagicEffectType.AddHealthRegen, MagicEffectType.ModifyStaminaRegen, MagicEffectType.ModifyEitrRegen, MagicEffectType.StaminaRegenBonusFromPlayerWeight, MagicEffectType.BloodMagicLevelIncreasesHealthRegen, MagicEffectType.ModifyLowHealth, MagicEffectType.ModifyArmor, MagicEffectType.ArmorFromMovementPenalty, MagicEffectType.ReduceArmorIncreaseDamage, MagicEffectType.AddFireResistancePercentage, MagicEffectType.AddFrostResistancePercentage, MagicEffectType.AddLightningResistancePercentage, MagicEffectType.AddPoisonResistancePercentage, MagicEffectType.AddSpiritResistancePercentage, MagicEffectType.AddElementalResistancePercentage, MagicEffectType.AddBluntResistancePercentage, MagicEffectType.AddSlashingResistancePercentage, MagicEffectType.AddPiercingResistancePercentage, MagicEffectType.AddChoppingResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage, MagicEffectType.PhysToFire, MagicEffectType.PhysToFrost, MagicEffectType.PhysToPoison, MagicEffectType.PhysToLightning, MagicEffectType.ModifyBlockPower, MagicEffectType.ModifyParry, MagicEffectType.ModifyBlockForce, MagicEffectType.ModifyParryWindow, MagicEffectType.BurdenedBlock, MagicEffectType.AnchoredBlock, MagicEffectType.Duelist, MagicEffectType.ModifyBlockStaminaUse, MagicEffectType.ModifyMovementSpeed, MagicEffectType.RemoveSpeedPenalty, MagicEffectType.TravelLight, MagicEffectType.ModifySprintStaminaUse, MagicEffectType.ModifyJumpStaminaUse, MagicEffectType.ModifyDodgeStaminaUse, MagicEffectType.DecreaseDodgeCost, MagicEffectType.ModifyNoise, MagicEffectType.AddCarryWeight, MagicEffectType.Megingjord, MagicEffectType.CarryWeightForMovementPenalty, MagicEffectType.ReduceWeight, MagicEffectType.Weightless, MagicEffectType.IncreaseHeatResistance, MagicEffectType.ModifyDamage, MagicEffectType.ModifyPhysicalDamage, MagicEffectType.ModifyElementalDamage, MagicEffectType.AddBluntDamage, MagicEffectType.AddSlashingDamage, MagicEffectType.AddPiercingDamage, MagicEffectType.AddFireDamage, MagicEffectType.AddFrostDamage, MagicEffectType.AddLightningDamage, MagicEffectType.AddPoisonDamage, MagicEffectType.AddSpiritDamage, MagicEffectType.CoinHoarder, MagicEffectType.ConvertPhysicalDamageToLightning, MagicEffectType.IcyWeight, MagicEffectType.DamageBonusFromPlayerWeight, MagicEffectType.DamageIncreaseFromMovementPenalty, MagicEffectType.NecroticFire, MagicEffectType.AddSwordsSkill, MagicEffectType.AddKnivesSkill, MagicEffectType.AddClubsSkill, MagicEffectType.AddPolearmsSkill, MagicEffectType.AddSpearsSkill, MagicEffectType.AddBlockingSkill, MagicEffectType.AddAxesSkill, MagicEffectType.AddBowsSkill, MagicEffectType.AddCrossbowsSkill, MagicEffectType.AddUnarmedSkill, MagicEffectType.AddPickaxesSkill, MagicEffectType.AddFishingSkill, MagicEffectType.AddElementalMagicSkill, MagicEffectType.AddBloodMagicSkill, MagicEffectType.AddMovementSkills, MagicEffectType.AddCrafterSkills, MagicEffectType.IncreaseMeleeSkills, MagicEffectType.IncreaseRangedSkills, MagicEffectType.BlockAsDodgeAsBlock, MagicEffectType.BlockAsWoodCuttingAndPickaxes, MagicEffectType.Comfortable, MagicEffectType.FeatherFall, MagicEffectType.ModifyDurability, MagicEffectType.Indestructible, MagicEffectType.SailingSpeed, MagicEffectType.DaySailingSpeed }; Sections = new Dictionary<string, Section>(); CriticalHealth = new string[11] { MagicEffectType.ModifyArmorLowHealth, MagicEffectType.ModifyDamageLowHealth, MagicEffectType.ModifyBlockPowerLowHealth, MagicEffectType.ModifyParryLowHealth, MagicEffectType.ModifyMovementSpeedLowHealth, MagicEffectType.ModifyHealthRegenLowHealth, MagicEffectType.ModifyStaminaRegenLowHealth, MagicEffectType.ModifyEitrRegenLowHealth, MagicEffectType.ModifyAttackSpeedLowHealth, MagicEffectType.AvoidDamageTakenLowHealth, MagicEffectType.LifeStealLowHealth }; Daytime = new string[6] { MagicEffectType.DayArmor, MagicEffectType.DayHealthRegen, MagicEffectType.DayStaminaRegen, MagicEffectType.IncreaseDamageDuringDaytime, MagicEffectType.DayDiscovery, MagicEffectType.DayBlocker }; Nighttime = new string[5] { MagicEffectType.DamageReductionAtNight, MagicEffectType.NightStaminaRegenIncrease, MagicEffectType.IncreaseDamageDuringNighttime, MagicEffectType.NightCarryWeight, MagicEffectType.NightBlocker }; WhileRested = new string[2] { MagicEffectType.RestingHealthRegen, MagicEffectType.GainMaxCarryWeightFromRested }; EpicLootStatusTexts = new Dictionary<string, string> { ["EL_AssassinCooldown"] = "Your Assassin strike is recharging.", ["EL_BonemassPoisonCooldown"] = "Enemies you kill won't burst in venom until this ends.", ["EL_EitrBarrier"] = "Part of every hit is taken from your eitr first.", ["EL_EitrInfusion"] = "Your hits deal extra damage. Your eitr doesn't regenerate.", ["EL_ForestsAidCooldown"] = "Roots won't erupt when you are hit until this ends.", ["EL_Frostwalker"] = "Water freezes under your feet, draining your eitr. Crouch to break through.", ["EL_IcyRetributionCooldown"] = "You won't release a frost nova when hit until this ends.", ["EL_MeteorSummonerCharge"] = "Your weapon hits build charges. At full charge, your next hit calls down a meteor.", ["EL_RunningOnEmptyCooldown"] = "You won't burn health for stamina until this ends.", ["EL_ShockingChargeIndicator"] = "Your hits build charges. At full charge, your next hit unleashes a lightning shockwave.", ["EL_SpiritAnimal"] = "Your bound creature's spirit fights beside you until this ends.", ["EL_Vanished"] = "Enemies have lost sight of you. Your next hit from hiding is a sneak attack." }; statusTooltips = new List<UITooltip>(); Put(Section.Resources, CriticalHealth.Where((string type) => type.Contains("Regen")).ToArray()); Put(Section.Resources, new string[44] { MagicEffectType.DayHealthRegen, MagicEffectType.DayStaminaRegen, MagicEffectType.NightStaminaRegenIncrease, MagicEffectType.RestingHealthRegen, MagicEffectType.LifeSteal, MagicEffectType.LifeStealLowHealth, MagicEffectType.EitrLeech, MagicEffectType.BloodDrinker, MagicEffectType.Bloodlust, MagicEffectType.LifeGainOnHit, MagicEffectType.HealthGainPerXDamageDone, MagicEffectType.HealthOnEitrUse, MagicEffectType.StaminaOnKill, MagicEffectType.StaminaReturnFromEitr, MagicEffectType.RunningOnEmpty, MagicEffectType.ConsumeEitrFirstForBloodCosts, MagicEffectType.ConvertEitrCostToStaminaCost, MagicEffectType.ReduceEitrCost, MagicEffectType.KillsReduceNextBloodCost, MagicEffectType.GainEitrWhenSacrificingHealth, MagicEffectType.Conduit, MagicEffectType.Kindling, MagicEffectType.PerfectDodge, MagicEffectType.PerfectDodgeGivesHealth, MagicEffectType.PerfectDodgeGivesStamina, MagicEffectType.PerfectDodgeGivesEitr, MagicEffectType.AdrenalineCharge, MagicEffectType.AdrenalineFrostWave, MagicEffectType.AdrenalineIncreasesHealthRegen, MagicEffectType.BurningAdrenaline, MagicEffectType.DamageTakenGivesAdrenaline, MagicEffectType.EitrUseGivesAdrenaline, MagicEffectType.GainAdrenalineFromHarvesting, MagicEffectType.GainAdrenalineWhenApplyingPoison, MagicEffectType.GainAdrenalineWhenSacrificingHealth, MagicEffectType.SummonBatWhenActivatingAdrenaline, MagicEffectType.UseAdrenalineAsStamina, MagicEffectType.StormFury, MagicEffectType.Everflow, MagicEffectType.AutoMead, MagicEffectType.InstantMead, MagicEffectType.DecreaseMeadCooldown, MagicEffectType.PotionEfficacy, MagicEffectType.DecreaseForsakenCooldown }); Put(Section.Defense, new string[35] { MagicEffectType.ModifyArmorLowHealth, MagicEffectType.DayArmor, MagicEffectType.DamageReductionAtNight, MagicEffectType.ModifyBlockPowerLowHealth, MagicEffectType.ModifyParryLowHealth, MagicEffectType.AvoidDamageTaken, MagicEffectType.AvoidDamageTakenLowHealth, MagicEffectType.ReflectDamage, MagicEffectType.EitrShield, MagicEffectType.Warding, MagicEffectType.ElementalWarding, MagicEffectType.Coinplated, MagicEffectType.Immovable, MagicEffectType.BloodStaggerBlock, MagicEffectType.BloodBaseBlock, MagicEffectType.LifeGainOnBlock, MagicEffectType.StaminaGainOnBlock, MagicEffectType.EitrGainOnBlock, MagicEffectType.LuckyBlock, MagicEffectType.StaggerOnBlock, MagicEffectType.PhysToFireOnBlock, MagicEffectType.PhysToFrostOnBlock, MagicEffectType.PhysToPoisonOnBlock, MagicEffectType.PhysToLightningOnBlock, MagicEffectType.EitrWeave, MagicEffectType.OffSetAttack, MagicEffectType.Bulwark, MagicEffectType.Undying, MagicEffectType.ReduceFallDamage, MagicEffectType.RollCleanse, MagicEffectType.ForestsAid, MagicEffectType.IcyRetribution, MagicEffectType.Waterproof, MagicEffectType.Warmth, MagicEffectType.Paralyze }); Put(Section.Movement, new string[8] { MagicEffectType.ModifyMovementSpeedLowHealth, MagicEffectType.NightCarryWeight, MagicEffectType.GainMaxCarryWeightFromRested, MagicEffectType.DoubleJump, MagicEffectType.StormRider, MagicEffectType.BurningSpeed, MagicEffectType.PerfectDodgeGivesSpeed, MagicEffectType.Trailblazer }); Put(Section.Attacks, new string[45] { MagicEffectType.ModifyDamageLowHealth, MagicEffectType.IncreaseDamageDuringDaytime, MagicEffectType.IncreaseDamageDuringNighttime, MagicEffectType.ModifyAttackSpeed, MagicEffectType.ModifyAttackSpeedLowHealth, MagicEffectType.ModifyBackstab, MagicEffectType.ModifyStaggerDamage, MagicEffectType.ModifyStaggerDuration, MagicEffectType.StaggerOnDamageTaken, MagicEffectType.ChanceDoubleDamage, MagicEffectType.ChanceToCritOnHit, MagicEffectType.Executioner, MagicEffectType.Opportunist, MagicEffectType.Slow, MagicEffectType.ExplosiveArrows, MagicEffectType.QuickDraw, MagicEffectType.ModifyDrawStaminaUse, MagicEffectType.ModifyProjectileSpeed, MagicEffectType.ModifyMagicFireRate, MagicEffectType.ModifyFireRate, MagicEffectType.AmmoConservation, MagicEffectType.TripleBowShot, MagicEffectType.DoubleMagicShot, MagicEffectType.ChainLightning, MagicEffectType.FrostDamageAOE, MagicEffectType.StrikeCausesLightning, MagicEffectType.ShockingCharge, MagicEffectType.MeteorSummoner, MagicEffectType.CorpseRot, MagicEffectType.PoisonToTrueDamage, MagicEffectType.IncreaseAllPoisonDamageDone, MagicEffectType.EitrImbueAttack, MagicEffectType.Throwable, MagicEffectType.RecallWeapon, MagicEffectType.Apportation, MagicEffectType.HeadHunter, MagicEffectType.DodgeBuff, MagicEffectType.Bloodrage, MagicEffectType.SpellSword, MagicEffectType.ModifySummonDamage, MagicEffectType.ModifySummonHealth, MagicEffectType.BatteringRam, MagicEffectType.ModifyAttackStaminaUse, MagicEffectType.ModifyAttackEitrUse, MagicEffectType.ModifyAttackHealthUse }); Put(Section.Skills, new string[7] { MagicEffectType.QuickLearner, MagicEffectType.Inspiration, MagicEffectType.IncreaseXPGainFromMovementPenalty, MagicEffectType.IncreaseHarvestXPGain, MagicEffectType.IncreaseRangedSkills, MagicEffectType.DayBlocker, MagicEffectType.NightBlocker }); Put(Section.Utility, new string[22] { MagicEffectType.Luck, MagicEffectType.LuckyLoot, MagicEffectType.LuckyCraft, MagicEffectType.LuckWhileFishing, MagicEffectType.Riches, MagicEffectType.IncreaseMiningDrop, MagicEffectType.IncreaseTreeDrop, MagicEffectType.IncreaseHarvestDamage, MagicEffectType.BountifulHarvest, MagicEffectType.Mercenary, MagicEffectType.Wager, MagicEffectType.ModifyPickupRange, MagicEffectType.ModifyBuildDistance, MagicEffectType.ModifyDiscoveryRadius, MagicEffectType.DayDiscovery, MagicEffectType.ModifyWispRange, MagicEffectType.FreeBuild, MagicEffectType.Glowing, MagicEffectType.DvergerCirclet, MagicEffectType.Wishbone, MagicEffectType.Andvaranaut, MagicEffectType.ReduceFishingStaminaCost }); Put(Section.Resources, new string[3] { MagicEffectType.LifeAfterKill, MagicEffectType.LifeSiphon, MagicEffectType.GiantsBlood }); Put(Section.Defense, new string[3] { MagicEffectType.ReduceStaggerTaken, MagicEffectType.EitrBarrier, MagicEffectType.Vanish }); Put(Section.Movement, new string[4] { MagicEffectType.ModifyGrapplePullSpeed, MagicEffectType.ModifyGrappleFlightTime, MagicEffectType.Frostwalker, MagicEffectType.Hexen }); Put(Section.Attacks, new string[18] { MagicEffectType.CloseQuarter, MagicEffectType.Artillery, MagicEffectType.Assassin, MagicEffectType.CoilingVenom, MagicEffectType.ConjuredArrows, MagicEffectType.Earthshaker, MagicEffectType.EitrInfusion, MagicEffectType.ElementalArchery, MagicEffectType.Firebrand, MagicEffectType.HelsHarvest, MagicEffectType.KineticQuake, MagicEffectType.NineSteps, MagicEffectType.OverwhelmingLaunch, MagicEffectType.PiercingBolts, MagicEffectType.QuarryMark, MagicEffectType.ShieldThrow, MagicEffectType.Sniper, MagicEffectType.SpiritAnimal }); Put(Section.Utility, new string[2] { MagicEffectType.GreenThumb, MagicEffectType.Prosperity }); static void Put(Section section, string[] types) { foreach (string key in types) { Sections[key] = section; } } } [HarmonyPatch(typeof(TextsDialog), "UpdateTextsList")] [HarmonyPostfix] [HarmonyAfter(new string[] { "randyknapp.mods.epicloot" })] private static void ReplacePages(TextsDialog __instance) { if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)MagicPages.instance == (Object)null)) { List<TextInfo> obj = Texts.Invoke(__instance); string native = Localization.instance.Localize("$inventory_activeeffects"); obj.RemoveAll((TextInfo text) => (object)text == MagicPages.instance.MagicEffectsPage || (!(text is MagicTextInfo) && text.m_topic == native)); obj.Insert(0, (TextInfo)(object)(page ?? (page = new Page()))); } } [HarmonyPatch(typeof(MagicPages), "Reset")] [HarmonyPostfix] private static void Hidden(MagicPages __instance) { if (!((Object)(object)shownOn != (Object)(object)__instance)) { shownOn = null; shownRows = null; statusTooltips.Clear(); if ((Object)(object)columns != (Object)null) { Object.Destroy((Object)(object)columns); } columns = null; } } [HarmonyPatch(typeof(MagicPages), "OnSelectText")] [HarmonyPostfix] private static void Opened(MagicPages __instance, MagicTextInfo text) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown if ((object)text != page || (Object)(object)shownOn != (Object)(object)__instance) { return; } ScrollRect val = ListScroll.Invoke(__instance.MagicPagesTextArea); GameObject val2 = ElementObject.Invoke(__instance.TitleElement); foreach (Transform item in (Transform)val.content) { Transform val3 = item; if ((Object)(object)((Component)val3).gameObject != (Object)(object)val2 && (Object)(object)((Component)val3).gameObject != (Object)(object)columns) { LayoutElement component = ((Component)val3).GetComponent<LayoutElement>(); if (component == null || !component.ignoreLayout) { ((Component)val3).gameObject.SetActive(false); } } } Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate(val.content); val.StopMovement(); val.verticalNormalizedPosition = 1f; } [HarmonyPatch(typeof(MagicPages), "Update")] [HarmonyPostfix] private static void Refresh(MagicPages __instance) { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shownOn != (Object)(object)__instance || shownRows == null || Time.unscaledTime < nextRefresh || (Object)(object)Player.m_localPlayer == (Object)null) { return; } List<(string, string)> list = new List<(string, string)>(); List<string> list2 = RowsWithTooltips(Player.m_localPlayer, list); List<MagicTextGroup> elements = __instance.MagicPagesTextArea.Elements; if (list2.Count == shownRows.Count && elements.Count == list2.Count && list.Count == statusTooltips.Count) { for (int i = 0; i < list2.Count; i++) { if (list2[i] != shownRows[i]) { SetText((MagicTextElement)elements[i].Title, Shown(list2[i])); } } for (int j = 0; j < list.Count; j++) { statusTooltips[j].Set(list[j].Item1, list[j].Item2, (RectTransform)null, default(Vector2)); if (list[j].Item2.Length == 0 && (Object)(object)ShownTooltip.Invoke() == (Object)(object)statusTooltips[j]) { UITooltip.HideTooltip(); } } shownRows = list2; nextRefresh = Time.unscaledTime + 0.5f; } else { __instance.MagicPagesTextArea.Clear(); Fill(__instance, list2, list); } __instance.MagicPagesTextArea.ResizeOverlay(); __instance.OnSearch(__instance.Search.Input.text); } private static void Fill(MagicPages pages, List<string> rows, List<(string Topic, string Text)> tooltips) { foreach (string row in rows) { pages.MagicPagesTextArea.Add(Shown(row), Array.Empty<string>()); } Arrange(pages, rows, tooltips); shownRows = rows; nextRefresh = Time.unscaledTime + 0.5f; } private static void Arrange(MagicPages pages, List<string> rows, List<(string Topic, string Text)> tooltips) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Expected O, but got Unknown //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)columns == (Object)null) { columns = new GameObject("Active effects columns", new Type[1] { typeof(RectTransform) }); columns.transform.SetParent(((Component)ListLayout.Invoke(pages.MagicPagesTextArea)).transform, false); ((RectTransform)columns.transform).pivot = new Vector2(0.5f, 1f); HorizontalLayoutGroup obj = columns.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 24f; bool flag = (((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true); bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = flag); ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = childControlWidth; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; columns.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; for (int i = 0; i < 2; i++) { GameObject val = new GameObject("Column", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(columns.transform, false); LayoutElement obj2 = val.AddComponent<LayoutElement>(); float minWidth = (obj2.preferredWidth = 0f); obj2.minWidth = minWidth; obj2.flexibleWidth = 1f; VerticalLayoutGroup obj3 = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj3).spacing = 2f; ((LayoutGroup)obj3).childAlignment = (TextAnchor)0; flag = (((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = true); childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandWidth = flag); ((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = childControlWidth; ((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false; } } columns.transform.SetAsLastSibling(); int num2 = rows.Count; for (int j = 1; j < rows.Count; j++) { if (IsHeading(rows[j]) && Math.Max(j, rows.Count - j) < Math.Max(num2, rows.Count - num2)) { num2 = j; } } List<MagicTextGroup> elements = pages.MagicPagesTextArea.Elements; for (int k = 0; k < elements.Count; k++) { MagicTextElement val2 = (MagicTextElement)elements[k].Title; val2.SetFontSize(16); val2.SetParent(columns.transform.GetChild((k >= num2) ? 1 : 0)); if (IsHeading(rows[k])) { val2.SetAlignment((TextAnchor)6); ElementObject.Invoke(val2).AddComponent<LayoutElement>().minHeight = 34f; } } statusTooltips.Clear(); GameObject tooltipPrefab = InventoryGui.instance.m_playerGrid.m_elementPrefab.GetComponent<UITooltip>().m_tooltipPrefab; for (int l = 0; l < tooltips.Count; l++) { GameObject obj4 = ElementObject.Invoke((MagicTextElement)elements[l + 1].Title); ((Graphic)obj4.GetComponent<TMP_Text>()).raycastTarget = true; UITooltip val3 = obj4.AddComponent<UITooltip>(); val3.m_tooltipPrefab = tooltipPrefab; val3.Set(tooltips[l].Topic, tooltips[l].Text, (RectTransform)null, default(Vector2)); statusTooltips.Add(val3); } } private static string Shown(string row) { if (!IsHeading(row)) { return "<indent=1em><line-indent=-1em>" + row; } return row; } private static bool IsHeading(string row) { return row.StartsWith($"<size={20}>", StringComparison.Ordinal); } internal static List<string> Rows(Player player) { return RowsWithTooltips(player, new List<(string, string)>()); } private static List<string> RowsWithTooltips(Player player, List<(string Topic, string Text)> tooltips) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Dictionary<SkillType, Skill> dictionary = SkillData.Invoke(((Character)player).GetSkills()); HashSet<SkillType> known = new HashSet<SkillType>(dictionary.Keys); try { return Build(player, known, tooltips); } finally { foreach (SkillType item in dictionary.Keys.Where((SkillType skill) => !known.Contains(skill)).ToList()) { dictionary.Remove(item); } } } private static List<string> Build(Player player, HashSet<SkillType> known, List<(string Topic, string Text)> tooltips) { List<string> list = new List<string>(); Dictionary<Section, List<string>> dictionary = new Dictionary<Section, List<string>>(); MagicItemEffectDefinition val = default(MagicItemEffectDefinition); foreach (IGrouping<string, MagicItemEffect> item in (from effect in PlayerExtensions.GetAllActiveMagicEffects(player, (string)null) group effect by effect.EffectType).OrderBy<IGrouping<string, MagicItemEffect>, string>((IGrouping<string, MagicItemEffect> group) => group.Key, StringComparer.Ordinal)) { if (!Included.Contains(item.Key) && MagicItemEffectDefinitions.TryGet(item.Key, ref val)) { string text = Localization.instance.Localize(MagicItem.GetEffectText(val, PlayerExtensions.GetTotalActiveMagicEffectValue(player, item.Key, 1f, (ItemData)null))); bool? flag = Condition(player, item.Key); if (flag == true) { text += Muted(" (active now)"); } else if (flag == false) { text = Muted(text + " (not now)"); } Section value; Section key = (Sections.TryGetValue(item.Key, out value) ? value : Section.Other); if (!dictionary.TryGetValue(key, out var value2)) { value2 = (dictionary[key] = new List<string>()); } value2.Add(text); } } List<string> list3 = new List<string>(); StatusRows(player, list3, tooltips); if (list3.Count > 0) { list.Add(Title("Status effects")); list.AddRange(list3); } foreach (Section value4 in Enum.GetValues(typeof(Section))) { List<string> list4 = new List<string>(); switch (value4) { case Section.Resources: ResourceRows(player, list4); break; case Section.Defense: DefenseRows(player, list4); break; case Section.Movement: MovementRows(player, list4); break; case Section.Attacks: AttackRows(player, list4); break; case Section.Skills: SkillRows(player, known, list4); break; case Section.Utility: UtilityRows(player, list4); break; } if (dictionary.TryGetValue(value4, out var value3)) { list4.AddRange(value3); } if (list4.Count != 0) { list.Add(Title(SectionNames[(int)value4])); list.AddRange(list4); } } return list; } private static void StatusRows(Player player, List<string> rows, List<(string Topic, string Text)> tooltips) { List<StatusEffect> list = new List<StatusEffect>(); ((Character)player).GetSEMan().GetHUDStatusEffects(list); foreach (StatusEffect item in list) { string text = Localization.instance.Localize(item.m_name); if (!string.IsNullOrWhiteSpace(text)) { string iconText = item.GetIconText(); rows.Add(string.IsNullOrEmpty(iconText) ? text : Row(text, iconText)); tooltips.Add(Tooltip(text, Description(item))); } } foreach (Food food in player.GetFoods()) { string text2 = Localization.instance.Localize(food.m_item.m_shared.m_name); rows.Add(Row(text2, Duration(food.m_time))); tooltips.Add(Tooltip(text2, FoodText(food))); } StatusEffect val = default(StatusEffect); float num = default(float); player.GetGuardianPowerHUD(ref val, ref num); if ((Object)(object)val != (Object)null) { string text3 = Localization.instance.Localize(val.m_name); rows.Add(Row("Forsaken power: " + text3, (num > 0f) ? ("ready in " + Duration(num)) : "ready")); tooltips.Add(Tooltip(text3, PowerText(player, val))); } } private static (string Topic, string Text) Tooltip(string name, string text) { if (text.Length != 0) { return (Topic: name, Text: text); } return (Topic: "", Text: ""); } private static string GameStatusText(StatusEffect effect) { //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown switch (((Object)effect).name) { case "Burning": return "Fire damage over time. Getting wet puts it out sooner."; case "CampFire": return "Eases the cold. Sit or take shelter here to rest."; case "Demister": { GameObject val = WispBall.Invoke((SE_Demister)effect); Demister val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponentInChildren<Demister>() : null); if (!Object.op_Implicit((Object)(object)val2)) { return "Clears the mist around you."; } return "Clears the mist within " + val2.m_forceField.endRange.ToString("0.#", Numbers) + " m of you."; } case "EL_FrostWave": case "Frost": return $"Slows you by about {Mathf.RoundToInt((1f - ((SE_Frost)effect).m_minSpeedFactor) * 100f)}% at first, easing as it wears off. Any frost resistance prevents it."; case "Harpooned": return "A line ties you to whoever harpooned you and drags you back if you pull away."; case "Paralyze": return "You can't move until this ends."; case "Potion_BugRepellent": return "Deathsquitos flee from you instead of attacking."; case "Potion_tamer": return "Animals near you tame twice as fast."; case "Potion_TrollPheromones": return $"Trolls spawn more often where you are, with at least {Plugin.LovePotionMinimumTrollStars.Value} stars."; case "Smoked": return "You lose 2 health every second until you leave the smoke."; case "Spirit": return "Spirit damage over time."; default: return null; } } private static string Description(StatusEffect effect) { string text = effect.GetTooltipString(); string text2 = GameStatusText(effect); if (text2 != null) { text = text2 + text.Substring(effect.m_tooltip.Length); } text = Localization.instance.Localize(StatusEffectDurationUnits.WithSeconds(text)).Trim(); if (text.Length != 0 || !EpicLootStatusTexts.TryGetValue(((Object)effect).name, out var value)) { return text; } return value; } private static string Detail(string label, string value) { return label + ": <color=#ffa500>" + value + "</color>"; } private static string FoodText(Food food) { List<string> list = new List<string>(); if (food.m_health > 0f) { list.Add(Detail("Health", Number(food.m_health, "0"))); } if (food.m_stamina > 0f) { list.Add(Detail("Stamina", Number(food.m_stamina, "0"))); } if (food.m_eitr > 0f) { list.Add(Detail("Eitr", Number(food.m_eitr, "0"))); } if (food.m_item.m_shared.m_foodRegen > 0f) { list.Add(Detail("Healing", Number(food.m_item.m_shared.m_foodRegen) + " every 10 s")); } return string.Join("\n", list); } private static string PowerText(Player player, StatusEffect power) { List<string> list = new List<string>(); string text = Description(power); if (text.Length > 0) { list.Add(text); } float totalActiveMagicEffectValue = PlayerExtensions.GetTotalActiveMagicEffectValue(player, MagicEffectType.DecreaseForsakenCooldown, 0.01f, (ItemData)null); if (power.m_cooldown > 0f) { list.Add(Detail("Recharge", Duration(power.m_cooldown * (1f - totalActiveMagicEffectValue)))); } return string.Join("\n", list); } private static void ResourceRows(Player player, List<string> rows) { rows.Add(Row("Health", Number(((Character)player).GetHealth(), "0") + " / " + Number(((Character)player).GetMaxHealth(), "0"))); SEMan sEMan = ((Character)player).GetSEMan(); float num = 1f; sEMan.ModifyHealthRegen(ref num); float num2 = player.GetFoods().Sum((Food entry) => entry.m_item.m_shared.m_foodRegen); float value = ((num2 > 0f) ? ((num2 + PlayerExtensions.GetTotalActiveMagicEffectValue(player, MagicEffectType.AddHealthRegen, 1f, (ItemData)null)) * num) : 0f); if (num2 > 0f) { rows.Add(Row("Health regeneration", Number(value) + " every 10 s" + (Mathf.Approximately(num, 1f) ? "" : (" (" + Change(num) + ")")))); } float lowHealthPercentage = ModifyWithLowHealth.GetLowHealthPercentage(player); if (!Mathf.Approximately(lowHealthPercentage, ModifyWithLowHealth.LowHealthDefaultThreshold) || CriticalHealth.Any((string type) => PlayerExtensions.HasActiveMagicEffect(player, type))) { rows.Add(Row("Health Critical", "at " + Number(Mathf.Min(lowHealthPercentage, 1f) * 100f) + "% or less" + (ModifyWithLowHealth.PlayerHasLowHealth(player) ? " (now)" : ""))); } rows.Add(Row("Stamina", Number(player.GetStamina(), "0") + " / " + Number(((Character)player).GetMaxStamina(), "0"))); float num3 = 1f; sEMan.ModifyStaminaRegen(ref num3); if (!Mathf.Approximately(num3, 1f)) { rows.Add(Row("Stamina regeneration", Change(num3))); } float num4 = StaminaRegenDelay.EffectiveDelay(player.m_staminaRegenDelay, player); if (!Mathf.Approximately(num4, player.m_staminaRegenDelay)) { rows.Add(Row("Stamina regeneration delay", Number(num4, "0.##") + " s")); } float num5 = 1f; sEMan.ModifyEitrRegen(ref num5); if (((Character)player).GetMaxEitr() > 0f) { rows.Add(Row("Eitr", Number(player.GetEitr(), "0") + " / " + Number(((Character)player).GetMaxEitr(), "0"))); if (!Mathf.Approximately(num5, 1f)) { rows.Add(Row("Eitr regeneration", Change(num5))); } } if (((Character)player).GetMaxAdrenaline() > 0f) { rows.Add(Row("Adrenaline", Number(player.GetAdrenaline(), "0") + " / " + Number(((Character)player).GetMaxAdrenaline(), "0"))); } } private static void DefenseRows(Player player, List<string> rows) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) rows.Add(Row("Armor", Number(((Character)player).GetBodyArmor()))); DamageModifiers damageModifiers = ((Character)player).GetDamageModifiers((WeakSpot)null); List<(float, List<string>)> list = new List<(float, List<string>)>(); (DamageType, string)[] damageTypes = DamageTypes; DamageModifier val2 = default(DamageModifier); for (int i = 0; i < damageTypes.Length; i++) { (DamageType, string) tuple = damageTypes[i]; DamageType item = tuple.Item1; string item2 = tuple.Item2; HitData val = new HitData(); AddDamage(ref val.m_damage, item, 100f); IncomingPhysicalConversion.ModifyIncoming((Character)(object)player, val, false, false); ModifyResistance.ModifyIncoming((Character)(object)player, val); DamageReductionAtNight.ModifyIncoming((Character)(object)player, val); val.ApplyResistance(damageModifiers, ref val2); float taken = val.GetTotalDamage() / 100f; int num = list.FindIndex(((float Taken, List<string> Names) entry) => Mathf.Abs(entry.Taken - taken) < 0.0005f); if (num < 0) { list.Add((taken, new List<string> { item2 })); } else { list[num].Item2.Add(item2.ToLowerInvariant()); } } foreach (var (num2, list2) in list) { if (!Mathf.Approximately(num2, 1f)) { string text = ((list2.Count == 1) ? list2[0] : (string.Join(", ", list2.Take(list2.Count - 1)) + " and " + list2[list2.Count - 1])); rows.Add(Row(text + " damage taken", (num2 <= 0f) ? "immune" : Change(num2))); } } ItemData val3 = BlockedHits.CurrentBlocker((Humanoid)(object)player); if (val3 != null) { float skillFactor = ((Character)player).GetSkillFactor((SkillType)6); string text2 = Localization.instance.Localize(val3.m_shared.m_name); rows.Add(Row("Block armor", Number(val3.GetBlockPower(skillFactor)) + " (" + text2 + ")")); rows.Add(Row("Block force", Number(val3.GetDeflectionForce()))); if (val3.m_shared.m_timedBlockBonus > 1f) { float num3 = BlockTimer.Invoke((Humanoid)(object)player); float value; float deflectionForce; try { BlockTimer.Invoke((Humanoid)(object)player) = 0f; value = val3.GetBlockPower(skillFactor) * val3.m_shared.m_timedBlockBonus; ((Character)player).GetSEMan().ModifyTimedBlockBonus(ref value); deflectionForce = val3.GetDeflectionForce(); } finally { BlockTimer.Invoke((Humanoid)(object)player) = num3; } rows.Add(Row("Parry armor", Number(value))); if (!Mathf.Approximately(deflectionForce, val3.GetDeflectionForce())) { rows.Add(Row("Parry force", Number(deflectionForce))); } rows.Add(Row("Parry window", Number(ParryWindow.Seconds((Humanoid)(object)player) + PlayerExtensions.GetTotalActiveMagicEffectValue(player, MagicEffectType.ModifyParryWindow, 1f, (ItemData)null) / 1000f, "0.###") + " s")); float num4 = BlockStamina(player, ((Humanoid)player).m_perfectBlockStaminaDrain); if (num4 != 0f) { rows.Add(Row("Parry stamina", Number(num4))); } } rows.Add(Row("Block stamina", "up to " + Number(BlockStamina(player, ((Humanoid)player).m_blockStaminaDrain)) + " per hit")); } rows.Add(Row("Stagger limit", Number(((Character)player).GetMaxHealth() * ((Character)player).m_staggerDamageFactor, "0"))); float num5 = 1f; ((Character)player).GetSEMan().ModifyStagger(1f, ref num5); if (!Mathf.Approximately(num5, 1f)) { rows.Add(Row("Stagger taken", Change(num5))); } } private static void MovementRows(Player player, List<string> rows) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) SEMan sEMan = ((Character)player).GetSEMan(); float num = ((Character)player).m_speed * JogFactor((Character)(object)player); sEMan.ApplyStatusEffectSpeedMods(ref num, Vector3.zero); if (!Mathf.Approximately(num, ((Character)player).m_speed)) { rows.Add(Row("Movement speed", Change(num / ((Character)player).m_speed))); } float num2 = ((Character)player).m_runSpeed * RunFactor((Character)(object)player); sEMan.ApplyStatusEffectSpeedMods(ref num2, Vector3.zero); if (!Mathf.Approximately(num2, ((Character)player).m_runSpeed)) { rows.Add(Row("Running speed", Change(num2 / ((Character)player).m_runSpeed))); } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0f, ((Character)player).m_jumpForce, 0f); sEMan.ApplyStatusEffectJumpMods(ref val); if (!Mathf.Approximately(val.y, ((Character)player).m_jumpForce)) { rows.Add(Row("Jump strength", Change(val.y / ((Character)player).m_jumpForce))); } rows.Add(Row("Carried weight", Number(((Humanoid)player).GetInventory().GetTotalWeight()) + " / " + Number(MaxCarryWeight(player)))); Skills skills = ((Character)player).GetSkills(); float equipmentMovementModifier = ((Character)player).GetEquipmentMovementModifier(); float num3 = player.m_runStaminaDrain * Mathf.Lerp(1f, 0.5f, skills.GetSkillFactor((SkillType)102)); num3 -= num3 * equipmentMovementModifier; num3 += num3 * ((Character)player).GetEquipmentRunStaminaModifier(); sEMan.ModifyRunStaminaDrain(num3, ref num3, Vector3.zero, true); rows.Add(Row("Running stamina", Number(num3) + " per second")); float num4 = ((Character)player).m_jumpStaminaUsage - ((Character)player).m_jumpStaminaUsage * equipmentMovementModifier + ((Character)player).m_jumpStaminaUsage * ((Character)player).GetEquipmentJumpStaminaModifier(); sEMan.ModifyJumpStaminaUsage(num4, ref num4, true); rows.Add(Row("Jump stamina", Number(num4))); rows.Add(Row("Dodge stamina", Number(DodgeStamina(player)))); float num5 = Mathf.Lerp(player.m_swimStaminaDrainMinSkill, player.m_swimStaminaDrainMaxSkill, skills.GetSkillFactor((SkillType)103)); num5 += num5 * ((Character)player).GetEquipmentSwimStaminaModifier(); sEMan.ModifySwimStaminaUsage(num5, ref num5, true); rows.Add(Row("Swimming stamina", Number(num5) + " per second")); float num6 = player.m_sneakStaminaDrain * Mathf.Lerp(1f, 0.25f, Mathf.Pow(skills.GetSkillFactor((SkillType)101), 0.5f)); num6 += num6 * ((Character)player).GetEquipmentSneakStaminaModifier(); sEMan.ModifySneakStaminaUsage(num6, ref num6, true); rows.Add(Row("Sneaking stamina", Number(num6) + " per second")); float num7 = 1f; sEMan.ModifyNoise(1f, ref num7); if (!Mathf.Approximately(num7, 1f)) { rows.Add(Row("Noise", Change(num7))); } float num8 = 1f; sEMan.ModifyStealth(1f, ref num8); if (!Mathf.Approximately(num8, 1f)) { rows.Add(Row("Stealth", Change(num8))); } float equipmentHeatResistanceModifier = ((Character)player).GetEquipmentHeatResistanceModifier(); if (equipmentHeatResistanceModifier != 0f) { rows.Add(Row("Heat resistance", Change(1f + equipmentHeatResistanceModifier))); } } private static void AttackRows(Player player, List<string> rows) { //IL_0050: 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) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_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) ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon == null) { return; } ItemData item = WeaponTooltipRange.Item; HandOverride.Hands active = HandOverride.Active; try { WeaponTooltipRange.Item = currentWeapon; WeaponTooltip.AsIfEquipped(currentWeapon); ItemData ammunition; bool conjured; (DamageTypes, DamageTypes) tuple = WeaponDamagePreview.Range(player, currentWeapon, out ammunition, out conjured); List<string> list = new List<string>(); (DamageType, string)[] damageTypes = DamageTypes; for (int i = 0; i < damageTypes.Length; i++) { (DamageType, string) tuple2 = damageTypes[i]; DamageType item2 = tuple2.Item1; string item3 = tuple2.Item2; float num = Damage(tuple.Item1, item2); float num2 = Damage(tuple.Item2, item2); if (num > 0f || num2 > 0f) { list.Add("<nobr>" + Number(num, "0") + "-" + Number(num2, "0") + " " + item3.ToLowerInvariant() + "</nobr>"); } } string text = Localization.instance.Localize(currentWeapon.m_shared.m_name) + (conjured ? " with conjured arrows" : ((ammunition != null) ? (" with " + Localization.instance.Localize(ammunition.m_shared.m_name)) : "")); rows.Add(Row("Hit damage" + WeaponDamagePreview.PerProjectile(player, currentWeapon), ((list.Count > 0) ? string.Join(", ", list) : "none") + " (" + text + ")")); } finally { HandOverride.Active = active; WeaponTooltipRange.Item = item; } } private unsafe static void SkillRows(Player player, HashSet<SkillType> known, List<string> rows) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) Skills skills = ((Character)player).GetSkills(); Dictionary<SkillType, Skill> dictionary = SkillData.Invoke(skills); List<(string, string)> list = new List<(string, string)>(); foreach (SkillType item in skills.m_skills.Select((SkillDef definition) => definition.m_skill).Union(known).Distinct()) { float num = (known.Contains(item) ? dictionary[item].m_level : 0f); float num2 = skills.GetSkillFactor(item) * 100f; float num3 = num2 - Mathf.Min(Mathf.Floor(num), 100f); if (!(Mathf.Abs(num3) < 0.5f)) { list.Add((Localization.instance.Localize("$skill_" + ((object)(*(SkillType*)(&item))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant()), Number(num2, "0") + " (" + ((num3 > 0f) ? "+" : "") + Number(num3, "0") + ")")); } } foreach (var item2 in list.OrderBy<(string, string), string>(((string Name, string Value) entry) => entry.Name, StringComparer.CurrentCulture)) { rows.Add(Row(item2.Item1, item2.Item2)); } } private static void UtilityRows(Player player, List<string> rows) { rows.Add(Row("Comfort", player.GetComfortLevel().ToString(Numbers))); float totalActiveMagicEffectValue = PlayerExtensions.GetTotalActiveMagicEffectValue(player, MagicEffectType.SailingSpeed, 1f, (ItemData)null); float totalActiveMagicEffectValue2 = PlayerExtensions.GetTotalActiveMagicEffectValue(player, MagicEffectType.DaySailingSpeed, 1f, (ItemData)null); if (!(totalActiveMagicEffectValue <= 0f) || !(totalActiveMagicEffectValue2 <= 0f)) { bool flag = EnvMan.IsDay(); float num = ((1f + totalActiveMagicEffectValue * 0.01f) * (1f + totalActiveMagicEffectValue2 * 0.01f) - 1f) * 100f; if (Mathf.Approximately(num, totalActiveMagicEffectValue)) { rows.Add(Row("Helmsman's sailing and rowing speed", "+" + EffectTooltips.SailingSpeedText(totalActiveMagicEffectValue) + "%")); return; } SailingRow("Helmsman's daytime sailing and rowing speed", num, flag); SailingRow("Helmsman's nighttime sailing and rowing speed", totalActiveMagicEffectValue, !flag); } void SailingRow(string label, float forcePercent, bool active) { if (forcePercent != 0f) { string text = "+" + EffectTooltips.SailingSpeedText(forcePercent) + "%"; rows.Add(active ? (Row(label, text) + Muted(" (active now)")) : Muted(label + " " + text + " (not now)")); } } } private static float BlockStamina(Player player, float drain) { drain += drain * ((Character)player).GetEquipmentBlockStaminaModifier(); ((Character)player).GetSEMan().ModifyBlockStaminaUsage(drain, ref drain, false); return drain; } private static float MaxCarryWeight(Player player) { float carryWeightRate = Game.m_carryWeightRate; Game.m_carryWeightRate = 1f; try { return player.GetMaxCarryWeight(); } finally { Game.m_carryWeightRate = carryWeightRate; } } private static bool? Condition(Player player, string type) { if (CriticalHealth.Contains(type)) { return ModifyWithLowHealth.PlayerHasLowHealth(player); } if (Daytime.Contains(type)) { return EnvMan.IsDay(); } if (Nighttime.Contains(type)) { return EnvMan.IsNight(); } if (WhileRested.Contains(type)) { return ((Character)player).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectRested); } return null; } private static void AddDamage(ref DamageTypes damage, DamageType type, float amount) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 if ((int)type <= 64) { switch (type - 1) { case 0: damage.m_blunt += amount; return; case 1: damage.m_slash += amount; return; case 3: damage.m_pierce += amount; return; case 2: return; } if ((int)type != 32) { if ((int)type == 64) { damage.m_frost += amount; } } else { damage.m_fire += amount; } } else if ((int)type != 128) { if ((int)type != 256) { if ((int)type == 512) { damage.m_spirit += amount; } } else { damage.m_poison += amount; } } else { damage.m_lightning += amount; } } private static float Damage(DamageTypes damage, DamageType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0043: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0074: 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) if ((int)type <= 64) { switch (type - 1) { default: if ((int)type != 32) { if ((int)type != 64) { break; } return damage.m_frost; } return damage.m_fire; case 0: return damage.m_blunt; case 1: return damage.m_slash; case 3: return damage.m_pierce; case 2: break; } } else { if ((int)type == 128) { return damage.m_lightning; } if ((int)type == 256) { return damage.m_poison; } if ((int)type == 512) { return damage.m_spirit; } } return 0f; } private static string Title(string text) { return string.Format("<size={0}><color={1}>{2}</color></size>", 20, "#ffa626", text); } private static string Row(string label, string value) { return label + " <color=#ffa500>" + value + "</color>"; } private static string Muted(string text) { return "<color=#9a9a9a>" + text + "</color>"; } private static string Number(float value, string format = "0.#") { return value.ToString(format, Numbers); } private static string Change(float multiplier) { float num = (multiplier - 1f) * 100f; if (Mathf.Abs(num) < 0.05f) { return "0%"; } return ((num > 0f) ? "+" : "") + Number(num) + "%"; } private static string Duration(float seconds) { TimeSpan timeSpan = TimeSpan.FromSeconds(Mathf.CeilToInt(Mathf.Max(seconds, 0f))); if (!(timeSpan.TotalHours >= 1.0)) { return $"{timeSpan.Minutes}:{timeSpan.Seconds:00}"; } return $"{(int)timeSpan.TotalHours}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00}"; } } internal static class AffixDisplayValues { private static readonly Regex Arguments = new Regex("\\{(\\d+)(?::([^}]+))?\\}"); internal static readonly Regex Numbers = new Regex("(?<![\\w#.])[+-]?\\d+(?:[.,]\\d+)?(?:[Ee][+-]?\\d+)?(?![\\w.])"); private static readonly FieldRef<bool> InConversion = AccessTools.StaticFieldRefAccess<bool>(AccessTools.Field(typeof(AddSkillLevel_Skills_GetSkillFactor_Patch), "_inSkillsAsSkills")); internal static bool IsDropCount(string effectType) { if (!(effectType == MagicEffectType.IncreaseMiningDrop)) { return effectType == MagicEffectType.IncreaseTreeDrop; } return true; } internal static void Initialize() { string[] array = new string[2] { MagicEffectType.IncreaseMiningDrop, MagicEffectType.IncreaseTreeDrop }; for (int i = 0; i < array.Length; i++) { MagicItem.RegisterDisplayValues(array[i], (Func<float, object[]>)((float value) => new object[1] { Math.Max(0, (int)value) })); } MagicItem.RegisterDisplayValues(MagicEffectType.BlockAsDodgeAsBlock, (Func<float, object[]>)delegate(float value) { Player localPlayer = Player.m_localPlayer; return ((Object)(object)localPlayer == (Object)null) ? new object[3] { value, 0f, 0f } : new object[3] { value, (float)Converted(localPlayer, (SkillType)108, value), (float)Converted(localPlayer, (SkillType)6, value) }; }); MagicItem.RegisterDisplayValues(MagicEffectType.BlockAsWoodCuttingAndPickaxes, (Func<float, object[]>)delegate(float value) { Player localPlayer = Player.m_localPlayer; return new object[2] { value, (!((Object)(object)localPlayer == (Object)null)) ? (Converted(localPlayer, (SkillType)13, value) + Converted(localPlayer, (SkillType)12, value)) : 0 }; }); } private static int Converted(Player player, SkillType source, float value) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) bool flag = InConversion.Invoke(); InConversion.Invoke() = true; try { return (int)(((Character)player).GetSkills().GetSkillFactor(source) * value); } finally { InConversion.Invoke() = flag; } } internal static string Format(object value, string preferredFormat, CultureInfo culture) { if (value is float num) { return ((double)num).ToString("0.##", culture); } if (!(value is IFormattable formattable)) { return value.ToString(); } return formattable.ToString(preferredFormat, culture); } internal static string Number(string effectType, float value) { if (!IsDropCount(effectType)) { return Format(value, null, CultureInfo.CurrentCulture); } return Math.Max(0, (int)value).ToString(CultureInfo.CurrentCulture); } internal static string Generic(string effectType, string token) { float result; return Numbers.Replace(token, (Match match) => (!float.TryParse(match.Value.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out result)) ? match.Value : Number(effectType, result)); } internal static object[] FormatArguments(string template, object[] arguments) { object[] array = (object[])arguments.Clone(); foreach (Match item in Arguments.Matches(Localization.instance.Localize(template))) { int num = int.Parse(item.Groups[1].Value, CultureInfo.InvariantCulture); if (num < arguments.Length && arguments[num] is float) { array[num] = Format(arguments[num], item.Groups[2].Success ? item.Groups[2].Value : null, CultureInfo.CurrentCulture); } } return array; } } [HarmonyPatch(typeof(MagicItem), "FormatDisplayText")] internal static class AffixTextFormatting { private static void Prefix(string displayText, ref object[] args) { args = AffixDisplayValues.FormatArguments(displayText, args); } } [HarmonyPatch(typeof(MagicItem), "GetEffectTextGeneric")] internal static class AppliedAffixPreview { private static readonly Func<string, float, object[]> DisplayArguments = AccessTools.MethodDelegate<Func<string, float, object[]>>(AccessTools.Method(typeof(MagicItem), "GetDisplayArgs", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<string, object[], string> FormatText = AccessTools.MethodDelegate<Func<string, object[], string>>(AccessTools.Method(typeof(MagicItem), "FormatDisplayText", (Type[])null, (Type[])null), (object)null, true); private static bool Prefix(MagicItemEffectDefinition effectDef, ref string valueToken, ref string __result) { List<Match> list = AffixDisplayValues.Numbers.Matches(valueToken).Cast<Match>().ToList(); List<float> list2 = new List<float>(); foreach (Match item in list) { if (float.TryParse(item.Value.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { list2.Add(result); } } if (list2.Count == 0 || list2.Count != list.Count) { valueToken = AffixDisplayValues.Generic(effectDef.Type, valueToken); return true; } object[] array = DisplayArguments(effectDef.Type, 1f); object[] array2 = DisplayArguments(effectDef.Type, 2f); List<object[]> perValue = list2.Select((float value) => DisplayArguments(effectDef.Type, value)).ToList(); object[] array3 = new object[array.Length]; string input = valueToken; for (int i = 0; i < array3.Length; i++) { if ((i < array2.Length && object.Equals(array[i], array2[i])) || perValue.Any((object[] shown) => i >= shown.Length)) { array3[i] = array[i]; continue; } int next = 0; array3[i] = AffixDisplayValues.Numbers.Replace(input, (Match match) => AffixDisplayValues.Format(perValue[next++][i], null, CultureInfo.CurrentCulture)); } __result = FormatText(effectDef.DisplayText, array3); return false; } } [HarmonyPatch(typeof(MagicItem), "GetEffectDescription")] internal static class AppliedAffixDescription { private static void Postfix(MagicItemEffectDefinition effectDef, float value, ref string __result) { __result = __result.Replace("<b><color=yellow>" + value.ToString("0.#", CultureInfo.CurrentCulture) + "</color></b>", "<b><color=yellow>" + AffixDisplayValues.Number(effectDef.Type, value) + "</color></b>"); } } [HarmonyPatch] internal static class AffixReplacements { [HarmonyPatch(typeof(MagicItemEffectRequirements), "CheckItemTypeRequirements")] private static class SocketedBloodletting { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo methodInfo = AccessTools.Method(typeof(ItemDataExtensions), "HasMagicEffect", (Type[])null, (Type[])null); List<CodeInstruction> list = instructions.ToList(); int num = 0; for (int i = 1; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], methodInfo) && !(list[i - 1].opcode != OpCodes.Ldc_I4_0)) { list[i - 1].opcode = OpCodes.Ldc_I4_1; num++; } } if (num != 1) { throw new InvalidOperationException("Expected one rolled-only Bloodletting check in EpicLoot's item requirements."); } return list; } } private static readonly MethodInfo Available = AccessTools.Method(typeof(MagicItemEffectDefinitions), "GetAvailableEffects", (Type[])null, (Type[])null); private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(AugmentHelper), "GetAvailableAugments", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(LootRoller), "RollAugmentEffects", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(EnchantingUIController), "GetApplyableRunesforItem", (Type[])null, (Type[])null); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, Available)) { bool augmentHelper = __originalMethod.DeclaringType == typeof(AugmentHelper); bool runeEtch = __originalMethod.Name == "GetApplyableRunesforItem"; CodeInstruction val = new CodeInstruction(augmentHelper ? OpCodes.Ldarg_0 : ((__originalMethod.DeclaringType == typeof(LootRoller)) ? OpCodes.Ldarg_2 : OpCodes.Ldarg_1), (object)null); val.labels.AddRange(instruction.labels); instruction.labels.Clear(); yield return val; if (augmentHelper) { yield return new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(AugmentRecipe), "EffectIndex")); } instruction.operand = AccessTools.Method(typeof(AffixReplacements), runeEtch ? "RuneEffects" : "AugmentEffects", (Type[])null, (Type[])null); replacements++; } yield return instruction; } if (replacements != 1) { throw new InvalidOperationException("Expected one replacement effect check in " + __originalMethod.Name); } } internal static List<MagicItemEffectDefinition> AugmentEffects(ItemData item, MagicItem magicItem, int ignoredIndex, bool lootRoll, bool augmentRoll, bool runeRoll, int selectedIndex) { MagicItem magicItem2 = ItemDataExtensions.GetMagicItem(item); List<SocketedEffect> sockets = magicItem.Sockets; List<SocketedEffect> sockets2 = magicItem2?.Sockets; List<SocketedEffect> sockets3 = (magicItem.Sockets = new List<SocketedEffect>()); if (magicItem2 != null && magicItem2 != magicItem) { magicItem2.Sockets = sockets3; } try { return ReplacementEffects(item, magicItem, selectedIndex, lootRoll: true, augmentRoll: true, runeRoll: false, selectedIndex); } finally { magicItem.Sockets = sockets; if (magicItem2 != null && magicItem2 != magicItem) { magicItem2.Sockets = sockets2; } } } internal static List<MagicItemEffectDefinition> ReplacementEffects(ItemData item, MagicItem magicItem, int ignoredIndex, bool lootRoll, bool augmentRoll, bool runeRoll, int selectedIndex) { string selectedType = ((selectedIndex >= 0 && selectedIndex < magicItem.Effects.Count) ? magicItem.Effects[selectedIndex].EffectType : null); List<MagicItemEffectDefinition> availableEffects = MagicItemEffectDefinitions.GetAvailableEffects(item, magicItem, selectedIndex, lootRoll, augmentRoll, runeRoll); availableEffects.RemoveAll((MagicItemEffectDefinition definition) => definition.Type != selectedType && SocketConflicts.ReplacementConflict(definition.Type, magicItem, selectedIndex) != null); if (selectedType != null && MagicItemEffectDefinitions.IsValuelessEffect(selectedType)) { availableEffects.RemoveAll((MagicItemEffectDefinition definition) => definition.Type == selectedType); } return availableEffects; } private static List<MagicItemEffectDefinition> RuneEffects(ItemData item, MagicItem magicItem, int ignoredIndex, bool lootRoll, bool augmentRoll, bool runeRoll, string selectedEffect) { return ReplacementEffects(item, magicItem, ignoredIndex, lootRoll, augmentRoll, runeRoll, magicItem.Effects.FindIndex((MagicItemEffect effect) => effect.EffectType == selectedEffect)); } internal static bool PreservesRequirements(ItemData item, MagicItem magicItem, MagicItemEffectDefinition candidate, string replacedType) { List<string> first = magicItem.Effects.Select((MagicItemEffect effect) => effect.EffectType).ToList(); List<string> second = (from effect in magicItem.GetSocketedEffects() select effect.EffectType).ToList(); HashSet<string> after = new HashSet<string>(first.Concat(second)) { candidate.Type }; HashSet<string> before = new HashSet<string>(first.Concat(second)); if (replacedType != null) { before.Add(replacedType); } if (!Satisfied(item, candidate.Type, after)) { return false; } return first.Concat(from socket in magicItem.Sockets where socket?.Effect != null && (int)socket.ShardType == 97 select socket.Effect.EffectType).Distinct().All((string effectType) => Satisfied(item, effectType, after) || !Satisfied(item, effectType, before)); } private static bool Satisfied(ItemData item, string effectType, HashSet<string> present) { MagicItemEffectDefinition val = default(MagicItemEffectDefinition); if (!MagicItemEffectDefinitions.TryGet(effectType, ref val)) { return true; } MagicItemEffectRequirements requirements = val.Requirements; Attack attack = item.m_shared.m_attack; Attack secondaryAttack = item.m_shared.m_secondaryAttack; bool flag = attack.m_attackHealth > 0f || secondaryAttack.m_attackHealth > 0f || attack.m_attackHealthPercentage > 0f || secondaryAttack.m_attackHealthPercentage > 0f || present.Contains(MagicEffectType.Bloodlust); if (requirements.ItemUsesHealthOnAttack.HasValue && requirements.ItemUsesHealthOnAttack.Value != flag) { return false; } return requirements.MustHaveEffectTypes.All((string required) => present.Contains(required) || (required == MagicEffectType.Throwable && (int)item.m_shared.m_skillType == 5)); } } [HarmonyPatch(typeof(Character), "UpdateWalking")] internal static class AirborneIceMovement { private static bool OnSurface(bool slippery, Character character) { if (slippery) { if (character.IsPlayer()) { return character.IsOnGround(); } return true; } return false; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); FieldInfo slipping = AccessTools.Field(typeof(Character), "m_slipping"); (CodeInstruction instruction, int index)[] array = (from entry in list.Select((CodeInstruction instruction, int index) => (instruction: instruction, index: index)) where CodeInstructionExtensions.StoresField(entry.instruction, slipping) select entry).ToArray(); if (array.Length != 1) { throw new InvalidOperationException("Character's walking slipping-state assignment changed."); } int item = array[0].index; CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null); val.labels.AddRange(list[item].labels); list[item].labels.Clear(); list.InsertRange(item, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2] { val, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AirborneIceMovement), "OnSurface", (Type[])null, (Type[])null)) }); return list; } } internal static class AmmoConservationPerArrow { [HarmonyPatch(typeof(UseAmmoTranspilerPatch), "CustomRemoveItem")] private static class SpendAmmunition { private static bool Prefix(Inventory inventory, ItemData item, int amount, ref bool __result) { conservedAmmo = null; conservedLoadedArrow = false; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || inventory != ((Humanoid)localPlayer).GetInventory() || item == null) { return true; } float num = Mathf.Clamp01(PlayerExtensions.GetTotalActiveMagicEffectValue(localPlayer, MagicEffectType.AmmoConservation, 0.01f, (ItemData)null)); if (num <= 0f) { return true; } if (MultiShot.IsTripleShotActive) { amount *= MultiShot.ShotProjectiles; MultiShot.IsTripleShotActive = false; MultiShot.ShotProjectiles = 0; } int num2 = Math.Min(amount, item.m_stack); int num3 = 0; conservedAmmo = item; for (int i = 0; i < num2; i++) { bool flag = Random.value < num; if (i == 0) { conservedLoadedArrow = flag; } if (!flag) { num3++; } } __result = num3 == 0 || inventory.RemoveItem(item, num3); return false; } } [HarmonyPatch(typeof(AmmoConservation_Attack_UseAmmo_Patch), "Postfix")] private static class FinishConservation { private static bool Prefix(Attack __0, bool __1, ItemData __2) { Player localPlayer = Player.m_localPlayer; bool flag = (Object)(object)localPlayer != (Object)null && (Object)(object)GameFields.AttackCharacter.Invoke(__0) == (Object)(object)localPlayer && __2 != null && __2 == conservedAmmo; if (__1 && flag && conservedLoadedArrow) { ItemData weapon = __0.GetWeapon(); if (weapon != null && weapon.m_shared.m_attack.m_requiresReload) { SkipReload.Invoke() = true; } } conservedAmmo = null; conservedLoadedArrow = false; return !flag; } } private static ItemData conservedAmmo; private static bool conservedLoadedArrow; private static readonly FieldRef<bool> SkipReload = AccessTools.StaticFieldRefAccess<bool>(AccessTools.Field(typeof(AmmoConservation), "skipReload")); } internal static class AmmoCountBadge { private sealed class BarState { internal Player Player; internal ItemData Ammo; internal object FirstElement; internal int ElementCount; internal int InventoryVersion = -1; internal int ConfigurationVersion = -1; internal bool AfterReset; internal bool Conjuring; internal readonly List<(ItemData Item, Vector2i Position)> Items = new List<(ItemData, Vector2i)>(); } private const float IconGap = 2f; private static readonly FieldRef<HotkeyBar, object> Elements = AccessTools.FieldRefAccess<HotkeyBar, object>("m_elements"); private static readonly ConditionalWeakTable<HotkeyBar, BarState> Bars = new ConditionalWeakTable<HotkeyBar, BarState>(); private static readonly Dictionary<string, string> Counts = new Dictionary<string, string>(); private static FieldRef<bool> reset; private static int inventoryVersion; private static int configurationVersion; private static int countedVersion = -1; private static Inventory countedInventory; internal static void Initialize(IntegrationPatches harmony, ManualLogSource log) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_0137: Expected O, but got Unknown //IL_0137: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown if (PluginIds.TryGet("aedenthorn.AmmoCount", out var plugin)) { Type type = AccessTools.Inner(((object)plugin.Instance).GetType(), "HotkeyBar_Update_Patch"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "CheckAmmo", new Type[2] { typeof(ItemData), typeof(GameObject) }, (Type[])null)); MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.Method(type, "Postfix", new Type[2] { typeof(HotkeyBar), typeof(List<ItemData>) }, (Type[])null)); if (methodInfo == null || !methodInfo.IsStatic || methodInfo2 == null) { throw new InvalidOperationException("Ammo Count's badge check moved."); } reset = AccessTools.StaticFieldRefAccess<bool>(AccessTools.Field(((object)plugin.Instance).GetType(), "reset")); harmony.Patch(methodInfo, new HarmonyMethod(typeof(AmmoCountBadge), "OnlyOnWeapons", (Type[])null), new HarmonyMethod(typeof(AmmoCountBadge), "LayOut", (Type[])null), new HarmonyMethod(typeof(AmmoCountBadge), "CountEveryStack", (Type[])null)); harmony.Patch(methodInfo2, new HarmonyMethod(typeof(AmmoCountBadge), "RefreshNeeded", (Type[])null)); harmony.Patch(AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null), null, new HarmonyMethod(typeof(AmmoCountBadge), "InventoryChanged", (Type[])null)); EventHandler<SettingChangedEventArgs> changed = delegate { configurationVersion++; }; IntegrationChanges.Defer(delegate { plugin.Instance.Config.SettingChanged += changed; }, delegate { plugin.Instance.Config.SettingChanged -= changed; }); log.LogInfo((object)"Ammo Count's badge shows only on weapons, counts every stack of the ammunition, and scales with its slot with the icon beside the count."); } } private static void InventoryChanged() { inventoryVersion++; } private static bool RefreshNeeded(HotkeyBar __0, List<ItemData> __1) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return true; } BarState value = Bars.GetValue(__0, (HotkeyBar _) => new BarState()); IList list = (IList)Elements.Invoke(__0); object obj = ((list.Count == 0) ? null : list[0]); ItemData ammoItem = ((Humanoid)localPlayer).GetAmmoItem(); bool flag = reset.Invoke(); bool flag2 = PlayerExtensions.HasActiveMagicEffect(localPlayer, MagicEffectType.ConjuredArrows); bool flag3 = (Object)(object)value.Player != (Object)(object)localPlayer || value.Ammo != ammoItem || value.Conjuring != flag2 || value.InventoryVersion != inventoryVersion || value.ConfigurationVersion != configurationVersion || value.FirstElement != obj || value.ElementCount != list.Count || value.Items.Count != __1.Count || flag || value.AfterReset; if (!flag3) { for (int num = 0; num < __1.Count; num++) { if (value.Items[num].Item != __1[num] || value.Items[num].Position != __1[num].m_gridPos) { flag3 = true; break; } } } if (!flag3) { return false; } value.Player = localPlayer; value.Ammo = ammoItem; value.Conjuring = flag2; value.InventoryVersion = inventoryVersion; value.ConfigurationVersion = configurationVersion; value.FirstElement = obj; value.ElementCount = list.Count; value.AfterReset = flag; value.Items.Clear(); foreach (ItemData item in __1) { value.Items.Add((item, item.m_gridPos)); } return true; } private static bool OnlyOnWeapons(ItemData __0, GameObject __1) { float num = default(float); if (__0.IsWeapon() && !ConjuredArrows.TryGetShotCost(__0, ref num)) { return true; } __1.SetActive(false); return false; } private static IEnumerable<CodeInstruction> CountEveryStack(IEnumerable<CodeInstruction> instructions) { FieldInfo stack = AccessTools.Field(typeof(ItemData), "m_stack"); MethodInfo text = AccessTools.Method(typeof(int), "ToString", Type.EmptyTypes, (Type[])null); List<CodeInstruction> code = instructions.ToList(); List<int> list = (from index in Enumerable.Range(0, code.Count - 1) where CodeInstructionExtensions.LoadsField(code[index], stack, true) && CodeInstructionExtensions.Calls(code[index + 1], text) select index).ToList(); if (list.Count != 1) { throw new InvalidOperationException("Ammo Count's count changed."); } int num = list[0]; code[num].opcode = OpCodes.Call; code[num].operand = AccessTools.Method(typeof(AmmoCountBadge), "Total", (Type[])null, (Type[])null); code[num + 1].opcode = OpCodes.Nop; code[num + 1].operand = null; return code; } private static string Total(ItemData ammo) { Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (countedInventory != inventory || countedVersion != inventoryVersion) { Counts.Clear(); countedInventory = inventory; countedVersion = inventoryVersion; } string name = ammo.m_shared.m_name; if (!Counts.TryGetValue(name, out var value)) { value = (Counts[name] = inventory.CountItems(name, -1, false).ToString()); } return value; } private static void LayOut(GameObject __1) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) if (!__1.activeSelf) { return; } if (__1.transform.localScale != Vector3.one) { __1.transform.localScale = Vector3.one; } Transform obj = __1.transform.Find("Icon"); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if (val != null) { TMP_Text component = ((Component)__1.transform.Find("Text")).GetComponent<TMP_Text>(); RectTransform rectTransform = component.rectTransform; float x = rectTransform.anchoredPosition.x; Rect rect = rectTransform.rect; float num = x + ((Rect)(ref rect)).xMax - component.preferredWidth; float num2 = num - 2f; rect = val.rect; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(num2 - ((Rect)(ref rect)).width / 2f, val.anchoredPosition.y); if (val.anchoredPosition != val2) { val.anchoredPosition = val2; } } } } [HarmonyPatch(typeof(SE_CustomFinder), "UpdateStatusEffect")] internal static class AndvaranautTracking { private const float ScanInterval = 1f; private static readonly FieldRef<List<Beacon>> Beacons = AccessTools.StaticFieldRefAccess<List<Beacon>>(AccessTools.Field(typeof(Beacon), "m_instances")); private static SE_CustomFinder finder; private static bool hasTarget; private static bool beyondSearchRadius; private static Vector3 targetPosition; private static float scanTimer; private static float sincePing; internal static string ModeLabel(StatusEffect effect) { if (!((Object)(object)effect != (Object)(object)finder) && hasTarget) { if (!beyondSearchRadius) { return "Near"; } return "Far"; } return null; } private static bool IsLocalRing(SE_CustomFinder ring) { if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)((StatusEffect)ring).m_character == (Object)(object)Player.m_localPlayer) { return ring.RequiredComponentTypes?.Contains(typeof(TreasureMapChest)) ?? false; } return false; } internal static void RefreshTarget() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)finder == (Object)null) && IsLocalRing(finder)) { Player localPlayer = Player.m_localPlayer; FindTarget(localPlayer, ((Component)localPlayer).transform.position); beyondSearchRadius = hasTarget && Utils.DistanceXZ(((Component)localPlayer).transform.position, targetPosition) > Plugin.AndvaranautSearchRadius.Value; scanTimer = 0f; } } private static bool Prefix(SE_CustomFinder __instance) { return !IsLocalRing(__instance); } private static void Postfix(SE_CustomFinder __instance, float dt) { //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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (!IsLocalRing(__instance)) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)__instance != (Object)(object)finder) { finder = __instance; hasTarget = false; scanTimer = 1f; sincePing = Plugin.AndvaranautSlowestPing.Value; } sincePing += dt; Vector3 position = ((Component)localPlayer).transform.position; scanTimer += dt; if (scanTimer >= 1f) { scanTimer = 0f; FindTarget(localPlayer, position); } if (hasTarget) { float num = Utils.DistanceXZ(position, targetPosition); beyondSearchRadius = num > Plugin.AndvaranautSearchRadius.Value; if (sincePing >= Interval(num) && (!beyondSearchRadius || IsFacing(localPlayer, position))) { Ping((SE_Finder)(object)__instance, localPlayer); } } } private static bool IsFacing(Player player, Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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) Vector3 lookDir = ((Character)player).GetLookDir(); Vector3 val = targetPosition - position; lookDir.y = 0f; val.y = 0f; float value = Plugin.AndvaranautFacingAngle.Value; if (value > 0f && ((Vector3)(ref lookDir)).sqrMagnitude >= 0.0001f) { return Vector3.Angle(lookDir, val) <= value; } return false; } private static float Interval(float distance) { float value = Plugin.AndvaranautSearchRadius.Value; float value2 = Plugin.AndvaranautMaxRange.Value; float value3 = Plugin.AndvaranautSlowestPing.Value; float value4 = Plugin.AndvaranautSearchRadiusPing.Value; if (distance <= value) { return Mathf.Lerp(Plugin.AndvaranautNearestPing.Value, value4, Mathf.InverseLerp(0f, value, distance)); } if (value2 <= value) { return value3; } return Mathf.Lerp(value4, value3, Mathf.InverseLerp(value, value2, distance)); } private static void Ping(SE_Finder ring, Player player) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)player).transform; ZNetView.m_forceDisableInit = true; try { ring.m_pingEffectFar.Create(transform.position, transform.rotation, transform, 1f, -1, ((Character)player).GetZDOID()); } finally { ZNetView.m_forceDisableInit = false; } sincePing = 0f; } private static void FindTarget(Player player, Vector3 position) { //IL_0079: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_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_0077: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) hasTarget = false; float nearest = ((Plugin.AndvaranautMaxRange.Value > 0f) ? Plugin.AndvaranautMaxRange.Value : float.MaxValue); AdventureSaveData adventureSaveData = PlayerExtensions_Adventure.GetAdventureSaveData(player); long playerID = player.GetPlayerID(); foreach (TreasureMapChestInfo unfoundTreasureChest in adventureSaveData.GetUnfoundTreasureChests()) { if (!LocateChest(unfoundTreasureChest, playerID, out var located)) { located = SerializableVector3.op_Implicit(unfoundTreasureChest.Position) + SerializableVector3.op_Implicit(unfoundTreasureChest.MinimapCircleOffset); } Consider(located, position, ref nearest); } foreach (BountyInfo inProgressBounty in adventureSaveData.GetInProgressBounties()) { if (!inProgressBounty.Slain) { if (!LocateBounty(inProgressBounty.ID, position, out var located2)) { located2 = SerializableVector3.op_Implicit(inProgressBounty.Position) + SerializableVector3.op_Implicit(inProgressBounty.MinimapCircleOffset); } Consider(located2, position, ref nearest); } } } private static void Consider(Vector3 candidate, Vector3 position, ref float nearest) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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_0018: Unknown result type (might be due to invalid IL or missing references) float num = Utils.DistanceXZ(position, candidate); if (!(num >= nearest)) { nearest = num; hasTarget = true; targetPosition = candidate; } } private static bool LocateChest(TreasureMapChestInfo map, long playerId, out Vector3 located) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0092: Unknown result type (might be due to invalid IL or missing references) foreach (Beacon item in Beacons.Invoke()) { TreasureMapChest val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<TreasureMapChest>() : null); ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null); if (!((Object)(object)val2 == (Object)null) && val2.IsValid() && val.Interval == map.Interval && val.Biome == map.Biome && val2.GetZDO().GetLong("creator", 0L) == playerId) { located = ((Component)val).transform.position; return true; } } located = default(Vector3); return false; } private static bool LocateBounty(string bountyId, Vector3 position, out Vector3 located) { //IL_0007: 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_0082: 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) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; located = default(Vector3); foreach (Character allCharacter in Character.GetAllCharacters()) { ZNetView val = (((Object)(object)allCharacter != (Object)null && !allCharacter.IsDead()) ? ((Component)allCharacter).GetComponent<ZNetView>() : null); if (!((Object)(object)val == (Object)null) && val.IsValid() && BountyCreature.IsMainTarget(val.GetZDO()) && !(val.GetZDO().GetString(BountyCreature.IdKey, "") != bountyId)) { float num2 = Utils.DistanceXZ(position, ((Component)allCharacter).transform.position); if (!(num2 >= num)) { num = num2; located = ((Component)allCharacter).transform.position; } } } return num < float.MaxValue; } } [HarmonyPatch(typeof(StatusEffect), "GetIconText")] internal static class AndvaranautModeLabel { private static void Postfix(StatusEffect __instance, ref string __result) { __result = AndvaranautTracking.ModeLabel(__instance) ?? __result; } } internal static class ArmorDisplay { internal static void Initialize(IntegrationPatches harmony) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown if (PluginIds.TryGet("MK_BetterUI", out var plugin)) { Type type = ((object)plugin.Instance).GetType().Assembly.GetType("BetterUI.GameClasses.BetterInventoryGui"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "PatchArmor", (Type[])null, (Type[])null)); if (methodInfo == n
patchers/EpicLootProgressionFix.Preloader.dll
Decompiled 16 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading.Tasks; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Mono.Cecil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EpicLootProgressionFix.Preloader { public static class DiscordConnectorFileLog { private const string HarmonyId = "valheim.epiclootprogressionfix.discord-file-log"; private static readonly object writes = new object(); private static FieldInfo logPathField; private static FieldInfo loggerField; public static IEnumerable<string> TargetDLLs => Array.Empty<string>(); public static void Patch(AssemblyDefinition assembly) { } public static void Initialize() { AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; } private static void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) { //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown if (args.LoadedAssembly.GetName().Name != "DiscordConnector") { return; } Type? type = args.LoadedAssembly.GetType("DiscordConnector.Common.VdcLogger", throwOnError: true); FieldInfo fieldInfo = AccessTools.Field(type, "s_logFilePath"); FieldInfo fieldInfo2 = AccessTools.Field(type, "s_logger"); MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "LogToFileAsync", new Type[2] { typeof(string), typeof(string) }, (Type[])null); if (fieldInfo?.FieldType != typeof(string) || fieldInfo2?.FieldType != typeof(ManualLogSource) || methodInfo?.ReturnType != typeof(Task)) { throw new InvalidOperationException("DiscordConnector's file logger changed."); } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo != null) { foreach (Patch prefix in patchInfo.Prefixes) { if (prefix.owner == "valheim.epiclootprogressionfix.discord-file-log") { return; } } } logPathField = fieldInfo; loggerField = fieldInfo2; new Harmony("valheim.epiclootprogressionfix.discord-file-log").Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(DiscordConnectorFileLog), "QueueWrite", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.CreateLogSource("Progression Fix preloader").LogInfo((object)"DiscordConnector file writes are serialized before startup."); } private static bool QueueWrite(string severity, string message, ref Task __result) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown __result = Write((string)logPathField.GetValue(null), (ManualLogSource)loggerField.GetValue(null), severity, message); return false; } private static Task Write(string path, ManualLogSource log, string severity, string message) { lock (writes) { try { using StreamWriter streamWriter = new StreamWriter(path, append: true); streamWriter.WriteLine($"{DateTime.Now} [{severity}]: {message}"); } catch (Exception ex) { log.LogError((object)("Error writing to log file: " + ex.Message)); } } return Task.CompletedTask; } } }