Decompiled source of BetterTooltips v0.1.1
plugins/BetterTooltips/BetterTooltips.dll
Decompiled an hour ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Logging; using Burst2Flame; using Burst2Flame.Observable; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("BetterTooltips")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Melhora textos, tooltips e descrições do Stolen Realm.")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1")] [assembly: AssemblyProduct("BetterTooltips")] [assembly: AssemblyTitle("BetterTooltips")] [assembly: AssemblyVersion("0.1.1.0")] namespace BetterTooltips { [BepInPlugin("com.gumatos.bettertooltips", "Better Tooltips", "0.1.1")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log { get; private set; } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Better Tooltips carregado."); AplicarPatches(); } private static void AplicarPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown Harmony val = new Harmony("com.gumatos.bettertooltips"); List<string> list = new List<string>(); int num = 0; int num2 = 0; int num3 = 0; Type[] types; try { types = typeof(Plugin).Assembly.GetTypes(); } catch (Exception ex) { Log.LogError((object)("BetterTooltips: nao deu para listar os tipos do mod — nenhum gancho aplicado: " + ex)); return; } foreach (Type type in types) { if (EhClasseDeGancho(type)) { num++; try { int num4 = val.CreateClassProcessor(type).Patch()?.Count ?? 0; num3 += num4; num2++; Log.LogInfo((object)("BetterTooltips: gancho aplicado — " + type.Name + " (" + num4 + " metodo(s) de patch).")); } catch (Exception ex2) { list.Add(type.Name); Log.LogError((object)("BetterTooltips: FALHA ao aplicar o gancho " + type.Name + " — " + ex2.Message)); } } } string text = "BetterTooltips: patches Harmony aplicados (" + num2 + "/" + num + " ganchos, " + num3 + " metodos de patch)."; if (list.Count == 0) { Log.LogInfo((object)text); } else { Log.LogError((object)(text + " GANCHOS QUE FALHARAM: " + string.Join(", ", list.ToArray()) + ". O mod continua de pe, mas o recurso que dependia deles nao existe nesta sessao.")); } } private static bool EhClasseDeGancho(Type tipo) { try { if (tipo == null || !tipo.IsClass) { return false; } return tipo.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0; } catch (Exception) { return false; } } } } namespace BetterTooltips.Patches { public static class GlobulePatch { private static readonly HashSet<string> GlobuleKeys = new HashSet<string> { "Heals for 50% of Max Health", "Restores 50% of Max Mana", "Cleanses all debuffs", "Grants an additional Action Point", "Lowers Cooldowns by 1", "Increases all damage by 10%", "Increases damage and summon damage by 10%" }; private static readonly HashSet<string> PickupKeys = new HashSet<string> { "Restores 10% health", "Restores 15% health", "Restores 20% health", "Restores 10% mana", "Restores 15% mana", "Restores 20% mana" }; private const string PrefixoSustenance = "Consuming any Globule heals you for "; private static Character _cacheChar; private static float _cachePct; private static List<string> _cacheTiers; private static float _cacheQuando = -999f; private const float TtlCache = 1f; private static readonly HashSet<string> _marcas = new HashSet<string>(); public static bool EhGlobule(string texto) { if (texto != null) { if (!GlobuleKeys.Contains(texto)) { return PickupKeys.Contains(texto); } return true; } return false; } public static string FraseSustenance(string chaveDaTooltip) { try { if (!EhGlobule(chaveDaTooltip)) { return ""; } Character val = ShrineAuraPatch.ReceptorDaTooltip(); if (val == null) { Marca("sem numero: nenhum personagem em foco"); return ""; } PctDasTiersAtivas(val, out var pct, out var tiers); if (pct <= 0f || tiers.Count == 0) { Marca("'" + chaveDaTooltip + "': " + val.CharacterName + " nao tem Sustenance ativa -> sem numero"); return ""; } float maxHealth = val.MaxHealth; float maxMana = val.MaxMana; if (maxHealth <= 0f && maxMana <= 0f) { Marca("sem numero: personagem sem MaxHealth/MaxMana"); return ""; } string text = ((tiers.Count == 1) ? tiers[0] : string.Join(" and ", tiers.ToArray())); string text2 = (PickupKeys.Contains(chaveDaTooltip) ? "Picking this up also heals you for " : "Consuming a Globule also heals you for "); string text3 = text2 + pct.ToString("0.#") + "% of your Max Health and Max Mana (" + text + "): " + (maxHealth * pct / 100f).ToString("0.#") + " health and " + (maxMana * pct / 100f).ToString("0.#") + " mana with your current pools."; Marca("'" + chaveDaTooltip + "': " + val.CharacterName + " " + text + " = " + pct.ToString("0.#") + "% -> " + text3); return text3; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Globule RV-28] frase do Sustenance falhou (tooltip intacto): " + ex.GetType().Name + ": " + ex.Message)); return ""; } } private static void PctDasTiersAtivas(Character personagem, out float pct, out List<string> tiers) { if (_cacheChar == personagem && _cacheTiers != null && Time.realtimeSinceStartup - _cacheQuando < 1f) { pct = _cachePct; tiers = _cacheTiers; return; } pct = 0f; tiers = new List<string>(); List<SkillInfo> skills = personagem.Skills; if (skills != null) { foreach (SkillInfo item in skills) { if (!((Object)(object)item == (Object)null) && !string.IsNullOrEmpty(item.Description) && TentaLerPct(item.Description, out var pct2) && !(pct2 <= 0f)) { pct += pct2; tiers.Add(string.IsNullOrEmpty(item.SkillName) ? "(sem nome)" : item.SkillName); } } } _cacheChar = personagem; _cachePct = pct; _cacheTiers = tiers; _cacheQuando = Time.realtimeSinceStartup; } private static bool TentaLerPct(string descricao, out float pct) { pct = 0f; int num = descricao.IndexOf("Consuming any Globule heals you for ", StringComparison.Ordinal); if (num < 0) { return false; } num += "Consuming any Globule heals you for ".Length; int num2 = descricao.IndexOf('%', num); if (num2 < 0) { return false; } string text = descricao.Substring(num, num2 - num).Trim(); if (text.Length > 0) { return float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out pct); } return false; } private static void Marca(string linha) { try { if (_marcas.Count < 200 && _marcas.Add(linha)) { Plugin.Log.LogInfo((object)("[Globule RV-28] " + linha)); } } catch { } } } [HarmonyPatch(typeof(OptionsManager), "Localize")] public static class LocalizePatch { [HarmonyPatch] internal static class CorEOrdemDoTooltip { private static bool _diagnosticadoCor; private static readonly Type[] AssinaturaDoShowTooltip = new Type[13] { typeof(string), typeof(string), typeof(Sprite), typeof(string), typeof(TooltipOffsetInfo), typeof(Color), typeof(Vector3?), typeof(bool), typeof(bool), typeof(float), typeof(ControlGlyphInfo?), typeof(string), typeof(bool) }; private static MethodBase TargetMethod() { try { MethodInfo methodInfo = AccessTools.Method(typeof(Tooltip), "ShowTooltip", AssinaturaDoShowTooltip, (Type[])null); if (methodInfo != null) { return methodInfo; } Plugin.Log.LogError((object)"BetterTooltips: Tooltip.ShowTooltip com a assinatura de 13 parametros NAO foi encontrado — o gancho de cor/ordem do tooltip NAO sera aplicado nesta sessao (nunca um metodo escolhido por engano)."); return null; } catch (Exception ex) { Plugin.Log.LogError((object)("BetterTooltips: falha ao resolver Tooltip.ShowTooltip pela lista de tipos — gancho de cor/ordem NAO aplicado: " + ex.Message)); return null; } } private static void Prefix(ref string description) { string text = description; try { if (string.IsNullOrEmpty(description)) { return; } string text2 = (string.IsNullOrEmpty(_corEspecialDoJogo) ? "C8B090" : _corEspecialDoJogo); string text3 = CorDaLinhaDeAuras(); bool ultimo = string.Equals(text2, text3, StringComparison.OrdinalIgnoreCase); string bloco; bool num = TirarBloco(ref description, text3, ultimo, "Your active shrine auras:", out bloco); string bloco2; bool flag = TirarBloco(ref description, text2, ultimo: false, null, out bloco2); if (!num && !flag) { if (!_diagnosticadoCor) { _diagnosticadoCor = true; Plugin.Log.LogInfo((object)("BetterTooltips: ShowTooltip interceptado SEM o bloco (procurando <color=#" + text2 + "> e <color=#" + text3 + ">)")); } return; } if (!_diagnosticadoCor) { _diagnosticadoCor = true; Plugin.Log.LogInfo((object)("BetterTooltips: ShowTooltip interceptado, blocos movidos para o fim (nota #" + text2 + ", auras ativas #" + text3 + ")")); } string text4 = description.TrimEnd(); if (!string.IsNullOrEmpty(bloco2)) { text4 = text4 + "\n\n" + bloco2; } if (!string.IsNullOrEmpty(bloco)) { text4 = text4 + "\n\n" + bloco; } description = text4; } catch (Exception e) { description = text; RegistrarFalhaIgnorada("prefix de cor/ordem do Tooltip.ShowTooltip", e); } } private static bool TirarBloco(ref string corpo, string hex, bool ultimo, string exigir, out string bloco) { bloco = null; if (string.IsNullOrEmpty(corpo) || string.IsNullOrEmpty(hex)) { return false; } string value = "<color=#" + hex + ">"; int num = (ultimo ? corpo.LastIndexOf(value, StringComparison.Ordinal) : corpo.IndexOf(value, StringComparison.Ordinal)); while (num >= 0) { int num2 = corpo.IndexOf("</color>", num, StringComparison.Ordinal); if (num2 < 0) { return false; } int num3 = ((num > 0 && corpo[num - 1] == '\n') ? (num - 1) : num); int num4 = num2 + "</color>".Length; string text = corpo.Substring(num3, num4 - num3).TrimStart('\n').TrimEnd(); if (string.IsNullOrEmpty(exigir) || text.IndexOf(exigir, StringComparison.Ordinal) >= 0) { bloco = text; corpo = corpo.Remove(num3, num4 - num3); return true; } if (ultimo) { if (num == 0) { return false; } num = corpo.LastIndexOf(value, num - 1, StringComparison.Ordinal); } else { num = corpo.IndexOf(value, num + 1, StringComparison.Ordinal); } } return false; } } internal static string _corEspecialDoJogo; internal static string _corAuraDoJogo; private static readonly Dictionary<string, string> TextAppends = new Dictionary<string, string> { { "+ 20% Damage Reduction", "\n<color=#C8B090>Reduces all damage you take. Applied before Resistances and Armor.</color>" }, { "+ 16% Damage Reduction", "\n<color=#C8B090>Reduces all damage you take. Applied before Resistances and Armor.</color>" }, { "+ 12% Damage Reduction", "\n<color=#C8B090>Reduces all damage you take. Applied before Resistances and Armor.</color>" }, { "+ 8% Damage Reduction", "\n<color=#C8B090>Reduces all damage you take. Applied before Resistances and Armor.</color>" }, { "+ 4% Damage Reduction", "\n<color=#C8B090>Reduces all damage you take. Applied before Resistances and Armor.</color>" }, { "Summons a cloud of chaos that strikes 3 times. At every strike each damage type has a @50%@ chance to deal *0 damage.", "\n<color=#C8B090>The 50% roll only decides whether each element lands; the damage can still be dodged, and those are two separate rolls.</color>" }, { "Hurls a bolt of chaos dealing damage to a single target. Every damage type has a 50% chance to deal *0 damage.", "\n<color=#C8B090>The 50% roll only decides whether each element lands; the damage can still be dodged, and those are two separate rolls.</color>" }, { "Curses the target to take damage. Each element has a @50%@ chance to deal *0 damage every turn.", "\n<color=#C8B090>The 50% roll only decides whether each element lands; the damage can still be dodged, and those are two separate rolls.</color>" }, { "Summons a whirling blade of chaos in a line. Every damage type has a 50% chance to deal *0 damage.", "\n<color=#C8B090>The 50% roll only decides whether each element lands; the damage can still be dodged, and those are two separate rolls.</color>" }, { "Creates a clone of yourself that can cast your abilities. The Replicate Clone explodes for damage on death, each element has a @50%@ chance to deal *0 damage.", "\n<color=#C8B090>The 50% roll only decides whether each element lands; the damage can still be dodged, and those are two separate rolls.</color>" }, { "Increases damage dealt by 15%.", "\n<color=#C8B090>Stacks up to 10 times, one stack per ally killed.</color>" }, { "@Life steal@ increased.", "\n<color=#C8B090>Increases life steal by 50%. The aura reaches 3 hexes from its source and applies to allies inside it.</color>" }, { "@Life steal@ increased by 5%.", "\n<color=#C8B090>The aura reaches 3 hexes from its source and applies to allies inside it.</color>" }, { "@Life steal@ increased by 20%.", "\n<color=#C8B090>The aura reaches 3 hexes from its source and applies to allies inside it.</color>" }, { "@Life Steal@ increased by 5%.", "\n<color=#C8B090>The aura reaches 3 hexes from its source and applies to allies inside it.</color>" }, { "@Life steal@ increased by 50%.", "\n<color=#C8B090>The aura reaches 3 hexes from its source and applies to allies inside it.</color>" }, { "Grants 50% increased Armor, Magic Armor, and Max Health.", "\n<color=#C8B090>Lasts 2 turns.</color>" }, { "Increases Max Health and Damage by [0]%. Stacks.", "\n<color=#C8B090>Stacks up to 5 times.</color>" }, { "The next damage you deal causes a Thunder Bolt to strike your target. Stacks.", "\n<color=#C8B090>Stacks up to 8 times.</color>" }, { "Will leave when finished playing with you.", "\n<color=#C8B090>Invincible: it cannot be damaged.</color>" }, { "Decreases damage taken by 10%.", "\n<color=#C8B090>It reaches allies within 3 hexes of the seal's bearer.</color>" }, { "Cannot control your character. Increases damage by [0]%. Grants enrage.", "\n<color=#C8B090>Also increases the healing this character does by the same percentage.</color>" }, { "Damage increased by 10%, Range increased by 1 per stack.", "\n<color=#C8B090>Gains a stack at the end of your turn, and moving removes the status.\nAlso increases the healing this character does by the same percentage.</color>" }, { "Increases Damage Dealt and Max Health by 25%.", "\n<color=#C8B090>Current health is increased by the same percentage and goes back down when the status ends.\nAlso increases the healing this character does by the same percentage.</color>" }, { "Increases @Mana Costs@ by {4,20}%, power of all @Mana Abilites@ by {8,40}% and @Intelligence@ by {3,15}. <i><color=#808080>The energies of a Mana Spring swell within you!</i></color> ", "\n<color=#C8B090>Power of Mana increases the damage and healing of abilities that cost Mana.\nIt does not change how much Mana they cost, it does nothing for abilities that cost no Mana,\nand it does not change the duration or the bonuses of the statuses those abilities apply.</color>" }, { "Adds *0 lightning damage to your next basic attack. Can stack up to 10 times.", "\n<color=#C8B090>Lasts 2 turns.</color>" }, { "The Dead One's tether to this world wanes. Lasts [0] more round(s).", "\n<color=#C8B090>While the tether lasts the Dead One is Invincible: it takes no damage and harmful statuses cannot be applied to it.</color>" }, { "<i><color=#808080>You carry the Necronomicon!</i></color> Changes your @Skeletal Summons@ into something... stronger. Increases Summon Damage and Health by {5,25}%", "\n<color=#C8B090>Your skeletal summons are raised as Undead instead: Undead Berserker, Undead Ranger and Undead Wizard.</color>" }, { "Mana costs reduced.", "\n<color=#C8B090>Allies within 4 hexes of the caster: Muse I reduces Mana Costs by 10%, Muse II by a further 15%.</color>" }, { "<i><color=#808080>\"Look at me, I'm the alpha now!</i></color> Changes your @Nature Summons@ into @Pack Summons@. Increases Summon Damage and Health by {5,25}%", "\n<color=#C8B090>Pack summons are fixed instead of random: Timber Wolf, Tundra Wolf and Dire Wolf.</color>" }, { "Gain the ability to shapeshift into a White Dragonkin. <i><color=#808080>\"Imbued with a gentle radiance, it serves as a testament to the enduring strength of the forces of light\"</i></color> ", "\n<color=#C8B090>While transformed you gain: Dragonkin Holy Slash, Dragonkin Holy Breath and Dragonkin Holy Blast.</color>" }, { "Invincible.", "\n<color=#C8B090>Cannot take damage.</color>" }, { "Damage increased by 60%.", "\n<color=#C8B090>Also increases the healing this character does by the same percentage.</color>" }, { "Can only be harmed by destroying Soul Fetishes. Immune to movement imparing effects.", "\n<color=#C8B090>Also grants immunity to effects that Disable the character (they cannot perform actions).</color>" }, { "Targets in holy ground receive healing.", "\n<color=#C8B090>Heals each turn while the target stays in the holy ground.</color>" }, { "Healed.", "\n<color=#C8B090>Restores health. The amount depends on the effect that applied it.</color>" }, { "Immune to damage.", "\n<color=#C8B090>Also cannot be targeted by harmful skills, and harmful statuses do not apply.</color>" }, { "Damage and Health increased by 25% Size increased by 25%", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Damage increased by [0]%. Damage taken increased by [0]%. ", "\n<color=#C8B090>Base 25% damage and +25% damage taken; the value shown already includes the Shrine Effect Bonus. Also increases the healing you do by the same percentage.</color>" }, { "Damage increased by 5% per stack. Can stack up to 10 times.", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Immune to all movement impairing effects and knockback.", "\n<color=#C8B090>Also immune to being Chilled, Frozen, Stunned or Disabled.</color>" }, { "Dodging incoming attacks.", "\n<color=#C8B090>Guarantees a dodge (100% chance) against incoming attacks; each dodge spends one charge.</color>" }, { "Dodge chance increased by 8%.", "\n<color=#C8B090>Each stack adds another 8%; you gain one stack per strike.</color>" }, { "Damage increased by 50% ", "\n<color=#C8B090>Lasts 3 turns.\nAlso increases the healing you do by the same percentage.</color>" }, { "Increases your @Action Points@ by @1@. If you are using a One-Handed Sword, Axe, Hammer, Gun, or Wand. <i><color=#808080>You carry the Speed of the Ymir!</color></i>", "\n<color=#C8B090>Also works with Fist weapons, and it does not apply while wielding a two-handed weapon.</color>" }, { "Has a [0]% chance to resist any control effects.", "\n<color=#C8B090>Also halves the effect of Chilled.</color>" }, { "Damage and healing from non basic skills increased by 10%.", "\n<color=#C8B090>Each stack is consumed by your next damaging or healing skill.</color>" }, { "Increases @Damage@ by {6,30}%. Increases @Damage Taken@ by 10%. <i><color=#808080>\"Judge not a life until its final breath, for the Reaper's touch brings truth to death.\"</i></color> ", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Your first attack in battle deals 100% additional damage.", "\n<color=#C8B090>It also boosts your first healing, and the bonus is consumed by your first damaging or healing cast.</color>" }, { "Damage increased by 50%. Damage taken increased by 25%.", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Damage increased by 30%. Damage taken increased by 15%.", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Damage increased by 10%. Damage taken increased by 5%.", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Damage increased by 40%. Damage taken increased by 20%.", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Damage increased by 20%. Damage taken increased by 10%.", "\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Increases damage dealt and life steal by 25%.", "\n<color=#C8B090>Lasts 2 turns.\nAlso increases the healing you do by the same percentage.</color>" }, { "Increases damage dealt by 30%.", "\n<color=#C8B090>Lasts 3 turns.\nAlso increases the healing you do by the same percentage.</color>" }, { "Immune to poisoned.", "\n<color=#C8B090>Lasts 2 turns.</color>" }, { "Reduces @Range@ by @3@ per stack.", "\n<color=#C8B090>Only ranged attacks and skills lose range; melee range is unchanged.</color>" }, { "Enemies gain 2 stacks of poison.", "\n<color=#C8B090>Reapplied each turn to enemies in range of the flower.</color>" }, { "Critical Failure", "\n<color=#C8B090>All attributes reduced by 5%.</color>" }, { "Forced to attack the taunter. Damage reduced by 20%.", "\n<color=#C8B090>You can only target the taunter, and you are forced to attack them.</color>" }, { "Taunted.", "\n<color=#C8B090>You can only target the taunter, and you are forced to attack them.</color>" }, { "Stunned.", "\n<color=#C8B090>Cannot move or perform actions.</color>" }, { "@Cooldowns@ increased by @1@ turn.", "\n<color=#C8B090>Only abilities whose base cooldown is 2 or more are affected: 1-turn cooldowns stay at 1, and basic attacks are unaffected.</color>" }, { "Lowers movement and range by 1 and lowers Damage by 10% per stack.", "\n<color=#C8B090>Only ranged attacks and skills lose range; melee range is unchanged.</color>" }, { "Lowers movement and range by 1 and lowers Damage by 5% per stack.", "\n<color=#C8B090>Only ranged attacks and skills lose range; melee range is unchanged.</color>" }, { "Asleep.", "\n<color=#C8B090>Cannot move or perform actions; damage taken is increased by 50%.</color>" }, { "Shapeshifted into a box. Damage taken increased by 100%.", "\n<color=#C8B090>While in the box you cannot move or use abilities.</color>" }, { "Range is reduced by 6 Hexes.", "\n<color=#C8B090>Only ranged abilities are affected.</color>" }, { "Range is reduced by 4 Hexes.", "\n<color=#C8B090>Only ranged abilities are affected.</color>" }, { "Range is reduced by 2 Hexes.", "\n<color=#C8B090>Only ranged abilities are affected.</color>" }, { "Max Health reduced by 25%.", "\n<color=#C8B090>Current health is reduced by the same percentage and comes back when the status ends. This cannot kill.</color>" }, { "Reduces @Damage@ by @20%@ per stack.", "\n<color=#C8B090>Also reduces the healing this character does by the same percentage.</color>" }, { "Damage reduced by 50%.", "\n<color=#C8B090>Also reduces the healing this character does by the same percentage.</color>" }, { "Damage reduced by 20%.", "\n<color=#C8B090>Also reduces the healing this character does by the same percentage.</color>" }, { "Damage reduced by 5%.", "\n<color=#C8B090>Also reduces the healing this character does by the same percentage.</color>" }, { "Damage reduced by 25%.", "\n<color=#C8B090>Also reduces the healing this character does by the same percentage.</color>" }, { "Reduces Physical resistance by 25%.", "\n<color=#C8B090>Resistances reduce their damage type by the listed %. If a resistance goes negative, that damage type is amplified instead.</color>" }, { "Attackers lifesteal for [0]%.", "\n<color=#C8B090>Lasts 2 turns.</color>" }, { "Blind.", "\n<color=#C8B090>Skill range is reduced to 1 hex.</color>" }, { "*0 lightning damage dealt to enemies within the aura each time they perform an action.", "\n<color=#C8B090>The aura reaches 3 hexes from its source.</color>" }, { "Deals *0 cold damage per turn while in the aura.", "\n<color=#C8B090>The aura reaches 3 hexes from its source, and it damages enemies that start their turns inside it.</color>" }, { "[0] fire damage dealt to enemies within the aura.", "\n<color=#C8B090>The aura reaches 3 hexes from its source.</color>" }, { "*0 fire damage dealt to enemies within the aura.", "\n<color=#C8B090>The aura reaches 3 hexes from its source.</color>" }, { "Shapeshift into a @Werewolf@. Empowers your basic attack and gain new abilities. Increases @Max Health@ by 10%.", "\n<color=#C8B090>While transformed you gain: a stronger basic attack, Blood Howl and Cursed Bite.</color>" }, { "Shapeshift into a @Dire Werewolf@. Basic attack and abilities are further empowered. Increases @Max Health@ by 20%.", "\n<color=#C8B090>While transformed you gain: a further empowered basic attack, Greater Blood Howl and Greater Cursed Bite.</color>" }, { "Shapeshift into a @Vampire Bat@. Gain new abilities. @Movement@ increased. Immune to @attacks of opportunity@.", "\n<color=#C8B090>While transformed you gain: Energy Drain.</color>" }, { "The first time you deal damage or healing in battle, it's effectiveness is increased by 100%.", "\n<color=#C8B090>That bonus is consumed by your first damaging cast.</color>" }, { "Deals *0 physical damage. Pulls enemies within 4 hexes towards you. Targets are crippled for 1 turn. ", "\n<color=#C8B090>The pull drags them the whole way: they land on a hex adjacent to you.</color>" }, { "Breath fire dealing *0 fire damage to all enemies in a cone. ", "\n<color=#C8B090>The cone reaches 4 hexes from you.</color>" }, { "Deals *0 cold damage each turn.", "\n<color=#C8B090>Hits everything in a cone reaching 4 hexes from you.</color>" }, { "Deals *0 weapon damage and applies {STA=Stunned} to all enemies within a line for 1 turn.", "\n<color=#C8B090>The line reaches 5 hexes from you.</color>" }, { "Deals *0 weapon damage to all enemies within a line.", "\n<color=#C8B090>The line reaches 5 hexes from you.</color>" }, { "The caster hurls a razor-like shard of ice piercing foes in a line dealing *0 cold damage. ", "\n<color=#C8B090>The line reaches 10 hexes from you.</color>" }, { "Conjures the breath of a frost dragon dealing *0 cold damage to all enemies in a cone. ", "\n<color=#C8B090>The cone reaches 4 hexes from you.</color>" }, { "Breath lightning dealing *0 lightning damage to all enemies in a cone. ", "\n<color=#C8B090>The cone reaches 4 hexes from you.</color>" }, { "Charges to the target and deals *0 weapon damage to all enemies in your path.", "\n<color=#C8B090>The path is a line of up to 7 hexes.</color>" }, { "Conjures a lightning bolt that chains up to 5 enemies near the target dealing *0 lightning damage to each target. ", "\n<color=#C8B090>The 5 counts the chain's HOPS, not different enemies: the bolt can hit the same enemy again, so with only two enemies in range it bounces between them.</color>" }, { "Increase the mana cost of all skills by 20% and increase the power of mana using skills by 40%.", "\n<color=#C8B090>Power of Mana increases the damage and healing of abilities that cost Mana.\nIt does not change how much Mana they cost, it does nothing for abilities that cost no Mana,\nand it does not change the duration or the bonuses of the statuses those abilities apply.</color>" }, { "Increase the mana cost of all skills by an additional 30% and increase the power of mana using skills by an additional 60%.", "\n<color=#C8B090>Power of Mana increases the damage and healing of abilities that cost Mana.\nIt does not change how much Mana they cost, it does nothing for abilities that cost no Mana,\nand it does not change the duration or the bonuses of the statuses those abilities apply.</color>" }, { "Calls down a magical rain that increases potency of Mana using abilities by 50% for allies within the area. Lasts 2 turns.", "\n<color=#C8B090>Power of Mana increases the damage and healing of abilities that cost Mana.\nIt does not change how much Mana they cost, it does nothing for abilities that cost no Mana,\nand it does not change the duration or the bonuses of the statuses those abilities apply.</color>" }, { "Grants [0] Return Physical Damage.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Grants an additional [0] Return Physical Damage.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Grants [0] Return Shadow Damage.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Physical damage increased by [0].", "\n<color=#C8B090>Scales with your character level.</color>" }, { "@Intelligence@ grants [0] @Armor@ and @Magic Armor@ per point. Current Bonus: [1]", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Damage caused steals [0] points of @Dexterity@. Lasts the entire battle. Stacks up to 10 times.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Damage caused steals [0] points of @Intelligence@. Lasts the entire battle. Stacks up to 10 times.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Damage caused steals [0] points of @Might@. Lasts the entire battle. Stacks up to 10 times.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Envelopes the target in living vines that increase @armor@ and @magic armor@ by [0] and causes the target to regenerate *0 @health@ each turn.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Increases all attributes by [0]. In addition, 10% of your highest attribute value is added to all other attributes. Current Bonus: [1]", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Encases the friendly target in a dome of ice granting [0] Armor and Magic Armor for the duration. Immobilizes the target.", "\n<color=#C8B090>Scales with your character level.</color>" }, { "Summons a Raven, Coyote, or Raccoon to fight for you.", "\n<color=#C8B090>One is summoned at random:\n- Raven: Melee Attack, Evasion\n- Raccoon: Melee Attack, Steal Action\n- Coyote: Melee Attack, Cripple\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summons a Stag, Wolf, or Boar to fight for you.", "\n<color=#C8B090>One is summoned at random:\n- Stag: Melee Attack, Stunning Kick\n- Wolf: Melee Attack, Howl\n- Boar: Melee Attack, Fracture\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summons a Bear, Moose, or Panther to fight for you.", "\n<color=#C8B090>One is summoned at random:\n- Bear (a Grizzly): Stunning Slam, Wild Cleave\n- Moose: Melee Attack, Ground Slam\n- Panther: Melee Attack, Shadow Walk\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summons a Tundra Wolf to fight for you.", "\n<color=#C8B090>Tundra Wolf: Melee Attack, Howl\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summons a Dire Wolf to fight for you.", "\n<color=#C8B090>Dire Wolf: Melee Attack, Blood Howl\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summon a grizzly to fight your enemies.", "\n<color=#C8B090>Grizzly: Stunning Slam, Wild Cleave\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summon a wolf to fight your enemies.", "\n<color=#C8B090>Wolf: Melee Attack, Howl\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summon a Raven to fight your enemies. ", "\n<color=#C8B090>Raven: Melee Attack, Evasion\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Raise an Undead Ranger to fight by your side.", "\n<color=#C8B090>Undead Ranger: Ranged Attack, Hide In Shadows\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Raise an Undead Berserker to fight by your side.", "\n<color=#C8B090>Undead Berserker: Bleeding Cleave\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summon brambles to block 4 hexes. Attackers will take physical damage when striking the brambles. Lasts 4 turns.", "\n<color=#C8B090>Benefits from your Might and Intelligence, but does not count as a summon.</color>" }, { "Summon pillars of ice to block 4 hexes blocking enemy's line of sight. Attackers take cold damage. Lasts 4 turns.", "\n<color=#C8B090>Benefits from your Might and Intelligence, but does not count as a summon.</color>" }, { "Increases the target allies' stats by 20%.", "\n<color=#C8B090>Lasts 5 turns.</color>" }, { "Restores target's health by *0.", "\n<color=#C8B090>Healing scales with your Attack Power and Holy Power.\nReduced by effects that lower the target's healing received.</color>" }, { "Restores *0 health to all allies within 2 hexes of target.", "\n<color=#C8B090>Healing scales with your Attack Power and Holy Power.\nReduced by effects that lower the target's healing received.\nThe 2-hex area is centred on the chosen TARGET, not on the caster.</color>" }, { "Target restores *0 health per turn. ", "\n<color=#C8B090>Healing scales with your Attack Power and Holy Power.\nReduced by effects that lower the target's healing received.</color>" }, { "All allies within 3 hexes of you heal for *0 per turn. ", "\n<color=#C8B090>Healing scales with your Attack Power and Holy Power.\nReduced by effects that lower the target's healing received.</color>" }, { "Restores the target to full health.", "\n<color=#C8B090>Healing scales with your Holy Power.\nReduced by effects that lower the target's healing received.</color>" }, { "Summons a radiant light applying {STA=Blind} to the target dealing *0 Holy damage.", "\n<color=#C8B090>Damage scales with your Attack Power and Holy Power.</color>" }, { "Breathe out a stream of holy light dealing *0 holy damage to all enemies and healing *0 to all allies in range.", "\n<color=#C8B090>Damage and healing scale with your Attack Power and Holy Power.\nHealing is reduced by effects that lower the target's healing received.</color>" }, { "Expel a powerful celestial light blinding enemies and dealing *0 holy damage to all enemies and healing *1 to all allies in range.", "\n<color=#C8B090>Damage and healing scale with your Attack Power and Holy Power.\nHealing is reduced by effects that lower the target's healing received.</color>" }, { "Consecrate an area of ground to heal allies that stand upon it. Heals *0 per turn for 3 turns. ", "\n<color=#C8B090>Healing scales with your Attack Power and Holy Power.</color>" }, { "Any target you heal with Cure, Regenerate, Healing Hand, Mass Cure, or Divine Intervention also receives an additional healing over time effect restoring *0 health for 3 turns.", "\n<color=#C8B090>Healing scales with your Attack Power and Holy Power.</color>" }, { "Calls down a shield that protects the target absorbing *0 damage. ", "\n<color=#C8B090>Absorption scales with your Attack Power and Holy Power.</color>" }, { "Conjures a shield imbued with holy flame absorbing *0 damage. Upon shield depletion, it explodes and deals *0 holy damage to all foes in a 3 hex radius.", "\n<color=#C8B090>Damage and absorption scale with your Attack Power and Holy Power.</color>" }, { "+ 20% increased Treasure Find", "\n<color=#C8B090>Increases the chance for enemies to drop items. Does not affect item rarity. Stacks with your party.</color>" }, { "+ 40% increased Treasure Find", "\n<color=#C8B090>Increases the chance for enemies to drop items. Does not affect item rarity. Stacks with your party.</color>" }, { "+ 60% increased Treasure Find", "\n<color=#C8B090>Increases the chance for enemies to drop items. Does not affect item rarity. Stacks with your party.</color>" }, { "+ 80% increased Treasure Find", "\n<color=#C8B090>Increases the chance for enemies to drop items. Does not affect item rarity. Stacks with your party.</color>" }, { "+ 100% increased Treasure Find", "\n<color=#C8B090>Increases the chance for enemies to drop items. Does not affect item rarity. Stacks with your party.</color>" }, { "+ 10% increased Gold Find", "\n<color=#C8B090>Increases the gold you earn. Stacks with your party.</color>" }, { "+ 20% increased Gold Find", "\n<color=#C8B090>Increases the gold you earn. Stacks with your party.</color>" }, { "+ 30% increased Gold Find", "\n<color=#C8B090>Increases the gold you earn. Stacks with your party.</color>" }, { "+ 40% increased Gold Find", "\n<color=#C8B090>Increases the gold you earn. Stacks with your party.</color>" }, { "+ 50% increased Gold Find", "\n<color=#C8B090>Increases the gold you earn. Stacks with your party.</color>" }, { "+ 5% to Damage and Healing", "\n<color=#C8B090>Increases all damage you deal and all healing you do.</color>" }, { "+ 10% to Damage and Healing", "\n<color=#C8B090>Increases all damage you deal and all healing you do.</color>" }, { "+ 15% to Damage and Healing", "\n<color=#C8B090>Increases all damage you deal and all healing you do.</color>" }, { "+ 20% to Damage and Healing", "\n<color=#C8B090>Increases all damage you deal and all healing you do.</color>" }, { "+ 25% to Damage and Healing", "\n<color=#C8B090>Increases all damage you deal and all healing you do.</color>" }, { "Gain 1 additional movement", "\n<color=#C8B090>Each movement point lets you move one extra hex per turn.</color>" }, { "Gain 2 additional movement", "\n<color=#C8B090>Each movement point lets you move one extra hex per turn.</color>" }, { "Gain 1 additional range", "\n<color=#C8B090>Increases the range of your ranged attacks and skills. Does not apply to certain skills.</color>" }, { "Gain 2 additional range", "\n<color=#C8B090>Increases the range of your ranged attacks and skills. Does not apply to certain skills.</color>" }, { "Skill Options +1", "\n<color=#C8B090>Increases the number of skill choices offered when leveling up.</color>" }, { "Skill Options +2", "\n<color=#C8B090>Increases the number of skill choices offered when leveling up.</color>" }, { "Attribute Points Per Level +1", "\n<color=#C8B090>Grants additional attribute points each time you level up.</color>" }, { "Attribute Points Per Level +2", "\n<color=#C8B090>Grants additional attribute points each time you level up.</color>" }, { "Attribute Points Per Level +3", "\n<color=#C8B090>Grants additional attribute points each time you level up.</color>" }, { "[[ResistCold]] +10%", "\n<color=#C8B090>Reduces Cold damage you take.</color>" }, { "[[ResistCold]] +15%", "\n<color=#C8B090>Reduces Cold damage you take.</color>" }, { "[[ResistCold]] +20%", "\n<color=#C8B090>Reduces Cold damage you take.</color>" }, { "[[ResistFire]] +10%", "\n<color=#C8B090>Reduces Fire damage you take.</color>" }, { "[[ResistFire]] +15%", "\n<color=#C8B090>Reduces Fire damage you take.</color>" }, { "[[ResistFire]] +20%", "\n<color=#C8B090>Reduces Fire damage you take.</color>" }, { "[[ResistLightning]] +10%", "\n<color=#C8B090>Reduces Lightning damage you take.</color>" }, { "[[ResistLightning]] +15%", "\n<color=#C8B090>Reduces Lightning damage you take.</color>" }, { "[[ResistLightning]] +20%", "\n<color=#C8B090>Reduces Lightning damage you take.</color>" }, { "[[ResistPhysical]] +10%", "\n<color=#C8B090>Reduces Physical damage you take.</color>" }, { "[[ResistPhysical]] +15%", "\n<color=#C8B090>Reduces Physical damage you take.</color>" }, { "[[ResistPhysical]] +20%", "\n<color=#C8B090>Reduces Physical damage you take.</color>" }, { "+ 5% to Summon Damage and Health", "\n<color=#C8B090>Increases the damage and health of your summoned creatures.</color>" }, { "+ 10% to Summon Damage and Health", "\n<color=#C8B090>Increases the damage and health of your summoned creatures.</color>" }, { "+ 15% to Summon Damage and Health", "\n<color=#C8B090>Increases the damage and health of your summoned creatures.</color>" }, { "+ 20% to Summon Damage and Health", "\n<color=#C8B090>Increases the damage and health of your summoned creatures.</color>" }, { "+ 25% to Summon Damage and Health", "\n<color=#C8B090>Increases the damage and health of your summoned creatures.</color>" }, { "Skill Tree Removals +1", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Skill Tree Removals +2", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Skill Tree Removals +3", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Skill Tree Removals +4", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Skill Tree Removals +5", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Skill Tree Removals +6", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Skill Tree Removals +7", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Skill Tree Removals +8", "\n<color=#C8B090>Lets you remove skill trees from your pool of skill choices (at least 4 trees remain). Can only be chosen at select party screen.</color>" }, { "Attackers take Fire Damage.", "\n<color=#C8B090>The attacker takes this damage in return, based on its own Max Health and not on the health of the one it attacked, before damage reduction.</color>" }, { "Take [0]% of your Max Health in Shadow Damage per turn.", "\n<color=#C8B090>Raw damage, before damage reduction: your own Max Health multiplied by the percentage shown, which already includes your own Shrine Effect Bonus, and it can be 0.</color>" }, { "Damage increased by [0]%. ", "\n<color=#C8B090>Base 20%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "Reduces Damage taken by [0]%. ", "\n<color=#C8B090>Base 20%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "Critical hit chance increased by [0]%.", "\n<color=#C8B090>Base 20%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "Increases dodge chance by [0]%.", "\n<color=#C8B090>Base 20%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "Lifesteal increased by [0]%.", "\n<color=#C8B090>Base 8%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "Decreases the cost of mana using abilities by [0]%.", "\n<color=#C8B090>Base 50%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "Your attacks have a [0]% chance to stun the target.", "\n<color=#C8B090>Base 20%; the value shown already includes the Shrine Effect Bonus.</color>" } }; private static readonly Dictionary<string, string> TextFixes = new Dictionary<string, string> { { "10% chance to cast Level [level value] {SKL=Meteor} when Striking.", "10% chance to cast Level [level value] {SKL=Meteor} when striking." }, { "Striking with this weapon applies 2 stack of Poison.", "Striking with this weapon applies 2 stacks of Poison." }, { "Vitality increased by 10 for 5 turns.", "Vitality increased by 5 for 5 turns." }, { "Applies Hunger Ksvaldir: Sacrifices 10% of your max health per turn.", "Applies Hunger of Ksvaldir: Sacrifices 10% of your max health per turn." }, { "Weapon attacks apply 1 stacks of bleeding.", "Weapon attacks apply 1 stack of bleeding." }, { "10% chance on hit to cast Level [level value] {SKL=Consumption}", "10% chance on hit to cast Level [level value] {SKL=Consumption}." }, { "5% chance to cast Level [level value] {SKL=Thunder Bolt} when hitting an enemy with any ability. 5% chance to cast Level [level value] {SKL=Frost Nova} when hitting an enemy with any ability. 5% chance to cast Level [level value] {SKL=Fireball} when hitting an enemy with any ability.", "5% chance to cast Level [level value] {SKL=Thunder Bolt} when hitting an enemy with any ability. 8% chance to cast Level [level value] {SKL=Frost Nova} when hitting an enemy with any ability. 5% chance to cast Level [level value] {SKL=Fireball} when hitting an enemy with any ability." }, { "Grants the passive Grants the passive skill {SKL=Lich Lord}.", "Grants the passive skill {SKL=Lich Lord}." }, { "Increases the power and cost of all @Mana Abilites@ by 5% of your Max Mana.", "Increases the power and cost of all @Mana Abilities@ by 5% of your Max Mana." }, { "Holy power increased by [15]%", "Holy Power increased by [15]%" }, { "Holy power increased by [6]%", "Holy Power increased by [6]%" }, { "Holy power increased by [3]%", "Holy Power increased by [3]%" }, { "Holy power increased by [9]%", "Holy Power increased by [9]%" }, { "Holy power increased by [12]%", "Holy Power increased by [12]%" }, { "5% of your max life regenerated per turn.", "5% of your max health regenerated per turn." }, { "Recover [0]% of maximum mana each turn. ", "Recover [0]% of max mana each turn. \n<color=#C8B090>Base 10%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "Increases @Life Steal@ by 6%. Reduces @Max Life@ by 15%. <i><color=#808080>\"A thirst so deep, it blurs the lines, Til we're but marionettes of our own designs.\"</i></color>", "Increases @Life Steal@ by 6%. Reduces @Max Health@ by 15%. <i><color=#808080>\"A thirst so deep, it blurs the lines, Til we're but marionettes of our own designs.\"</i></color>" }, { "Increases Damage and Damage Taken by 25%. Increases max life by 15%.", "Increases Damage and Damage Taken by 25%. Increases max health by 15%." }, { "Consuming any Globule heals you for 20% of max life and mana.", "Consuming any Globule heals you for 20% of max health and mana." }, { "Consuming any Globule heals you for 8% of max life and mana.", "Consuming any Globule heals you for 8% of max health and mana." }, { "Increases @maximum mana@ by 20%.", "Increases @max mana@ by 20%." }, { "Every summon active increases the @Max Life@, @Damage@ and @Healing@ of you and your summons by 5%.", "Every summon active increases the @Max Health@, @Damage@ and @Healing@ of you and your summons by 5%." }, { "@Maximum health@ and @maximum mana@ lowered by 25%.", "@Max health@ and @max mana@ lowered by 25%." }, { "Recover [0]% of maximum health each turn. ", "Recover [0]% of max health each turn. \n<color=#C8B090>Base 10%; the value shown already includes the Shrine Effect Bonus.</color>" }, { "@Maximum health@ increased by 10% per stack.", "@Max health@ increased by 10% per stack." }, { "@Maximum health@ and @maximum mana@ lowered by 25% per stack.", "@Max health@ and @max mana@ lowered by 25% per stack." }, { "Increases damage received by 20%.", "Increases damage taken by 20%." }, { "Heals 25% of your maximum health and removes all negative statuses. Can be used when Disabled.", "Heals 25% of your max health and removes all negative statuses. Can be used when Disabled." }, { "Every enemy that dies heals you for 10% of your maximum health.", "Every enemy that dies heals you for 10% of your max health." }, { "Increases @Damage dealt@ and @Max Life@ by 15%. Increases @damage received@ by 15%.", "Increases @Damage dealt@ and @Max Health@ by 15%. Increases @damage taken@ by 15%." }, { "For every enemy within 3 hexes of your character gain 3% @increased Damage@ and 3% @Maximum Health@.", "For every enemy within 3 hexes of your character gain 3% @increased Damage@ and 3% @Max Health@." }, { "Grants 10% @mana steal@. Sacrifices 10% maximum health per turn.", "Grants 10% @mana steal@. Sacrifices 10% max health per turn." }, { "Gain 2% of your maximum health as @Additional Shadow Damage@. Current Shadow Damage Increase: [0].", "Gain 2% of your max health as @Additional Shadow Damage@. Current Shadow Damage Increase: [0]." }, { "Increase the effectiveness of your damage and healing skills by 30%. Maximum health reduced by 20%.", "Increase the effectiveness of your damage and healing skills by 30%. Max health reduced by 20%." }, { "Devour the life force of all enemies within 2 hexes dealing *0 Shadow Damage and giving you 10% @Maximum Health@ for each enemy effected.", "Devour the life force of all enemies within 2 hexes dealing *0 Shadow Damage and giving you 10% @Max Health@ for each enemy effected.\n\n<color=#C8B090>Each stack grants another 10% Max Health; you gain one stack per enemy hit.</color>" }, { "Every enemy slain grants 6% @maximum health@ and @Increased Damage@. Lasts the duration of the battle. Stacks up to 5 times.", "Every enemy slain grants 6% @max health@ and @Increased Damage@. Lasts the duration of the battle. Stacks up to 5 times." }, { "Bless all allies within 5 hexes. Increases @damage@, @maximum health@, and @maximum Mana@ by 10%.", "Bless all allies within 5 hexes. Increases @damage@, @max health@, and @max mana@ by 10%." }, { "Increases @Damage dealt@ and @damage received@ by 25%. Increases @Max Life@ by 15%.", "Increases @Damage dealt@ and @damage taken@ by 25%. Increases @Max Health@ by 15%." }, { "Divine Resistance increased by 5%", "Holy Resistance increased by 5%" }, { "Divine Resistance increased by 15%", "Holy Resistance increased by 15%" }, { "Divine Resistance increased by 10%", "Holy Resistance increased by 10%" }, { "Applies @2@ @poison@ when striking Applies @2@ @poison@ when struck", "Applies @2@ @poison@ when striking. Applies @2@ @poison@ when struck." }, { "Increased damage by 50% All resistances lowered by 25% Control Resistance", "Increased damage by 50%. All resistances except Holy lowered by 25%. Control Resistance" }, { "Increases damage and summon damage by 10%", "Increases damage and summon damage by 10%.\n<color=#C8B090>Also increases the healing this character does by the same percentage.</color>" }, { "Ranged spells deal damage the closer you are. Calculates how much ranged you have and the closer you are from your max range the more damage you deal.", "Increases damage by 50%.\n<color=#C8B090>Also increases the healing this character does by the same percentage.</color>" }, { "Movement increased by 3 Action Points increased by 1 Max Health reduced by 25% Damage reduced by 25%", "Movement increased by 3. Action Points increased by 1. Max Health reduced by 25%. Damage reduced by 25%.\n<color=#C8B090>Also reduces the healing this character does by the same percentage.</color>\n<color=#C8B090>Current health is reduced by the same percentage and comes back when the status ends. This cannot kill.</color>" }, { "Grants 1 additional Action Points. Lowers movement points by 6.", "Grants 1 additional Action Point. Lowers movement points by 6." }, { "Grants 1 additional Action Point. Increases Damage Taken by 25%.", "Grants 1 additional Action Point." }, { "Immune to Bleeding.", "Immune to Blind." }, { "All Resistances reduced by 30%", "All Resistances except Holy reduced by 30%" }, { "All Resistances reduced by 20%", "All Resistances except Holy reduced by 20%" }, { "All Resistances reduced by 10%", "All Resistances except Holy reduced by 10%" }, { "Deals *0 damage. Lifesteals for 8%.", "Deals *0 damage. Lifesteals for 2.5%." }, { "All stats reduced by 15%", "Might, Dexterity, Intelligence, Vitality and Recovery reduced by 15%" }, { "Cannot receive additional actions points. Caused by receiving additional action points this turn.", "Cannot receive additional action points. Caused by receiving additional action points this turn." }, { "Your damage dealt is reduced by 20%", "Your damage dealt is reduced by 20%." }, { "Dash to an enemy dealing *0 weapon damage then quickly dash to an enemy within 2 hexes to strike again. Strikes up to 4 times. Each time you strike a target it increases your dodge chance by 8%. Lasts 2 turns. ", "Dash to an enemy dealing *0 weapon damage then quickly dash to an enemy within 3 hexes to strike again. Strikes up to 4 times. Each time you strike a target it increases your dodge chance by 8%. Lasts 2 turns. " }, { "Dash to an enemy dealing *0 weapon damage then quickly dash to an enemy within 2 hexes to strike again. Strikes up to 4 times. Each time you hit increases the damage of Power Strikes by 50%.", "Dash to an enemy dealing *0 weapon damage then quickly dash to an enemy within 3 hexes to strike again. Strikes up to 4 times. Each time you hit increases the damage of Power Strikes by 50%." }, { "Dash to an enemy dealing *0 weapon damage then quickly dash to an enemy within 2 hexes to strike again. Strikes up to 4 times.", "Dash to an enemy dealing *0 weapon damage then quickly dash to an enemy within 3 hexes to strike again. Strikes up to 3 times." }, { "Resist Divine", "Resist Holy" }, { "Resistance Divine", "Resistance Holy" }, { "Shops are refreshed every time your party completes a quest. Check back often for new loot!", "Shops are refreshed every time your party completes a quest. Check back often for new loot!" }, { "A well timed healing or mana potion can turn the tide of battle. ", "A well timed healing or mana potion can turn the tide of battle." }, { "Deals *0 shadow damage to the target every turn for 3 turns. @Life Steals@ for 6%. @Life Steal@ heals you for a percentage of your @max health@ each time you hit. Reduced for area of effect and no ap cost abilities.", "Deals *0 shadow damage to the target every turn for 3 turns. @Life Steals@ for 2.5%. @Life Steal@ heals you for a percentage of your @max health@ each time you hit. Reduced for area of effect and no ap cost abilities." }, { "The caster creates an poison gas cloud applies @4@ stacks of {STA=Poisoned} within 2 hexes of the selected target.", "The caster creates a poison gas cloud that applies @4@ stacks of {STA=Poisoned} within 2 hexes of the selected target." }, { "Raise a Undead Wizard to fight by your side.", "Raise an Undead Wizard to fight by your side.\n<color=#C8B090>Undead Wizard: Bone Explosion, Consumption, Ghost Armor\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Completely negates the next attack. Lasts until hit. ", "Completely negates the next attack. Lasts until hit." }, { "Crush the target's soul dealing *0 @Shadow Damage@ increased by your Max Health. ", "Crush the target's soul dealing *0 @Shadow Damage@ increased by your Max Health." }, { "Summon a skeletal archer to fight by your side.", "Raise a skeletal archer to fight by your side.\n<color=#C8B090>Skeletal Archer: Ranged Attack\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summon a skeletal mage to fight by your side.", "Raise a skeletal mage to fight by your side.\n<color=#C8B090>Skeletal Mage: Frost Nova, Fireball, Twister, Ghost Armor\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Summon a skeletal warrior to fight by your side.", "Raise a skeletal warrior to fight by your side.\n<color=#C8B090>Skeletal Warrior: Melee Attack, Cleave\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Raise a Mighty Iron Golem to fight for you.", "Raise a Mighty Iron Golem to fight by your side.\n<color=#C8B090>Iron Golem: Ground Slam\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Gain the ability to shapeshift into a powerful elemental @Dragonkin@. Empowers basic attack, grants new abilities, and resistance based on the color you choose. Increases @Armor@ by [0].", "Shapeshift into a powerful elemental @Dragonkin@. Empowers basic attack, grants new abilities, and resistance based on the color you choose. Increases @Armor@ by [0].\n<color=#C8B090>Scales with your character level.</color>\n<color=#C8B090>The Dragonkin grants a Slash, a Breath and an Orb of its element: Shadow, Frost, Lightning, Fire or Holy.</color>" }, { "Sacrifice 15% of your maximum health in exchange for an additonal action this turn. Applies {STA=Exhaustion}.", "Sacrifice 15% of your max health in exchange for an additional action this turn. Applies {STA=Exhaustion}." }, { "Increase the range of all non-melee abilites by 1 hex. ", "Increase the range of all non-melee abilities by 1 hex. " }, { "Deals *0 weapon damage. Every hex between you and your target increases the damage of by 10%. Called Shot cannot be dodged or blocked.", "Deals *0 weapon damage. Every hex between you and your target increases the damage by 10%. Called Shot cannot be dodged or blocked." }, { "Deals *0 weapon damage, removes 1 random benefical status from the target and lowers the target's @Resistance@ by 20% for 2 turns.", "Deals *0 weapon damage, removes 1 random beneficial status from the target and lowers the target's @Resistance@ by 20% for 2 turns." }, { "Deals *0 weapon damage. Removes 1 random benefical status from the target.", "Deals *0 weapon damage. Removes 1 random beneficial status from the target." }, { "Every enemy slain on your turn grants 1 additonal AP. Can only grant up to 1 additional AP per turn.", "Every enemy slain on your turn grants 1 additional AP. Can only grant up to 1 additional AP per turn." }, { "Deals *0 shadow damage and removes a random benefical status from the target. If a status is removed, the target suffers an additional *0 shadow damage.", "Deals *0 shadow damage and removes a random beneficial status from the target. If a status is removed, the target suffers an additional *0 shadow damage." }, { "Deals *0 weapon damage. Every hex between you and your target increases the damage of by 10%. ", "Deals *0 weapon damage. Every hex between you and your target increases the damage by 10%. " }, { "Deals *0 weapon damage. Every hex between you and your target increases the damage of by 15%. ", "Deals *0 weapon damage. Every hex between you and your target increases the damage by 15%. " }, { "Infects enemies with Stunning Spores applying {STA=Stun} for 1 turns.", "Infects enemies with Stunning Spores applying {STA=Stun} for 1 turn." }, { "Hurls a ball of Ice dealing *0 cold damage to all targets in range. Applies 5 stacks of {STA=Chilled}", "Hurls a ball of Ice dealing *0 cold damage to all targets in range. Applies 5 stacks of {STA=Chilled}." }, { "Hurls a ball of flame dealing *0 fire damage to all targets in range. Applies 10 stacks of {STA=Heat}", "Hurls a ball of flame dealing *0 fire damage to all targets in range. Applies 10 stacks of {STA=Heat}." }, { "Summons a Timber Wolf to fight for you", "Summons a Timber Wolf to fight for you.\n<color=#C8B090>Timber Wolf: Melee Attack, Cripple\nDoes not copy your attributes.\nYour Might raises its damage; your Intelligence, its health.</color>" }, { "Increases damage dealt and max life by 15%. Increases damage received by 15%.", "Increases damage dealt and max health by 15%. Increases damage taken by 15%.\n\n<color=#C8B090>Current health is increased by the same percentage and goes back down when the status ends.\nAlso increases the healing this character does by the same percentage.</color>" }, { "@Maximum health@ and @Damage Dealt@ increased by 6% per stack.", "@Max health@ and @Damage Dealt@ increased by 6% per stack.\n\n<color=#C8B090>Stacks up to 5 times.\nAlso increases the healing you do by the same percentage.</color>" }, { "@Maximum health@ and @maximum mana@ increased by 10%. @Damage dealt@ increased by 10%.", "@Max health@ and @max mana@ increased by 10%. @Damage dealt@ increased by 10%.\n\n<color=#C8B090>Also increases the healing you do by the same percentage.</color>" }, { "Maximum health increased by 25% Deals more damage at lower health", "Max health increased by 25% Deals more damage at lower health\n\n<color=#C8B090>Lasts 3 turns.\nThe bonus is your missing health as a percentage: up to +100% damage at 1 health.</color>" }, { "Increases damage dealt by 25%. Increases max life and damage taken by 15%.", "Increases damage dealt by 25%. Increases max health and damage taken by 15%.\n\n<color=#C8B090>Lasts 3 turns.\nAlso increases the healing you do by the same percentage.</color>" }, { "Maximum health reduced by 15%.", "Max health reduced by 15%.\n\n<color=#C8B090>Current health is reduced by the same percentage and comes back when the status ends. This cannot kill.</color>" }, { "@Maximum health@ reduced by 10%.", "@Max health@ reduced by 10%.\n\n<color=#C8B090>Each stack grants another 10% Max Health; you gain one stack per enemy hit.</color>" }, { "@Maximum health@ reduced by 20%.", "@Max health@ reduced by 20%.\n\n<color=#C8B090>Each stack grants another 10% Max Health; you gain one stack per enemy hit.</color>" }, { "Removes all negative statuses from friendly target but inflicts 10% of target's maximum health as fire damage. Can be used when Disabled.", "Removes all negative statuses from friendly target but inflicts 10% of target's max health as fire damage. Can be used when Disabled.\n\n<color=#C8B090>This cannot reduce the target below 1 health.</color>" }, { "The caster reaches out in aid healing 30% of target's maximum health.", "The caster reaches out in aid healing 30% of target's max health.\n\n<color=#C8B090>Healing scales with your Holy Power.\nReduced by effects that lower the target's healing received.</color>" }, { "Max Health, Damage, Armor, and Dodge Chance reduced by 50%.", "Max Health, Damage, Armor, Magic Armor, and Dodge Chance reduced by 50%." }, { "Damage increased 50%.", "Damage increased by 50%." } }; private static readonly HashSet<string> _appliedFixes = new HashSet<string>(); private static readonly HashSet<string> _appliedAppends = new HashSet<string>(); private static readonly HashSet<string> _rotulosDeStatusAvisados = new HashSet<string>(); private static bool _loggedAlive; private static readonly Regex AttributePowerupRegex = new Regex("^\\+\\s*\\d+\\s+to\\s+(Might|Dexterity|Intelligence|Vitality|Reflex)$", RegexOptions.Compiled); private static readonly Regex DamageReductionRegex = new Regex("^\\+\\s*\\d+%\\s+Damage Reduction$", RegexOptions.Compiled); private static readonly (Regex Pattern, string Attribute)[] StatusAttributeRules = new(Regex, string)[5] { (new Regex("^Might increased by (\\[\\d+\\]|\\d+)\\.$", RegexOptions.Compiled), "Might"), (new Regex("^Dexterity increased by (\\[\\d+\\]|\\d+)\\.$", RegexOptions.Compiled), "Dexterity"), (new Regex("^Intelligence increased\\.$|^Intelligence increased by (\\[\\d+\\]|\\d+)\\.$", RegexOptions.Compiled), "Intelligence"), (new Regex("^Vitality increased by (\\[\\d+\\]|\\d+)\\.$", RegexOptions.Compiled), "Vitality"), (new Regex("^Reflex increased by (\\[\\d+\\]|\\d+)\\.$", RegexOptions.Compiled), "Reflex") }; private static readonly (Regex Pattern, string Attribute)[] FortuneAttributeRules = new(Regex, string)[5] { (new Regex("^@Might@ increased by \\{\\d+,\\d+\\}\\.?", RegexOptions.Compiled), "Might"), (new Regex("^@Dexterity@ increased by \\{\\d+,\\d+\\}\\.?", RegexOptions.Compiled), "Dexterity"), (new Regex("^@Intelligence@ increased by \\{\\d+,\\d+\\}\\.?", RegexOptions.Compiled), "Intelligence"), (new Regex("^@Vitality@ increased by \\{\\d+,\\d+\\}\\.?", RegexOptions.Compiled), "Vitality"), (new Regex("^@Reflex@ increased by \\{\\d+,\\d+\\}\\.?", RegexOptions.Compiled), "Reflex") }; private const string ResistanceExplainSuffix = "\nResistances reduce their damage type by the listed %. If a resistance goes negative, that damage type is amplified instead."; private static readonly string[] ResistanceReductionPrefixes = new string[7] { "Elemental resistance reduced by 5% per stack", "Reduces @Cold Resistance@ by @25%@ per stack", "Reduces @Fire Resistance@ by @25%@ per stack", "Reduces @Physical Resistance@ by @25%@ per stack", "Reduces Elemental resistances by 25%", "@Resistance@ lowered by 20%", "@Resistances@ lowered by 20%. Reduces healing received by 50%" }; private static readonly HashSet<string> GlossaryLabelExclusions = new HashSet<string> { "Life Steal", "Lifesteal", "% Life Steal", "% Lifesteal", "Stealth", "Enrage", "Marked Prey" }; private static readonly (Regex Match, string Append, string ExcludeIfContains)[] SkillGlossaryRules = new(Regex, string, string)[4] { (new Regex("\\bStealth\\b", RegexOptions.Compiled), "\nStealth: attacking from stealth has 100% critical hit chance.", "critical hit chance"), (new Regex("Marked Prey", RegexOptions.Compiled), "\nMarked Prey: increases damage taken by 10% per stack.", "Damage taken"), (new Regex("\\bEnrage\\b", RegexOptions.Compiled), "\nEnraged characters are immune to movement impairing effects and knockback.", "immune to"), (new Regex("Life Steal|Lifesteal", RegexOptions.Compiled), "\nLife Steal: heals you for a percentage of your Max Health each time you hit. Reduced for area of effect abilities.", "heals you for") }; private static readonly Regex ArmorAffixRegex = new Regex("\\bArmor\\b", RegexOptions.Compiled); private static readonly HashSet<string> ArmorQueTambemDaMagicArmor = new HashSet<string> { "Armor increased by 5%", "Armor increased by 35%", "Armor increased by 15%", "Armor increased by [50]% Movement points lowered 1", "Armor increased by 25% Movement points lowered", "Armor increased by [30]% Movement points lowered 1", "Armor increased by 45% Movement points lowered", "Armor increased by 20%", "Armor increased by 25%", "Armor increased by [60]% Movement points lowered 1", "Armor increased by [20]% Movement points lowered 1", "Armor increased by 35% Movement points lowered", "Armor increased by 45%", "Armor increased by [40]% Movement points lowered 1", "Armor increased by 10%" }; private static readonly Regex ArmorValueSourceRegex = new Regex("Armor@?\\s+value", RegexOptions.Compiled); private static readonly Regex ResistAffixRegex = new Regex("\\bResistance\\w*\\b", RegexOptions.Compiled); private static readonly HashSet<string> RotulosDeStatusSemNota = new HashSet<string> { "Increased Armor", "Reduced Resistances I", "Reduced Resistances II", "Reduced Resistances III" }; private static readonly HashSet<string> _falhasRegistradas = new HashSet<string>(); internal static string ComACorDoJogo(string texto) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(texto) || texto.IndexOf("#C8B090", StringComparison.Ordinal) < 0) { return texto; } if (_corEspecialDoJogo == null) { try { Tooltip val = (((Object)(object)GUIManager.instance != (Object)null) ? GUIManager.instance.tooltip : null); _corEspecialDoJogo = (((Object)(object)val != (Object)null) ? ColorUtility.ToHtmlStringRGB(val.specialDescColor) : string.Empty); Plugin.Log.LogInfo((object)("BetterTooltips: cor do jogo para explicacoes = #" + _corEspecialDoJogo)); } catch (Exception ex) { _corEspecialDoJogo = string.Empty; Plugin.Log.LogWarning((object)("BetterTooltips: nao consegui ler specialTextColor (" + ex.Message + "); mantendo o fallback.")); } } if (!string.IsNullOrEmpty(_corEspecialDoJogo)) { return texto.Replace("#C8B090", _corEspecialDoJogo); } return texto; } internal static string CorDaLinhaDeAuras() { if (_corAuraDoJogo == null) { _corAuraDoJogo = LerCorAzulDoJogo(); if (_corAuraDoJogo == null) { _corAuraDoJogo = "C8B090"; Plugin.Log.LogWarning((object)"BetterTooltips: nenhuma cor azul da paleta do jogo disponivel (skillStatusColor/coldColor) — a linha de auras ativas sai na cor das notas (#C8B090)."); } else { Plugin.Log.LogInfo((object)("BetterTooltips: cor da linha de auras ativas = #" + _corAuraDoJogo)); } } return _corAuraDoJogo; } private static string LerCorAzulDoJogo() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) try { Tooltip val = (((Object)(object)GUIManager.instance != (Object)null) ? GUIManager.instance.tooltip : null); if ((Object)(object)val != (Object)null && EhAzul(val.skillStatusColor)) { string text = ColorUtility.ToHtmlStringRGB(val.skillStatusColor); Plugin.Log.LogInfo((object)("BetterTooltips: azul da paleta lido em Tooltip.skillStatusColor (status do jogo em tooltip) = #" + text)); return text; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("BetterTooltips: nao consegui ler skillStatusColor (" + ex.Message + ").")); } try { if ((Object)(object)GUIManager.instance != (Object)null && EhAzul(GUIManager.instance.coldColor)) { string text2 = ColorUtility.ToHtmlStringRGB(GUIManager.instance.coldColor); Plugin.Log.LogInfo((object)("BetterTooltips: azul da paleta lido em GUIManager.coldColor (cor do dano Cold) = #" + text2)); return text2; } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("BetterTooltips: nao consegui ler coldColor (" + ex2.Message + ").")); } return null; } private static bool EhAzul(Color c) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) float num = c.b - c.r + (c.b - c.g); if (c.b >= c.r && c.b >= c.g && c.b > 0.35f) { return num > 0.05f; } return false; } [HarmonyPostfix] [HarmonyPriority(600)] private static void CorDoJogoPostfix(ref string __result) { string text = __result; try { __result = ComACorDoJogo(__result); } catch (Exception e) { __result = text; RegistrarFalhaIgnorada("postfix de cor (Priority.High) do OptionsManager.Localize", e); } } private static bool IsGlossaryLabel(string original) { string text = original.Trim(); if (GlossaryLabelExclusions.Contains(text) || text.EndsWith(" Applied")) { return true; } if (text.Length <= 24) { string text2 = text.ToLower(); if (text2.StartsWith("life steal") || text2.StartsWith("lifesteal")) { return true; } } return false; } private static string AnexarNota(string texto, string nota) { if (string.IsNullOrEmpty(nota)) { return texto; } return texto.TrimEnd() + "\n\n" + nota.TrimStart(new char[1] { '\n' }); } private static string BuildArmorNote() { GlobalSettingsManager instance = GlobalSettingsManager.instance; GlobalSettings val = ((instance != null) ? instance.globalSettings : null); if ((Object)(object)val == (Object)null) { return null; } return "\nArmor blocks damage: each " + val.ArmorPerDamagePointReduction.ToString("0.##") + " Armor reduces damage taken by 1 (capped at " + val.maxArmorReductionPercent.ToString("0.##") + "% of the incoming damage). Armor and Magic Armor do not reduce Shadow damage."; } private static string BuildAttributeEffects(string attribute) { GlobalSettingsManager instance = GlobalSettingsManager.instance; GlobalSettings val = ((instance != null) ? instance.globalSettings : null); if ((Object)(object)val == (Object)null) { return null; } return attribute switch { "Might" => "\nEffects per point:\n+" + val.AbilityPwrPerMight.ToString("0.##") + "% Damage & Healing\n+" + val.AbilityPwrPerMightSummon.ToString("0.##") + "% Summon Damage\n+" + val.ArmorPercPerMight.ToString("0.##") + "% Armor & Magic Armor", "Dexterity" => "\nEffects per point:\n+" + val.CritRatingPerDex.ToString("0.##") + " Crit Rating\n+" + val.CritDamagePerDex.ToString("0.##") + "% Crit Damage\n" + $"1 Movement Per {val.MovementPointPerDexInterval} Dex (Max 3)", "Intelligence" => "\nEffects per point:\n+" + val.ManaPerInt.ToString("0.##") + " Max Mana\n+" + val.MaxManaPercPerInt.ToString("0.##") + "% Max Mana\n" + $"1 Skill Range Per {val.RangePerIntInterval} Int (Max 3)\n" + "+" + val.SummonLifePerInt.ToString("0.##") + "% Summon Health", "Vitality" => "\nEffects per point:\n+" + val.MaxHealthPerVit.ToString("0.##") + " Max Health\n+" + val.MaxHealthPercPerVit.ToString("0.##") + "% Max Health", "Reflex" => "\nEffects per point:\n+" + val.DodgeRatingPerReflex.ToString("0.##") + " Dodge Rating\n+" + val.DodgeCounterChancePerReflex.ToString("0.##") + "% Dodge Counter Chance\n+" + val.OppAttackPercDmgPerReflex.ToString("0.##") + "% Opportunity Attack Damage\n+" + val.OppAttackPercDmgPerReflex.ToString("0.##") + "% Counter Attack Damage\n" + $"1 Counter Attack a turn Per {val.ExtraCounterAttacksPerReflexInterval} Reflex (Max 3)", _ => null, }; } private static string BuildDamageReductionNote() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) try { GlobalSettingsManager instance = GlobalSettingsManager.instance; GlobalSettings val = ((instance != null) ? instance.globalSettings : null); if ((Object)(object)val == (Object)null) { return null; } DamageReductionCalcOrder[] damageReductionOrder = val.DamageReductionOrder; if (damageReductionOrder == null || damageReductionOrder.Length == 0) { return null; } List<string> list = new List<string>(); bool flag = false; DamageReductionCalcOrder[] array = damageReductionOrder; for (int i = 0; i < array.Length; i++) { string text = ((object)array[i]/*cast due to .constrained prefix*/).ToString(); if (text == "GeneralReduction") { flag = true; } else if (flag) { list.Add((text == "Resists") ? "Resistances" : ((text == "Armor") ? "Armor" : text)); } } if (flag && list.Count > 0) { return "\nReduces all damage you take. Applied before " + string.Join(" and ", list) + "."; } return "\nReduces all damage you take."; } catch { return "\nReduces all damage you take."; } } private static void Postfix(string original, ref string __result) { string text = __result; try { AplicarNotasDoFunil(original, ref __result); } catch (Exception e) { __result = text; RegistrarFalhaIgnorada("postfix do funil OptionsManager.Localize", e); } } private static void RegistrarFalhaIgnorada(string gancho, Exception e) { try { string text = gancho + " | " + e.GetType().FullName + ": " + e.Message; if (_falhasRegistradas.Count < 25 && _falhasRegistradas.Add(text)) { Plugin.Log.LogError((object)("BetterTooltips: falha IGNORADA em " + gancho + " (texto do jogo mantido intacto) — " + text)); } } catch { } } private static void AplicarNotasDoFunil(string original, ref string __result) { if (original == null || __result == null || __result != original) { return; } if (!_loggedAlive) { _loggedAlive = true; string text = ((original.Length > 60) ? (original.Substring(0, 60) + "...") : original); Plugin.Log.LogInfo((object)("BetterTooltips: postfix ativo (1a localizacao em ingles: '" + text + "')")); } string value2; if (TextFixes.TryGetValue(original, out var value)) { __result = value; if (_appliedFixes.Add(original)) { Plugin.Log.LogInfo((object)("BetterTooltips: corrigido '" + original + "' -> '" + value + "'")); } } else if (TextAppends.TryGetValue(original, out value2)) { __result = AnexarNota(__result, value2); if (_appliedAppends.Add(original)) { Plugin.Log.LogInfo((object)("BetterTooltips: explicação adicionada a '" + original + "'")); } } else { Match match = AttributePowerupRegex.Match(original); if (match.Success) { string text2 = BuildAttributeEffects(match.Groups[1].Value); if (text2 != null) { __result = AnexarNota(__result, text2); if (_appliedAppends.Add(original)) { Plugin.Log.LogInfo((object)("BetterTooltips: efeitos por ponto adicionados a '" + original + "'")); } } } else { if (DamageReductionRegex.IsMatch(original)) { string text3 = BuildDamageReductionNote(); if (text3 != null) { __result = AnexarNota(__result, text3); if (_appliedAppends.Add(original)) { Plugin.Log.LogInfo((object)("BetterTooltips: ordem de redução adicionada a '" + original + "'")); } } } bool flag = false; (Regex, string)[] statusAttributeRules = StatusAttributeRules; for (int i = 0; i < statusAttributeRules.Length; i++) { (Regex, string) tuple = statusAttributeRules[i]; if (tuple.Item1.IsMatch(original)) { string text4 = BuildAttributeEffects(tuple.Item2); if (text4 != null) { __result = AnexarNota(__result, text4); flag = true; } break; } } if (!flag) { statusAttributeRules = FortuneAttributeRules; for (int i = 0; i < statusAttributeRules.Length; i++) { (Regex, string) tuple2 = statusAttributeRules[i]; if (tuple2.Item1.IsMatch(original)) { string text5 = BuildAttributeEffects(tuple2.Item2); if (text5 != null) { __result = AnexarNota(__result, text5); flag = true; } break; } } } if (!flag) { string[] resistanceReductionPrefixes = ResistanceReductionPrefixes; foreach (string value3 in resistanceReductionPrefixes) { if (original.StartsWith(value3, StringComparison.Ordinal)) { __result = AnexarNota(__result, "\nResistances reduce their damage type by the listed %. If a resistance goes negative, that damage type is amplified instead."); flag = true; break; } } } if (!flag) { (Regex, string, string)[] skillGlossaryRules = SkillGlossaryRules; for (int i = 0; i < skillGlossaryRules.Length; i++) { (Regex, string, string) tuple3 = skillGlossaryRules[i]; if (IsGlossaryLabel(original)) { break; } if (tuple3.Item1.IsMatch(original) && !original.Contains(tuple3.Item3)) { __result = AnexarNota(__result, tuple3.Item2); flag = true; break; } } } if (!flag) { string text6 = original.ToLower(); bool flag2 = text6.Contains("increased") || text6.Contains("added") || text6.Contains("lowered") || text6.Contains("reduced") || text6.Contains("granted"); bool flag3 = RotulosDeStatusSemNota.Contains(original); if (flag3 && _rotulosDeStatusAvisados.Add(original)) { Plugin.Log.LogInfo((object)("BetterTooltips: nota de mecanica NAO anexada ao NOME de status '" + original + "' (BUG-33: o feed de combate localiza o nome; a explicacao continua na descricao do status)")); } if (!flag3 && flag2 && ArmorAffixRegex.IsMatch(original) && !ArmorValueSourceRegex.IsMatch(original) && !original.Contains("blocks damage")) { string text7 = BuildArmorNote(); if (text7 != null) { if (ArmorQueTambemDaMagicArmor.Contains(original)) { text7 = "\nAlso increases Magic Armor by the same amount." + text7; } __result = AnexarNota(__result, text7); flag = true; } } else if (!flag3 && flag2 && ResistAffixRegex.IsMatch(original) && !original.Contains("Summon resistance") && !original.Contains("resistances reduce")) { __result = AnexarNota(__result, "\nResistances reduce their damage type by the listed %. If a resistance goes negative, that damage type is amplified instead."); flag = true; } } if (flag && _appliedAppends.Add(original)) { Plugin.Log.LogInfo((object)("BetterTooltips: explicação adicionada a '" + original + "'")); } } } if (__result.Contains(" ")) { string text8 = __result; while (__result.Contains(" ")) { __result = __result.Replace(" ", " "); } if (_appliedFixes.Add("espacos:" + text8)) { Plugin.Log.LogInfo((object)("BetterTooltips: espacos normalizados em '" + text8 + "'")); } } if (original == "Attackers take Fire Damage.") { string text9 = ShrineAuraPatch.FraseAlvosDoFlame(original); if (!string.IsNullOrEmpty(text9)) { int num = __result.IndexOf("<color=#C8B090>", StringComparison.Ordinal); __result = ((num >= 0) ? __result.Insert(num + "<color=#C8B090>".Length, text9 + " ") : AnexarNota(__result, "\n<color=#C8B090>" + text9 + "</color>")); } } if (original == "Take [0]% of your Max Health in Shadow Damage per turn.") { string text10 = ShrineAuraPatch.LinhaDecayComValor(original); if (!string.IsNullOrEmpty(text10)) { __result = __result.Replace(original, text10); } } if (GlobulePatch.EhGlobule(original)) { string text11 = GlobulePatch.FraseSustenance(original); if (!string.IsNullOrEmpty(text11)) { int num2 = __result.LastIndexOf("</color>", StringComparison.Ordinal); __result = ((num2 >= 0) ? (__result.Substring(0, num2) + " " + text11 + __result.Substring(num2)) : AnexarNota(__result, "\n<color=#C8B090>" + text11 + "</color>")); } } if (ShrineAuraPatch.IsShrineKey(original)) { string text12 = ShrineAuraPatch.AcumuladoShrines(original); if (!string.IsNullOrEmpty(text12)) { __result = AnexarNota(__result, text12); } Plugin.Log.LogInfo((object)("[Shrine RV-23] chave '" + original + "' -> resultado final: '" + ((__result.Length > 140) ? (__result.Substring(0, 140) + "...") : __result) + "'")); } } } [HarmonyPatch] public static class ShrineAuraPatch { private enum TipoDoEfeitoDaAura { Atributo, Gatilho, Outro } private static readonly HashSet<string> ShrineKeys = new HashSet<string> { "Attackers take Fire Damage.", "Take [0]% of your Max Health in Shadow Damage per turn.", "Damage increased by [0]%. ", "Reduces Damage taken by [0]%. ", "Critical hit chance increased by [0]%.", "Increases dodge chance by [0]%.", "Lifesteal increased by [0]%.", "Decreases the cost of mana using abilities by [0]%.", "Your attacks have a [0]% chance to stun the target.", "Recover [0]% of maximum health each turn. ", "Recover [0]% of maximum mana each turn. ", "Damage increased by [0]%. Damage taken increased by [0]%. " }; private static readonly HashSet<string> _marcas = new HashSet<string>(); private static bool _vivo = false; internal const string ChaveFlame = "Attackers take Fire Damage."; internal const string NomeStatusFlame = "Flame Shrine Aura"; private const string FormulaDanoFlameCru = "Mathf.Max(1, Mathf.Round((Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.025f, .08f, .1f, .12f, .14f, .05f)) * (1 + (Source[\"ShrineEffectBonus\"] / 100))))"; private const string FormulaDanoFlameSemBonus = "Mathf.Max(1, Mathf.Round(Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.025f, .08f, .1f, .12f, .14f, .05f)))"; internal const string ChaveDecay = "Take [0]% of your Max Health in Shadow Damage per turn."; internal const string ChaveDwarven = "Your attacks have a [0]% chance to stun the target."; private const string FormulaDanoDecay = "Mathf.Round((Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.05f, .1f, .12f, .15f, .2f, .1f)) * (1 + (Source[\"ShrineEffectBonus\"] / 100)))"; private const string FormulaDanoDecaySemBonus = "Mathf.Round(Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.05f, .1f, .12f, .15f, .2f, .1f))"; private const string PorcentagemDoDecay = "Target.GetValueByEnemyType(.05f, .1f, .12f, .15f, .2f, .1f)"; internal const string MarcadorLinhaDeAuras = "Your active shrine auras:"; private static readonly string[] OrdemDosAtributos = new string[8] { "DamageMod", "DamageReduction", "CritChance", "DodgeChance", "LifeOnHit", "HealthPerTurnPercent", "ManaPerTurnPercent", "ManaCostMod" }; private static bool _avisosDeCacheRegistrados; public static bool IsShrineKey(string text) { if (text != null) { return ShrineKeys.Contains(text); } return false; } private static bool UsesShrineBonus(string[] expressions) { if (expressions == null) { return false; } foreach (string text in expressions) { if (text != null && text.Contains("ShrineEffectBonus")) { return true; } } return false; } [HarmonyPatch(typeof(Tooltip), "ApplyDescriptionExpressions", new Type[] { typeof(string), typeof(string[]), typeof(GameFunctionParameters), typeof(float), typeof(float) })] [HarmonyPrefix] private static void FixShrineExpressionParams(Tooltip __instance, string[] expressions, ref GameFunctionParameters __2) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) try { if (!UsesShrineBonus(expressions)) { return; } if (!_vivo) { _vivo = true; Plugin.Log.LogInfo((object)"[Shrine RV-22] prefix de parametros ativo em ApplyDescriptionExpressions (__2 = GameFunctionParameters)"); } bool flag = ((GameFunctionParameters)(ref __2)).Target == null; bool flag2 = ((GameFunctionParameters)(ref __2)).Source == null; bool flag3 = !flag2 && EhPersonagemVazioDoShrine(((GameFunctionParameters)(ref __2)).Source); if (!flag && !flag2 && !flag3) { return; } Game instance = Game.Instance; if ((Object)(object)((instance != null) ? instance.GetAttribute("ShrineEffectBonus") : null) == (Object)null) { Marca("atributo ShrineEffectBonus ausente neste build — parametros intactos"); return; } Character val = Receptor(__instance, __2); if (val == null) { Marca("nenhum receptor disponivel — parametros intactos ([0] fica na base)"); return; } if (flag2 || flag3) { ((GameFunctionParameters)(ref __2)).Source = val; } if (flag) { ((GameFunctionParameters)(ref __2)).Target = val; } Marca("params: Target" + (flag ? "(vazio)->" : "(intacto)") + val.CharacterName + " Source" + (flag2 ? "(vazio)->" : (flag3 ? "(shrine)->" : "(intacto)")) + ((flag2 || flag3) ? val.CharacterName : "(mantido)")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Shrine RV-22] prefix falhou (parametros devolvidos intactos): " + ex.GetType().Name + ": " + ex.Message)); } } private static Character Receptor(Tooltip tooltip, GameFunctionParameters parametros) { try { Tooltip val = tooltip; if ((Object)(object)val == (Object)null && (Object)(object)GUIManager.instance != (Object)null) { val = GUIManager.instance.tooltip; } if ((Object)(object)val != (Object)null) { Character tooltipCharacter = val.TooltipCharacter; if (tooltipCharacter != null) { return tooltipCharacter; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Shrine RV-22] TooltipCharacter indisponivel: " + ex.GetType().Name + ": " + ex.Message)); } try { NetworkingManager instance = NetworkingManager.Instance; object obj; if (instance == null) { obj = null; } else { NetworkManager networkManager = instance.NetworkManager; if (networkManager == null) { obj = null; } else { Root root = ((Observer<Root>)(object)networkManager).Root; obj = ((root != null) ? root.WorldCharacter : null); } } Character val2 = (Character)obj; if (val2 != null) { return val2; } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[Shrine RV-22] WorldCharacter indisponivel: " + ex2.GetType().Name + ": " + ex2.Message)); } if (((GameFunctionParameters)(ref parametros)).Source == null) { return ((GameFunctionParameters)(ref parametros)).Target; } return ((GameFunctionParameters)(ref parametros)).Source; } private static bool EhPersonagemVazioDoShrine(Character fonte) { if (fonte == null) { return false; } try { NetworkingManager instance = NetworkingManager.Instance; object obj; if (instance == null) { obj = null; } else { NetworkManager networkManager = instance.NetworkManager; if (networkManager == null) { obj = null; } else { Root root = ((Observer<Root>)(object)networkManager).Root; obj = ((root != null) ? root.WorldCharacter : null); } } Character val = (Character)obj; return val != null && fonte == val; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Shrine RV-34] WorldCharacter indisponivel: " + ex.GetType().Name + ": " + ex.Message)); return false; } } internal static Character ReceptorDaTooltip() { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) return Receptor(null, default(GameFunctionParameters)); } public static string FraseAlvosDoFlame(string chaveDaTooltip) { try { if (!string.Equals(chaveDaTooltip, "Attackers take Fire Damage.", StringComparison.Ordinal)) { return ""; } List<Character> list = AlvosNaAreaDoFlame(); if (list.Count == 0) { Marca("RV-33 Flame sem alvo: ninguem com o status da aura vivo agora (nenhum numero)"); return ""; } List<string> list2 = new List<string>(); foreach (Character item in list) { if (item != null && !(item.MaxHealth <= 0f)) { if (!ValorDaExpressao(FormulaDoDano("Mathf.Max(1, Mathf.Round((Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.025f, .08f, .1f, .12f, .14f, .05f)) * (1 + (Source[\"ShrineEffectBonus\"] / 100))))", "Mathf.Max(1, Mathf.Round(Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.025f, .08f, .1f, .12f, .14f, .05f)))"), item, item, out var valor)) { Marca("RV-34 Flame alvo '" + item.CharacterName + "' sem numero: formula nao avaliada"); continue; } string text = (string.IsNullOrEmpty(item.CharacterName) ? "(sem nome)" : item.CharacterName); list2.Add(text + " " + valor.ToString("0.#")); Marca("RV-34 Flame alvo '" + text + "': MaxHealth=" + item.MaxHealth.ToString("0.#") + " tipo=" + TipoDoAlvo(item) + " bonus=" + BonusDoReceptor(item) + " dano=" + valor.ToString("0.#")); } } if (list2.Count == 0) { return ""; } return "In the aura now (raw damage it takes as the attacker, from its own Max Health and its own Shrine Effect Bonus): " + string.Join("; ", list2.ToArray()) + "."; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Shrine RV-33] alvos do Flame falharam (texto intacto): " + ex.GetType().Name + ": " + ex.Message)); return ""; } } private static List<Character> AlvosNaAreaDoFlame() { List<Character> list = new List<Character>(); try { NetworkingManager instance = NetworkingManager.Instance; object obj; if (instance == null) { obj = null; } else { NetworkManager networkManager = instance.NetworkManager; if (networkManager == null) { obj = null; } else { Root root = ((Observer<Root>)(object)networkManager).Root; obj = ((root != null) ? root.AllCharacters : null); } } ObservableList<Character> val = (ObservableList<Character>)obj; if (val == null || val.Count == 0) { return list; } foreach (Character item in val) { if (item == null || item.ActionStatuses == null) { continue; } foreach (ActionStatus actionStatus in item.ActionStatuses) { if (actionStatus != null && !((Object)(object)actionStatus.ActionStatusInfo == (Object)null) && (string.Equals(actionStatus.ActionStatusInfo.Description, "Attackers take Fire Damage.", StringComparison.Ordinal) || string.Equals(((Object)actionStatus.ActionStatusInfo).name, "Flame Shrine Aura", StringComparison.Ordinal))) { list.Add(item); break; } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Shrine RV-33] varredura de alvos falhou (" + ex.GetType().Name + "): " + ex.Message)); list.Clear(); } return list; } private static string TipoDoAlvo(Character c) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) try { return c.IsAI ? ((object)c.EnemyType/*cast due to .constrained prefix*/).ToString() : "player"; } catch (Exception ex) { return "(" + ex.GetType().Name + ")"; } } private static string FormulaDoDano(string comFator, string semFator) { Game instance = Game.Instance; if ((Object)(object)((instance != null) ? instance.GetAttribute("ShrineEffectBonus") : null) != (Object)null) { return comFator; } Marca("RV-34 fator do ShrineEffectBonus NAO aplicado: atributo ausente neste build — o numero sai como estava, SEM o fator (nada estimado)"); return semFator; } private static float FatorDoBonus(Character personagem) { if (personagem == null) { return 1f; } Game instance = Game.Instance; if ((Object)(object)((instance != null) ? instance.GetAttribute("ShrineEffectBonus") : null) == (Object)null) { Marca("RV-34 reserva do Decay sem fator: atributo ShrineEffectBonus ausente neste build"); return 1f; } try { return 1f + personagem["ShrineEffectBonus"] / 100f; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Shrine RV-34] leitura do ShrineEffectBonus falhou (fator=1): " + ex.GetType().Name + ": " + ex.Message)); return 1f; } } public static string LinhaDecayComValor(string chaveDaTooltip) { try { if (!string.Equals(chaveDaTooltip, "Take [0]% of your Max Health in Shadow Damage per turn.", StringComparison.Ordinal)) { return null; } Character val = ReceptorDaTooltip(); if (val == null) { Marca("RV-33 Decay sem numero: nenhum receptor (personagem em foco) disponivel"); return null; } if (val.MaxHealth <= 0f) { Marca("RV-33 Decay sem numero: receptor sem MaxHealth"); return null; } if (!ValorDaExpressao(FormulaDoDano("Mathf.Round((Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.05f, .1f, .12f, .15f, .2f, .1f)) * (1 + (Source[\"ShrineEffectBonus\"] / 100)))", "Mathf.Round(Target[\"MaxHealth\"] * Target.GetValueByEnemyType(.05f, .1f, .12f, .15f, .2f, .1f))"), val, val, out var valor)) { if (!ValorDaExpressao("Target.GetValueByEnemyType(.05f, .1f, .12f, .15f, .2f, .1f)", val, val, out var valor2)) { Marca("RV-34 Decay sem numero: formula e % nao avaliadas pelo interpretador"); return null; } valor = Mathf.Round(val.MaxHealth * valor2 * FatorDoBonus(val)); Marca("RV-34 Decay reserva: formula completa nao avaliada; dano montado a partir da % e do bonus do personagem"); } string text = "Take [0]% of your Max Health in Shadow Damage per turn.".Substring(0, "Take [0]% of your Max Health in Shadow Damage per turn.".Length - 1) + " (" + valor.ToString("0.#") + " damage per turn for you)."; Marca("RV-34 linha do Decay: " + val.CharacterName + " MaxHealth=" + val.MaxHealth.ToString("0.#") + " tipo=" + TipoDoAlvo(val) + " bonus=" + BonusDoReceptor(val) + " -> '" + text + "'"); return text; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Shrine RV-33] valor do Decay falhou (linha intacta): " + ex.GetType().Name + ": " + ex.Message)); return null; } } private static void Marca(string linha) { try { if (_marcas.Count < 200 && _marcas.Add(linha)) { Plugin.Log.LogInfo((object)("[Shrine RV-23] " + linha)); } } catch { } } private static string Format(string attr, float v) { int num = InteiroDoJogo(v); switch (attr) { case "DamageReduction": if (num <= 0) { return "Damage taken +" + Mathf.Abs(num) + "%"; } return "Damage taken −" + num + "%"; case "ManaCostMod": if (num > 0) { return "Mana Costs increased by " + num + "%"; } return "Mana Costs reduced by " + Mathf.Abs(num) + "%"; case "DamageMod": return "Damage " + ComSinal(v) + "%"; case "CritChance": return "Crit Chance " + ComSinal(v) + "%"; case "DodgeChance": return "Dodge " + ComSinal(v) + "%"; case "LifeOnHit": return "Life Steal " + ComSinal(v) + "%"; case "HealthPerTurnPercent": return "Health per turn " + ComSinal(v) + "%"; case "ManaPerTurnPercent": return "Mana per turn " + ComSinal(v) + "%"; default: return null; } } private static string ComSinal(float v) { int num = InteiroDoJogo(v); return ((num >= 0) ? "+" : "−") + Mathf.Abs(num); } private static int InteiroDoJogo(float v) { if (!float.IsNaN(v) && !float.IsInfinity(v)) { return Mathf.CeilToInt(v); } return 0; } private static string TotalComSinal(string nome, float v) { int num = InteiroDoJogo(v); return ComSinal(string.Equals(nome, "DamageReduction", StringComparison.Ordinal) ? (-num) : num) + "%"; } public static string AcumuladoShrines(string chaveDaTooltip) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) try { Game instance = Game.Instance; if ((Object)(object)((instance != null) ? instance.GetAttribute("ShrineEffectBonus") : null) == (Object)null) { return ""; } Character val = Receptor(null, default(GameFunctionParameters)); if (val == null) { Marca("acumulado: nenhum receptor disponivel"); return ""; } List<ActionStatus> list = AurasVivas(val); if (list.Count == 0) { Marca("RV-31 sem linha: " + val.CharacterName + " nao tem aura de shrine viva agora (tooltip '" + chaveDaTooltip + "')"); return ""; } List<string> repeticoes; List<ActionStatus> list2 = AurasUnicas(list, out repeticoes); if (repeticoes.Count > 0) { Marca("RV-46 instancias repetidas na lista viva de " + val.CharacterName + ": [" + string.Join(", ", repeticoes.ToArray()) + "] — o motor soma cada instancia (Character.cs:8494 + TotalStacks em Character.cs:8563) e o TETO do atributo corta o total; a CONTRIBUICAO conta cada aura UMA vez (e o numero que a linha branca do proprio shrine mostra)"); } List<string> deAtributo; List<string> deGatilho; List<ActionStatus> unicas = AurasQueContamPorInstancia(list, out deAtributo, out deGatilho); if (deGatilho.Count > 0) { Marca("RV-46/DWA-2 tipo do efeito: atributo=[" + string.Join(", ", deAtributo.ToArray()) + "] (1x por aura: o motor soma as instancias e o teto do atributo corta — l.37194/37263 + l.40571-40578) | gatilho=[" + string.Join(", ", deGatilho.ToArray()) + "] (1 item por INSTANCIA: o gatilho entra na lista uma vez por status vivo — l.33489-33508 —, o laco percorre todas as entradas — l.40953-40959 — e a chance e rolada de novo em cada uma — l.41211-41216; o gatilho do Dwarven tem Cooldown=0 e MaxNumUses va