Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DamageSplash v0.1.3
DamageSplash.dll
Decompiled 2 hours 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.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DamageSplash.Core; using DamageSplash.Patches; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("DamageSplash")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Bigger, bolder, more festive floating damage numbers for Valheim.")] [assembly: AssemblyFileVersion("0.1.3.0")] [assembly: AssemblyInformationalVersion("0.1.3+09f1e350c897f8c9da44ad04e661b9351188ad7d")] [assembly: AssemblyProduct("DamageSplash")] [assembly: AssemblyTitle("DamageSplash")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DamageSplash { [BepInPlugin("com.jumpingmushroom.damagesplash", "DamageSplash", "0.1.3")] [BepInProcess("valheim.exe")] [BepInProcess("valheim.x86_64")] public sealed class DamageSplashPlugin : BaseUnityPlugin { public const string PluginGuid = "com.jumpingmushroom.damagesplash"; public const string PluginName = "DamageSplash"; public const string PluginVersion = "0.1.3"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PluginConfig.Bind(((BaseUnityPlugin)this).Config); ConsoleCommands.Register(); _harmony = new Harmony("com.jumpingmushroom.damagesplash"); _harmony.PatchAll(typeof(DamageSplashPlugin).Assembly); PluginConfig.Changed += OnConfigChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)"DamageSplash 0.1.3 loaded."); } private void OnDestroy() { PluginConfig.Changed -= OnConfigChanged; DamageTextPatches.ApplyMaxDistance(unloading: true); EdgeFlash.Destroy(); SplashPool.Clear(); if (_harmony != null) { _harmony.UnpatchSelf(); } } private void Update() { Demo.Update(Time.time); EdgeFlash.Update(Time.deltaTime); } private static void OnConfigChanged() { Styles.Invalidate(); SplashPool.Rematerial(); EdgeFlash.Invalidate(); Compat.Detect(); DamageTextPatches.ApplyMaxDistance(); } } public static class PluginConfig { public const string PresetCustom = "Custom"; public const string VisibilityAll = "All"; public const string VisibilityMine = "Mine"; public const string VisibilityNone = "None"; public static readonly string[] PresetNames = new string[4] { "Vanilla", "Bold", "Festive", "Custom" }; public static readonly string[] AnimPresetNames = new string[6] { "Vanilla", "Pop", "Arc", "Fountain", "Bounce", "Custom" }; public static ConfigEntry<bool> Enabled; public static ConfigEntry<string> Preset; public static ConfigEntry<float> MaxDistance; public static ConfigEntry<bool> HideZeros; public static ConfigEntry<int> MaxAlive; public static ConfigEntry<bool> Verbose; public static ConfigEntry<string> FontName; public static ConfigEntry<bool> FauxBold; public static ConfigEntry<float> NearSize; public static ConfigEntry<float> FarSize; public static ConfigEntry<float> NearDistance; public static ConfigEntry<float> FarDistance; public static ConfigEntry<float> FaceDilate; public static ConfigEntry<float> OutlineWidth; public static ConfigEntry<Color> OutlineColor; public static ConfigEntry<bool> Shadow; public static ConfigEntry<float> ShadowOffset; public static ConfigEntry<Color> ColorNormal; public static ConfigEntry<Color> ColorResistant; public static ConfigEntry<Color> ColorWeak; public static ConfigEntry<Color> ColorImmune; public static ConfigEntry<Color> ColorHeal; public static ConfigEntry<Color> ColorTooHard; public static ConfigEntry<Color> ColorBlocked; public static ConfigEntry<Color> ColorBonus; public static ConfigEntry<Color> ColorSelfDamage; public static ConfigEntry<Color> ColorSelfNoDamage; public static ConfigEntry<bool> UseHitContext; public static ConfigEntry<bool> ElementalTints; public static ConfigEntry<Color> ColorFire; public static ConfigEntry<Color> ColorFrost; public static ConfigEntry<Color> ColorLightning; public static ConfigEntry<Color> ColorPoison; public static ConfigEntry<Color> ColorSpirit; public static ConfigEntry<bool> SneakEnabled; public static ConfigEntry<string> SneakTag; public static ConfigEntry<Color> SneakColor; public static ConfigEntry<bool> CritEnabled; public static ConfigEntry<string> CritTag; public static ConfigEntry<Color> CritColor; public static ConfigEntry<bool> KillEnabled; public static ConfigEntry<string> KillTag; public static ConfigEntry<Color> KillColor; public static ConfigEntry<float> KillDurationScale; public static ConfigEntry<float> TagScale; public static ConfigEntry<float> DotMergeWindow; public static ConfigEntry<float> HitMergeWindow; public static ConfigEntry<float> MergeMaxLife; public static ConfigEntry<string> Visibility; public static ConfigEntry<bool> EdgeFlash; public static ConfigEntry<float> EdgeFlashPercent; public static ConfigEntry<Color> EdgeFlashColor; public static ConfigEntry<float> EdgeFlashFade; public static ConfigEntry<float> EdgeFlashThickness; public static ConfigEntry<bool> YieldToOtherMods; public static ConfigEntry<bool> DebugSimulateConflict; public static ConfigEntry<bool> MagnitudeScaling; public static ConfigEntry<float> SmallBelowPercent; public static ConfigEntry<float> BigAbovePercent; public static ConfigEntry<float> HugeAbovePercent; public static ConfigEntry<float> SmallBelowDamage; public static ConfigEntry<float> BigAboveDamage; public static ConfigEntry<float> HugeAboveDamage; public static ConfigEntry<float> ScaleSmall; public static ConfigEntry<float> ScaleBig; public static ConfigEntry<float> ScaleHuge; public static ConfigEntry<string> AnimPreset; public static ConfigEntry<float> Duration; public static ConfigEntry<float> PopFrom; public static ConfigEntry<float> PopDuration; public static ConfigEntry<float> Overshoot; public static ConfigEntry<float> FadeIn; public static ConfigEntry<float> Tilt; public static ConfigEntry<float> RiseSpeed; public static ConfigEntry<float> Gravity; public static ConfigEntry<float> Spray; public static ConfigEntry<float> ExitShrink; public static ConfigEntry<bool> Bounce; public static ConfigEntry<float> Jitter; private static ConfigFile _cfg; private static bool _applying; private const string FontDescription = "Font for the numbers. \"Vanilla\" keeps the game's own damage-text font. The list is filled with every TextMeshPro font the game has loaded once you are in a world; use `splash fonts` to refresh it."; public static event Action Changed; public static void Bind(ConfigFile cfg) { //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_050d: Unknown result type (might be due to invalid IL or missing references) //IL_054c: Unknown result type (might be due to invalid IL or missing references) //IL_058b: Unknown result type (might be due to invalid IL or missing references) //IL_0735: Unknown result type (might be due to invalid IL or missing references) //IL_0774: Unknown result type (might be due to invalid IL or missing references) //IL_07b3: Unknown result type (might be due to invalid IL or missing references) //IL_0864: Unknown result type (might be due to invalid IL or missing references) //IL_08a3: Unknown result type (might be due to invalid IL or missing references) //IL_08e2: Unknown result type (might be due to invalid IL or missing references) //IL_0921: Unknown result type (might be due to invalid IL or missing references) //IL_0960: Unknown result type (might be due to invalid IL or missing references) //IL_0af1: Unknown result type (might be due to invalid IL or missing references) _cfg = cfg; int num = 0; Enabled = cfg.Bind<bool>("1 General", "Enabled", true, D("Turn the mod off and the vanilla renderer takes over on the next hit.", num++)); Preset = cfg.Bind<string>("1 General", "Preset", "Festive", D("Vanilla: the stock look. Bold: same motion, bigger outlined font. Festive: bold plus a pop and an arc. Choosing one overwrites the entries below; changing any of them flips this to Custom.", num++, PresetNames)); MaxDistance = cfg.Bind<float>("1 General", "MaxDistance", 30f, D("Numbers further than this from the camera are not shown. Vanilla: 30.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f))); HideZeros = cfg.Bind<bool>("1 General", "HideZeros", false, D("Do not show hits for 0 damage at all. Vanilla shows a grey 0.", num++)); MaxAlive = cfg.Bind<int>("1 General", "MaxAlive", 64, D("How many numbers can be on screen at once; the oldest is dropped beyond that. Vanilla has no cap (200 for zeros).", num++, (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 400))); Verbose = cfg.Bind<bool>("1 General", "Verbose", false, D("Extra lines in the BepInEx log.", num++, null, advanced: true)); FontName = cfg.Bind<string>("2 Font", "Font", "Vanilla", D("Font for the numbers. \"Vanilla\" keeps the game's own damage-text font. The list is filled with every TextMeshPro font the game has loaded once you are in a world; use `splash fonts` to refresh it.", num++)); FauxBold = cfg.Bind<bool>("2 Font", "FauxBold", false, D("Apply TextMeshPro's bold style on top of the font. Useful when only a regular weight is loaded.", num++)); NearSize = cfg.Bind<float>("2 Font", "NearSize", 30f, D("Font size for hits at or closer than NearDistance. Vanilla: 16.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 96f))); FarSize = cfg.Bind<float>("2 Font", "FarSize", 14f, D("Font size for hits at or beyond FarDistance. Vanilla: 8.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 96f))); NearDistance = cfg.Bind<float>("2 Font", "NearDistance", 8f, D("Metres. Size shrinks smoothly from NearSize at this distance to FarSize at FarDistance. Set both equal for vanilla's hard step at 10 m.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f))); FarDistance = cfg.Bind<float>("2 Font", "FarDistance", 30f, D("Metres. See NearDistance.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f))); FaceDilate = cfg.Bind<float>("2 Font", "Boldness", 0.28f, D("Fattens (positive) or thins (negative) the strokes. TextMeshPro's outline grows half inward, so pair an outline with some boldness or thin fonts go black. Vanilla: 0.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.6f))); OutlineWidth = cfg.Bind<float>("2 Font", "OutlineWidth", 0.18f, D("Outline thickness, 0 to 1 in TextMeshPro units. 0 disables the outline. Keep it modest; see Boldness. Vanilla: 0.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))); OutlineColor = cfg.Bind<Color>("2 Font", "OutlineColor", new Color(0f, 0f, 0f, 1f), D("Outline colour.", num++)); Shadow = cfg.Bind<bool>("2 Font", "Shadow", true, D("Soft drop shadow behind the number. Vanilla: off.", num++)); ShadowOffset = cfg.Bind<float>("2 Font", "ShadowOffset", 0.3f, D("Shadow offset, 0 to 1.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))); ColorNormal = cfg.Bind<Color>("3 Colours", "Normal", Color.white, D("Plain hits on enemies and things.", num++)); ColorResistant = cfg.Bind<Color>("3 Colours", "Resistant", new Color(0.6f, 0.6f, 0.6f, 1f), D("Target resists the damage type.", num++)); ColorWeak = cfg.Bind<Color>("3 Colours", "Weak", new Color(1f, 1f, 0f, 1f), D("Target is weak to the damage type.", num++)); ColorImmune = cfg.Bind<Color>("3 Colours", "Immune", new Color(0.6f, 0.6f, 0.6f, 1f), D("Target is immune.", num++)); ColorHeal = cfg.Bind<Color>("3 Colours", "Heal", new Color(0.5f, 1f, 0.5f, 0.7f), D("Healing, shown as +N.", num++)); ColorTooHard = cfg.Bind<Color>("3 Colours", "TooHard", new Color(0.8f, 0.7f, 0.7f, 1f), D("The \"too hard\" message on rocks and trees your tool cannot damage.", num++)); ColorBlocked = cfg.Bind<Color>("3 Colours", "Blocked", Color.white, D("Damage you blocked with a shield or weapon.", num++)); ColorBonus = cfg.Bind<Color>("3 Colours", "Bonus", new Color(1f, 0.63f, 0.24f, 1f), D("Crafting and gathering bonuses (+N).", num++)); ColorSelfDamage = cfg.Bind<Color>("3 Colours", "SelfDamage", new Color(1f, 0f, 0f, 1f), D("Damage taken by you or your tames.", num++)); ColorSelfNoDamage = cfg.Bind<Color>("3 Colours", "SelfNoDamage", new Color(0.5f, 0.5f, 0.5f, 1f), D("A 0 on you or your tames.", num++)); UseHitContext = cfg.Bind<bool>("5 Hits", "UseHitContext", true, D("Read the hit behind each number, which is what sneak, crit, kill, elemental tints and magnitude all rest on. Off means every number is styled by its kind alone, as vanilla does. Only hits resolved on your own machine carry this: yours on things you own, and everything that hits you.", num++)); MagnitudeScaling = cfg.Bind<bool>("5 Hits", "MagnitudeScaling", true, D("Size the number by how much the hit mattered. With hit context that is a share of the target's maximum health, so 30 on a greyling reads big and 30 on a fuling berserker does not; without it, by the raw number.", num++)); ElementalTints = cfg.Bind<bool>("5 Hits", "ElementalTints", true, D("Colour plain hits by their damage type. Weak, resistant and immune hits keep their own colour, because what they say is worth more than a tint.", num++)); SneakEnabled = cfg.Bind<bool>("5 Hits", "SneakEnabled", true, D("Mark sneak attacks, the multiplier Valheim gives for hitting an unaware target.", num++)); CritEnabled = cfg.Bind<bool>("5 Hits", "CritEnabled", true, D("Mark hits on a staggered creature, which Valheim doubles. This is the closest thing the game has to a critical hit.", num++)); KillEnabled = cfg.Bind<bool>("5 Hits", "KillEnabled", true, D("Mark the blow that kills.", num++)); SneakTag = cfg.Bind<string>("5 Hits", "SneakTag", "SNEAK", D("Word shown with a sneak attack. Empty for none.", num++)); CritTag = cfg.Bind<string>("5 Hits", "CritTag", "CRIT", D("Word shown with a hit on a staggered creature. Empty for none.", num++)); KillTag = cfg.Bind<string>("5 Hits", "KillTag", "KILL", D("Word shown with a killing blow. Empty for none. Try SKAL or VALHALLA.", num++)); SneakColor = cfg.Bind<Color>("5 Hits", "SneakColor", new Color(1f, 0.85f, 0.3f, 1f), D("Colour of a sneak attack.", num++)); CritColor = cfg.Bind<Color>("5 Hits", "CritColor", new Color(1f, 0.55f, 0.15f, 1f), D("Colour of a hit on a staggered creature.", num++)); KillColor = cfg.Bind<Color>("5 Hits", "KillColor", new Color(1f, 0.3f, 0.25f, 1f), D("Colour of a killing blow.", num++)); KillDurationScale = cfg.Bind<float>("5 Hits", "KillDurationScale", 1.6f, D("How much longer a killing blow stays on screen.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f))); TagScale = cfg.Bind<float>("5 Hits", "TagScale", 0.55f, D("Size of the tag word relative to the number.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1.5f))); ColorFire = cfg.Bind<Color>("5 Hits", "FireColor", new Color(1f, 0.5f, 0.15f, 1f), D("Tint for fire damage.", num++)); ColorFrost = cfg.Bind<Color>("5 Hits", "FrostColor", new Color(0.55f, 0.85f, 1f, 1f), D("Tint for frost damage.", num++)); ColorLightning = cfg.Bind<Color>("5 Hits", "LightningColor", new Color(1f, 0.95f, 0.5f, 1f), D("Tint for lightning damage.", num++)); ColorPoison = cfg.Bind<Color>("5 Hits", "PoisonColor", new Color(0.55f, 0.9f, 0.3f, 1f), D("Tint for poison damage.", num++)); ColorSpirit = cfg.Bind<Color>("5 Hits", "SpiritColor", new Color(0.85f, 0.95f, 1f, 1f), D("Tint for spirit damage.", num++)); DotMergeWindow = cfg.Bind<float>("7 Merging", "DotMergeWindow", 1.2f, D("Seconds. Burning, poison and the other ticks on one victim add into a single number that climbs, instead of stacking up one per tick. 0 turns it off.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f))); HitMergeWindow = cfg.Bind<float>("7 Merging", "HitMergeWindow", 0f, D("The same for ordinary hits on one target, for volleys and multi-hit swings. 0 (the default) keeps every hit its own number, which is usually what you want to read.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f))); MergeMaxLife = cfg.Bind<float>("7 Merging", "MergeMaxLife", 6f, D("Seconds. A climbing number stops accepting more after this long and a fresh one starts, so something burning forever does not leave one number on screen forever.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f))); Visibility = cfg.Bind<string>("8 Self", "Visibility", "All", D("All: every number, as vanilla does. Mine: only hits you dealt and damage done to you. None: no damage numbers at all, though blocks, heals and bonuses still show. Only hits resolved on your own machine can be told apart, so in multiplayer Mine also hides other people's hits on creatures they own.", num++, new string[3] { "All", "Mine", "None" })); EdgeFlash = cfg.Bind<bool>("8 Self", "EdgeFlash", true, D("Flash the edges of the screen when you take a heavy hit.", num++)); EdgeFlashPercent = cfg.Bind<float>("8 Self", "EdgeFlashPercent", 0.12f, D("Share of your maximum health a hit must take to flash the screen.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f))); EdgeFlashColor = cfg.Bind<Color>("8 Self", "EdgeFlashColor", new Color(0.7f, 0f, 0f, 0.55f), D("Colour of the flash. The alpha is how strong it gets at its peak.", num++)); EdgeFlashFade = cfg.Bind<float>("8 Self", "EdgeFlashFade", 0.6f, D("Seconds the flash takes to fade out.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f))); EdgeFlashThickness = cfg.Bind<float>("8 Self", "EdgeFlashThickness", 0.35f, D("How far in from the edge the flash reaches, as a share of half the screen.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f))); YieldToOtherMods = cfg.Bind<bool>("9 Compatibility", "YieldToOtherMods", true, D("Another mod that redraws the damage numbers (ColorfulDamage, ZenCombat) claims the same method, and whichever runs first silently wins. With this on, DamageSplash stands aside and lets the other one draw.", num++)); DebugSimulateConflict = cfg.Bind<bool>("9 Compatibility", "DebugSimulateConflict", false, D("Pretend a conflicting mod is installed, to check what this mod does about it.", num++, null, advanced: true)); SmallBelowPercent = cfg.Bind<float>("6 Magnitude", "SmallBelowPercent", 0.05f, D("A hit worth less than this share of the target's maximum health is drawn small.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))); BigAbovePercent = cfg.Bind<float>("6 Magnitude", "BigAbovePercent", 0.2f, D("At or above this share of maximum health a hit is drawn big.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))); HugeAbovePercent = cfg.Bind<float>("6 Magnitude", "HugeAbovePercent", 0.5f, D("At or above this share of maximum health a hit is drawn huge.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))); SmallBelowDamage = cfg.Bind<float>("6 Magnitude", "SmallBelowDamage", 10f, D("Fallback for numbers with no hit context: below this they are drawn small.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f))); BigAboveDamage = cfg.Bind<float>("6 Magnitude", "BigAboveDamage", 40f, D("Fallback for numbers with no hit context: at or above this they are drawn big.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f))); HugeAboveDamage = cfg.Bind<float>("6 Magnitude", "HugeAboveDamage", 120f, D("Fallback for numbers with no hit context: at or above this they are drawn huge.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f))); ScaleSmall = cfg.Bind<float>("6 Magnitude", "ScaleSmall", 0.8f, D("Size multiplier for a small hit. Normal hits are 1.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f))); ScaleBig = cfg.Bind<float>("6 Magnitude", "ScaleBig", 1.35f, D("Size multiplier for a big hit.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f))); ScaleHuge = cfg.Bind<float>("6 Magnitude", "ScaleHuge", 1.8f, D("Size multiplier for a huge hit, and for a killing blow.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f))); AnimPreset = cfg.Bind<string>("4 Animation", "AnimPreset", "Arc", D("Vanilla: straight drift up. Pop: vanilla drift with a scale-in. Arc: pop plus gravity and a little spray. Fountain: high and wide. Bounce: lands and bounces once. Choosing one overwrites the entries below.", num++, AnimPresetNames)); Duration = cfg.Bind<float>("4 Animation", "Duration", 1.8f, D("Seconds on screen. Vanilla: 1.5.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f))); PopFrom = cfg.Bind<float>("4 Animation", "PopFrom", 1.8f, D("Scale the number appears at before settling to 1. 1 disables the pop.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 4f))); PopDuration = cfg.Bind<float>("4 Animation", "PopDuration", 0.18f, D("Seconds the pop takes to settle.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))); Overshoot = cfg.Bind<float>("4 Animation", "Overshoot", 0.5f, D("How far the pop settles past its resting size before coming back, 0 to 1. 0 is a plain ease-out.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))); FadeIn = cfg.Bind<float>("4 Animation", "FadeIn", 0.05f, D("Seconds the number takes to fade in. 0 makes it appear at once, as vanilla does.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f))); Tilt = cfg.Bind<float>("4 Animation", "Tilt", 6f, D("Degrees. Each number is rotated by a random angle up to this, so a run of hits does not read as a printed column.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f))); RiseSpeed = cfg.Bind<float>("4 Animation", "RiseSpeed", 2.2f, D("Initial upward speed in metres per second. Vanilla: 1.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f))); Gravity = cfg.Bind<float>("4 Animation", "Gravity", 4f, D("Downward acceleration in metres per second squared. 0 is vanilla's straight drift.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f))); Spray = cfg.Bind<float>("4 Animation", "Spray", 35f, D("Degrees. The launch direction is tilted off vertical by a random angle up to this, in a random direction.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 90f))); ExitShrink = cfg.Bind<float>("4 Animation", "ExitShrink", 0.7f, D("Scale the number shrinks to over its last third while fading. 1 disables the shrink.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1.5f))); Bounce = cfg.Bind<bool>("4 Animation", "Bounce", false, D("Numbers that fall below their spawn height bounce once.", num++)); Jitter = cfg.Bind<float>("4 Animation", "Jitter", 0.3f, D("Random offset of the spawn point in metres, so overlapping hits separate. Vanilla: 0.5.", num++, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f))); cfg.SettingChanged -= OnSettingChanged; cfg.SettingChanged += OnSettingChanged; } private static ConfigDescription D(string desc, int order, AcceptableValueBase acceptable = null, bool advanced = false) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown return new ConfigDescription(desc, acceptable, new object[1] { new ConfigurationManagerAttributes { Order = 1000 - order, IsAdvanced = advanced } }); } private static ConfigDescription D(string desc, int order, string[] choices) { return D(desc, order, (AcceptableValueBase)(object)new AcceptableValueList<string>(choices)); } private static void OnSettingChanged(object sender, SettingChangedEventArgs args) { if (_applying) { return; } ConfigEntryBase changedSetting = args.ChangedSetting; if ((object)changedSetting == Preset) { ApplyPreset(Preset.Value); return; } if ((object)changedSetting == AnimPreset) { ApplyAnimPreset(AnimPreset.Value); return; } _applying = true; try { if (IsVisual(changedSetting) && Preset.Value != "Custom") { Preset.Value = "Custom"; } if (IsAnim(changedSetting) && AnimPreset.Value != "Custom") { AnimPreset.Value = "Custom"; } } finally { _applying = false; } Raise(); } private static bool IsAnim(ConfigEntryBase e) { if ((object)e != Duration && (object)e != PopFrom && (object)e != PopDuration && (object)e != Overshoot && (object)e != FadeIn && (object)e != Tilt && (object)e != RiseSpeed && (object)e != Gravity && (object)e != Spray && (object)e != ExitShrink && (object)e != Bounce) { return (object)e == Jitter; } return true; } private static bool IsVisual(ConfigEntryBase e) { if ((object)e != Enabled && (object)e != Verbose && (object)e != MaxDistance && (object)e != HideZeros && (object)e != MaxAlive && (object)e != Visibility && (object)e != YieldToOtherMods) { return (object)e != DebugSimulateConflict; } return false; } public static void ApplyPreset(string name) { //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) _applying = true; try { switch (name) { default: return; case "Vanilla": FontName.Value = "Vanilla"; FauxBold.Value = false; NearSize.Value = 16f; FarSize.Value = 8f; NearDistance.Value = 10f; FarDistance.Value = 10f; FaceDilate.Value = 0f; OutlineWidth.Value = 0f; Shadow.Value = false; ResetColors(); SetHitStyling(magnitude: false, tints: false, flags: false); SetExtras(on: false); AnimPreset.Value = "Vanilla"; SetAnim(AnimPresetValues("Vanilla")); break; case "Bold": FontName.Value = Fonts.PreferredDisplay(); FauxBold.Value = false; NearSize.Value = 24f; FarSize.Value = 12f; NearDistance.Value = 8f; FarDistance.Value = 30f; FaceDilate.Value = 0.22f; OutlineWidth.Value = 0.15f; OutlineColor.Value = Color.black; Shadow.Value = true; ShadowOffset.Value = 0.3f; ResetColors(); SetHitStyling(magnitude: true, tints: false, flags: true); SetExtras(on: true); AnimPreset.Value = "Pop"; SetAnim(AnimPresetValues("Pop")); break; case "Festive": FontName.Value = Fonts.PreferredDisplay(); FauxBold.Value = false; NearSize.Value = 30f; FarSize.Value = 14f; NearDistance.Value = 8f; FarDistance.Value = 30f; FaceDilate.Value = 0.28f; OutlineWidth.Value = 0.18f; OutlineColor.Value = Color.black; Shadow.Value = true; ShadowOffset.Value = 0.3f; ResetColors(); SetHitStyling(magnitude: true, tints: true, flags: true); SetExtras(on: true); AnimPreset.Value = "Arc"; SetAnim(AnimPresetValues("Arc")); break; } if (Preset.Value != name) { Preset.Value = name; } } finally { _applying = false; } Raise(); } public static void ApplyAnimPreset(string name) { _applying = true; try { switch (name) { default: return; case "Vanilla": case "Pop": case "Arc": case "Fountain": case "Bounce": SetAnim(AnimPresetValues(name)); if (AnimPreset.Value != name) { AnimPreset.Value = name; } if (Preset.Value != "Custom") { Preset.Value = "Custom"; } break; } } finally { _applying = false; } Raise(); } public static AnimParams AnimPresetValues(string name) { return name switch { "Vanilla" => AnimParams.Vanilla, "Pop" => new AnimParams { Duration = 1.5f, PopFrom = 1.5f, PopDuration = 0.15f, Overshoot = 0.3f, FadeIn = 0.05f, Tilt = 0f, RiseSpeed = 1f, Gravity = 0f, Spray = 0f, ExitShrink = 0.85f, Bounce = false, Jitter = 0.3f }, "Arc" => new AnimParams { Duration = 1.8f, PopFrom = 1.8f, PopDuration = 0.18f, Overshoot = 0.5f, FadeIn = 0.05f, Tilt = 6f, RiseSpeed = 2.2f, Gravity = 4f, Spray = 35f, ExitShrink = 0.7f, Bounce = false, Jitter = 0.3f }, "Fountain" => new AnimParams { Duration = 2f, PopFrom = 1.6f, PopDuration = 0.15f, Overshoot = 0.5f, FadeIn = 0.05f, Tilt = 10f, RiseSpeed = 3.5f, Gravity = 7f, Spray = 70f, ExitShrink = 0.6f, Bounce = false, Jitter = 0.3f }, "Bounce" => new AnimParams { Duration = 2f, PopFrom = 1.6f, PopDuration = 0.15f, Overshoot = 0.6f, FadeIn = 0.05f, Tilt = 8f, RiseSpeed = 3f, Gravity = 9f, Spray = 30f, ExitShrink = 0.8f, Bounce = true, Jitter = 0.3f }, _ => CurrentAnim(), }; } private static void SetAnim(AnimParams a) { Duration.Value = a.Duration; PopFrom.Value = a.PopFrom; PopDuration.Value = a.PopDuration; Overshoot.Value = a.Overshoot; FadeIn.Value = a.FadeIn; Tilt.Value = a.Tilt; RiseSpeed.Value = a.RiseSpeed; Gravity.Value = a.Gravity; Spray.Value = a.Spray; ExitShrink.Value = a.ExitShrink; Bounce.Value = a.Bounce; Jitter.Value = a.Jitter; } private static void SetHitStyling(bool magnitude, bool tints, bool flags) { MagnitudeScaling.Value = magnitude; ElementalTints.Value = tints; SneakEnabled.Value = flags; CritEnabled.Value = flags; KillEnabled.Value = flags; } private static void SetExtras(bool on) { DotMergeWindow.Value = (on ? 1.2f : 0f); HitMergeWindow.Value = 0f; EdgeFlash.Value = on; } private static void ResetColors() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) ColorNormal.Value = Color.white; ColorResistant.Value = new Color(0.6f, 0.6f, 0.6f, 1f); ColorWeak.Value = new Color(1f, 1f, 0f, 1f); ColorImmune.Value = new Color(0.6f, 0.6f, 0.6f, 1f); ColorHeal.Value = new Color(0.5f, 1f, 0.5f, 0.7f); ColorTooHard.Value = new Color(0.8f, 0.7f, 0.7f, 1f); ColorBlocked.Value = Color.white; ColorBonus.Value = new Color(1f, 0.63f, 0.24f, 1f); ColorSelfDamage.Value = new Color(1f, 0f, 0f, 1f); ColorSelfNoDamage.Value = new Color(0.5f, 0.5f, 0.5f, 1f); } public static void RebindFontChoices(IList<string> names) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (_cfg == null || FontName == null || names == null || names.Count == 0) { return; } string value = FontName.Value; List<string> list = new List<string>(names); if (!list.Contains(value)) { list.Add(value); } _applying = true; try { ConfigDescription description = ((ConfigEntryBase)FontName).Description; _cfg.Remove(((ConfigEntryBase)FontName).Definition); FontName = _cfg.Bind<string>("2 Font", "Font", "Vanilla", new ConfigDescription("Font for the numbers. \"Vanilla\" keeps the game's own damage-text font. The list is filled with every TextMeshPro font the game has loaded once you are in a world; use `splash fonts` to refresh it.", (AcceptableValueBase)(object)new AcceptableValueList<string>(list.ToArray()), description.Tags)); if (FontName.Value != value) { FontName.Value = value; } } finally { _applying = false; } } public static string SetByName(string key, string value) { ConfigEntryBase val = Find(key); if (val == null) { return "no setting called \"" + key + "\""; } try { val.BoxedValue = TomlTypeConverter.ConvertToValue(value, val.SettingType); return val.Definition.Key + " = " + val.GetSerializedValue(); } catch (Exception ex) { return "could not set " + val.Definition.Key + ": " + ex.Message; } } public static List<string> Describe(string filter) { List<string> list = new List<string>(); if (_cfg == null) { return list; } foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in (IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)_cfg) { if (string.IsNullOrEmpty(filter) || item.Key.Key.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0 || item.Key.Section.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) { list.Add(item.Key.Key + " = " + item.Value.GetSerializedValue()); } } list.Sort(StringComparer.OrdinalIgnoreCase); return list; } private static ConfigEntryBase Find(string key) { if (_cfg == null || string.IsNullOrEmpty(key)) { return null; } foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in (IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)_cfg) { if (string.Equals(item.Key.Key, key, StringComparison.OrdinalIgnoreCase)) { return item.Value; } } return null; } public static void Reload() { if (_cfg != null) { string value = Preset.Value; string value2 = AnimPreset.Value; _applying = true; try { _cfg.Reload(); } finally { _applying = false; } if (Preset.Value != value && Preset.Value != "Custom") { ApplyPreset(Preset.Value); } else if (AnimPreset.Value != value2 && AnimPreset.Value != "Custom") { ApplyAnimPreset(AnimPreset.Value); } else { Raise(); } } } public static AnimParams CurrentAnim() { return new AnimParams { Duration = Duration.Value, PopFrom = PopFrom.Value, PopDuration = PopDuration.Value, Overshoot = Overshoot.Value, FadeIn = FadeIn.Value, Tilt = Tilt.Value, RiseSpeed = RiseSpeed.Value, Gravity = Gravity.Value, Spray = Spray.Value, ExitShrink = ExitShrink.Value, Bounce = Bounce.Value, Jitter = Jitter.Value }; } private static void Raise() { PluginConfig.Changed?.Invoke(); } } internal sealed class ConfigurationManagerAttributes { public int? Order; public bool? IsAdvanced; } } namespace DamageSplash.Patches { [HarmonyPatch(typeof(Character))] internal static class ContextPatches { private static int _sneakTarget; private static float _sneakTime = -1f; [HarmonyPrefix] [HarmonyPatch("ApplyDamage")] private static void ApplyDamagePrefix(Character __instance, HitData hit, bool showDamageText, out HitInfo __state) { __state = HitContext.Take(); try { SetContext(__instance, hit, showDamageText); } catch (Exception ex) { HitContext.Clear(); Guard.Report("ApplyDamage prefix", ex); } } private static void SetContext(Character target, HitData hit, bool showDamageText) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Invalid comparison between Unknown and I4 //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Invalid comparison between Unknown and I4 if (hit == null || !showDamageText || !PluginConfig.Enabled.Value || !PluginConfig.UseHitContext.Value || target.IsDead() || target.IsDebugFlying() || target.IsTeleporting()) { return; } bool dot = IsOverTime(hit.m_hitType); bool flag = (int)hit.m_hitType == 1 || (int)hit.m_hitType == 2; bool flag2 = PluginConfig.Visibility.Value != "All"; int instanceID = ((Object)target).GetInstanceID(); HitInfo info = new HitInfo { Pos = hit.m_point, TargetId = instanceID, TargetIsLocalPlayer = ((object)target == Player.m_localPlayer), AttackerIsLocal = (flag2 && (object)hit.GetAttacker() == Player.m_localPlayer), Damage = hit.GetTotalDamage(), MaxHealth = target.GetMaxHealth(), WasAlive = (target.GetHealth() > 0f), Dot = dot, Sneak = (flag && IsSneak(target, instanceID)), StaggerCrit = (flag && !target.IsPlayer() && target.IsStaggering()) }; info.Majority = ((DamageTypes)(ref hit.m_damage)).GetMajorityDamageType(); info.Elemental = (info.Majority & 0xE0) != 0 || (int)info.Majority == 256 || (int)info.Majority == 512; HitContext.Set(info); if (info.TargetIsLocalPlayer && PluginConfig.EdgeFlash.Value && info.MaxHealth > 0f && !target.InGodMode() && !target.InGhostMode()) { float num = info.Damage * Game.m_localDamgeTakenRate; if (num > 0.1f && num / info.MaxHealth >= PluginConfig.EdgeFlashPercent.Value) { EdgeFlash.Trigger(); } } } private static bool IsSneak(Character target, int targetId) { float time = Time.time; if (target.m_backstabTime != time) { return false; } if (_sneakTarget == targetId && _sneakTime == time) { return false; } _sneakTarget = targetId; _sneakTime = time; return true; } [HarmonyPostfix] [HarmonyPatch("ApplyDamage")] private static void ApplyDamagePostfix(Character __instance) { try { Splash spawned = HitContext.Spawned; if (spawned != null && PluginConfig.KillEnabled.Value && HitContext.WasAlive && __instance.GetHealth() <= 0f) { Styles.ApplyKill(spawned); } } catch (Exception ex) { Guard.Report("ApplyDamage postfix", ex); } } [HarmonyFinalizer] [HarmonyPatch("ApplyDamage")] private static void ApplyDamageFinalizer(HitInfo __state) { HitContext.Restore(__state); } private static bool IsOverTime(HitType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 if (type - 4 <= 5) { return true; } return false; } } [HarmonyPatch(typeof(DamageText))] internal static class DamageTextPatches { private static float _vanillaMaxDistance = -1f; [HarmonyPostfix] [HarmonyPatch("Awake")] private static void AwakePostfix(DamageText __instance) { Fonts.Refresh(); PluginConfig.RebindFontChoices(Fonts.Names); Styles.Invalidate(); Compat.Detect(); SplashPool.Init(__instance); _vanillaMaxDistance = __instance.m_maxTextDistance; ApplyMaxDistance(); } internal static void ApplyMaxDistance(bool unloading = false) { DamageText instance = DamageText.instance; if (!((Object)(object)instance == (Object)null) && !(_vanillaMaxDistance < 0f)) { bool flag = !unloading && PluginConfig.Enabled.Value && !Compat.ShouldYield; instance.m_maxTextDistance = (flag ? PluginConfig.MaxDistance.Value : _vanillaMaxDistance); } } [HarmonyPrefix] [HarmonyPatch("AddInworldText")] private static bool AddInworldTextPrefix(DamageText __instance, TextType type, Vector3 pos, float distance, string text, bool mySelf) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.Enabled.Value || !SplashPool.Ready || Compat.ShouldYield) { return true; } try { Show(type, pos, distance, text, mySelf); return false; } catch (Exception ex) { Guard.Report("AddInworldText", ex); return true; } } private static void Show(TextType type, Vector3 pos, float distance, string text, bool mySelf) { //IL_002f: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((!(text == "0") || ((!PluginConfig.HideZeros.Value || (int)type == 5) && SplashPool.ActiveCount < PluginConfig.MaxAlive.Value)) && Allowed(type, mySelf, pos)) { Style style = Styles.Resolve(type, text, mySelf, pos); int num = Merger.KeyFor(style, type, mySelf); Splash splash = Merger.TryMerge(style, type, num, pos) ?? SplashPool.Spawn(style, style.Text, pos, distance, type, num); HitContext.SetSpawned(pos, splash); } } private static bool Allowed(TextType type, bool mySelf, Vector3 pos) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) string value = PluginConfig.Visibility.Value; if (value == "All") { return true; } if ((int)type == 6 || (int)type == 4 || (int)type == 7 || (int)type == 5) { return true; } if (value == "None") { return false; } if (mySelf) { return true; } if (HitContext.TryMatch(pos, out var info)) { if (!info.AttackerIsLocal) { return info.TargetIsLocalPlayer; } return true; } return OutgoingHits.Matches(pos); } [HarmonyPrefix] [HarmonyPatch("UpdateWorldTexts")] private static void UpdateWorldTextsPrefix(float dt) { SplashPool.Update(dt); } } [HarmonyPatch] internal static class OutgoingHitPatches { private static IEnumerable<MethodBase> TargetMethods() { Type[] types; try { types = typeof(Character).Assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } Type[] array = types; foreach (Type type in array) { if (!(type == null) && !type.IsAbstract && !type.IsInterface && typeof(IDestructible).IsAssignableFrom(type)) { MethodInfo method = type.GetMethod("Damage", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(HitData) }, null); if (method != null && !method.IsAbstract) { yield return method; } } } } private static void Prefix(HitData hit) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) try { if (hit != null && !(PluginConfig.Visibility.Value != "Mine")) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && hit.m_attacker == ((Character)localPlayer).GetZDOID()) { OutgoingHits.Record(hit.m_point); } } } catch (Exception ex) { Guard.Report("outgoing hit", ex); } } } } namespace DamageSplash.Core { public struct AnimParams { public float Duration; public float PopFrom; public float PopDuration; public float Overshoot; public float FadeIn; public float Tilt; public float RiseSpeed; public float Gravity; public float Spray; public float ExitShrink; public bool Bounce; public float Jitter; public bool Bounced; public static AnimParams Vanilla => new AnimParams { Duration = 1.5f, PopFrom = 1f, PopDuration = 0f, Overshoot = 0f, FadeIn = 0f, Tilt = 0f, RiseSpeed = 1f, Gravity = 0f, Spray = 0f, ExitShrink = 1f, Bounce = false, Jitter = 0.5f }; } public static class Animation { private const float ExitPortion = 0.3f; private const float BounceRestitution = 0.45f; private const float BackEase = 1.70158f; public static float Tilt(ref AnimParams p) { if (!(p.Tilt > 0f)) { return 0f; } return Random.Range(0f - p.Tilt, p.Tilt); } public static Vector3 InitialVelocity(ref AnimParams p) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_0018: Unknown result type (might be due to invalid IL or missing references) if (p.Spray <= 0f) { return Vector3.up * p.RiseSpeed; } float num = Random.Range(0f, p.Spray) * ((float)Math.PI / 180f); float num2 = Random.Range(0f, (float)Math.PI * 2f); return new Vector3(Mathf.Sin(num) * Mathf.Cos(num2), Mathf.Cos(num), Mathf.Sin(num) * Mathf.Sin(num2)) * p.RiseSpeed; } public static void Step(ref AnimParams p, ref Vector3 offset, ref Vector3 velocity, float dt) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0037: Unknown result type (might be due to invalid IL or missing references) if (p.Gravity > 0f) { velocity.y -= p.Gravity * dt; } offset += velocity * dt; if (p.Bounce && !p.Bounced && offset.y < 0f && velocity.y < 0f) { p.Bounced = true; offset.y = (0f - offset.y) * 0.45f; velocity.y = (0f - velocity.y) * 0.45f; velocity.x *= 0.6f; velocity.z *= 0.6f; } } public static float Scale(ref AnimParams p, float timer, float t01) { float num = 1f; if (p.PopDuration > 0f && timer < p.PopDuration && p.PopFrom != 1f) { float num2 = timer / p.PopDuration - 1f; float num3 = 1.70158f * p.Overshoot; float num4 = 1f + (num3 + 1f) * num2 * num2 * num2 + num3 * num2 * num2; num = Mathf.LerpUnclamped(p.PopFrom, 1f, num4); } if (p.ExitShrink != 1f && t01 > 0.7f) { float num5 = (t01 - 0.7f) / 0.3f; num *= Mathf.Lerp(1f, p.ExitShrink, num5); } return num; } public static float Alpha(ref AnimParams p, float timer, float t01) { float num = 1f - t01 * t01 * t01; if (p.FadeIn > 0f && timer < p.FadeIn) { num *= timer / p.FadeIn; } return num; } } public static class Compat { private static readonly string[] Known = new string[2] { "colorfuldamage", "zencombat" }; private static bool _logged; private static string _loggedConflict; private static bool _loggedYield; public static string Conflict { get; private set; } public static bool ShouldYield { get { if (Conflict != null) { return PluginConfig.YieldToOtherMods.Value; } return false; } } public static void Detect() { Conflict = null; if (PluginConfig.DebugSimulateConflict.Value) { Conflict = "a pretend mod (DebugSimulateConflict is on)"; } else { foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { string text = pluginInfo.Key ?? string.Empty; string text2 = ((pluginInfo.Value != null && pluginInfo.Value.Metadata != null) ? pluginInfo.Value.Metadata.Name : string.Empty); if (IsKnown(text) || IsKnown(text2)) { Conflict = (string.IsNullOrEmpty(text2) ? text : text2) + " (" + text + ")"; break; } } } if (!_logged || !(_loggedConflict == Conflict) || _loggedYield != ShouldYield) { _logged = true; _loggedConflict = Conflict; _loggedYield = ShouldYield; if (Conflict == null) { DamageSplashPlugin.Log.LogInfo((object)"no other damage-number mod found."); } else if (ShouldYield) { DamageSplashPlugin.Log.LogWarning((object)(Conflict + " also redraws the damage numbers. DamageSplash is standing aside and letting it draw; set YieldToOtherMods to false to take over instead, but do not run both.")); } else { DamageSplashPlugin.Log.LogWarning((object)(Conflict + " also redraws the damage numbers and YieldToOtherMods is off. Both will fight over the same method and whichever loads first wins; remove one of them.")); } } } private static bool IsKnown(string text) { if (string.IsNullOrEmpty(text)) { return false; } string[] known = Known; foreach (string value in known) { if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } } public static class ConsoleCommands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; public static ConsoleOptionsFetcher <>9__1_1; internal void <Register>b__1_0(ConsoleEventArgs args) { switch ((args.Length > 1) ? args[1].ToLowerInvariant() : "help") { case "demo": { Say(args.Context, "DamageSplash: " + Demo.Start((args.Length > 2 && float.TryParse(args[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) ? result : 0f)); return; } case "burst": { Say(args.Context, "DamageSplash: " + Demo.Burst((args.Length > 2 && int.TryParse(args[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3)) ? result3 : 40)); return; } case "rain": { Say(args.Context, "DamageSplash: " + Demo.Rain((args.Length > 2 && float.TryParse(args[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) ? result2 : 30f)); return; } case "dot": { Say(args.Context, "DamageSplash: " + Demo.Dot((args.Length > 2 && float.TryParse(args[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) ? result4 : 12f)); return; } case "stop": Demo.Stop(); Say(args.Context, "DamageSplash: stopped"); return; case "set": Set(args); return; case "get": Get(args); return; case "preset": Preset(args); return; case "anim": Anim(args); return; case "fonts": FontList(args.Context); return; case "reload": PluginConfig.Reload(); Say(args.Context, "DamageSplash: config reloaded from disk."); return; case "stats": Say(args.Context, Stats()); return; case "conflicts": Conflicts(args.Context); return; case "flash": EdgeFlash.Trigger(); Say(args.Context, "DamageSplash: " + (EdgeFlash.Ready ? "flashed" : "no canvas to flash on yet")); return; case "on": PluginConfig.Enabled.Value = true; Say(args.Context, "DamageSplash: on"); return; case "off": PluginConfig.Enabled.Value = false; Say(args.Context, "DamageSplash: off (vanilla numbers)"); return; } Say(args.Context, "splash demo [seconds] - one of every kind of number around you, optionally held that long"); Say(args.Context, "splash burst [n] - n random numbers at once (default 40)"); Say(args.Context, "splash rain [seconds] - a steady trickle to tune against (default 30, 0 stops)"); Say(args.Context, "splash dot [seconds] - fake burning ticks, to see them merge (default 12)"); Say(args.Context, "splash set <name> <v> - change one setting live, e.g. splash set gravity 6"); Say(args.Context, "splash get [filter] - print settings and their values"); Say(args.Context, "splash preset <name> - " + string.Join(" | ", PluginConfig.PresetNames)); Say(args.Context, "splash anim <name> - " + string.Join(" | ", PluginConfig.AnimPresetNames)); Say(args.Context, "splash fonts - every font the numbers can use"); Say(args.Context, "splash reload - re-read the config file"); Say(args.Context, "splash stats - pool and material state"); Say(args.Context, "splash conflicts - other mods that redraw the numbers"); Say(args.Context, "splash flash - test the screen-edge flash"); Say(args.Context, "splash on|off"); } internal List<string> <Register>b__1_1() { return new List<string> { "demo", "burst", "rain", "dot", "stop", "set", "get", "preset", "anim", "fonts", "reload", "stats", "conflicts", "flash", "on", "off" }; } } private static bool _registered; public static void Register() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (_registered) { return; } _registered = true; object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { switch ((args.Length > 1) ? args[1].ToLowerInvariant() : "help") { case "demo": { Say(args.Context, "DamageSplash: " + Demo.Start((args.Length > 2 && float.TryParse(args[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) ? result : 0f)); break; } case "burst": { Say(args.Context, "DamageSplash: " + Demo.Burst((args.Length > 2 && int.TryParse(args[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3)) ? result3 : 40)); break; } case "rain": { Say(args.Context, "DamageSplash: " + Demo.Rain((args.Length > 2 && float.TryParse(args[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) ? result2 : 30f)); break; } case "dot": { Say(args.Context, "DamageSplash: " + Demo.Dot((args.Length > 2 && float.TryParse(args[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) ? result4 : 12f)); break; } case "stop": Demo.Stop(); Say(args.Context, "DamageSplash: stopped"); break; case "set": Set(args); break; case "get": Get(args); break; case "preset": Preset(args); break; case "anim": Anim(args); break; case "fonts": FontList(args.Context); break; case "reload": PluginConfig.Reload(); Say(args.Context, "DamageSplash: config reloaded from disk."); break; case "stats": Say(args.Context, Stats()); break; case "conflicts": Conflicts(args.Context); break; case "flash": EdgeFlash.Trigger(); Say(args.Context, "DamageSplash: " + (EdgeFlash.Ready ? "flashed" : "no canvas to flash on yet")); break; case "on": PluginConfig.Enabled.Value = true; Say(args.Context, "DamageSplash: on"); break; case "off": PluginConfig.Enabled.Value = false; Say(args.Context, "DamageSplash: off (vanilla numbers)"); break; default: Say(args.Context, "splash demo [seconds] - one of every kind of number around you, optionally held that long"); Say(args.Context, "splash burst [n] - n random numbers at once (default 40)"); Say(args.Context, "splash rain [seconds] - a steady trickle to tune against (default 30, 0 stops)"); Say(args.Context, "splash dot [seconds] - fake burning ticks, to see them merge (default 12)"); Say(args.Context, "splash set <name> <v> - change one setting live, e.g. splash set gravity 6"); Say(args.Context, "splash get [filter] - print settings and their values"); Say(args.Context, "splash preset <name> - " + string.Join(" | ", PluginConfig.PresetNames)); Say(args.Context, "splash anim <name> - " + string.Join(" | ", PluginConfig.AnimPresetNames)); Say(args.Context, "splash fonts - every font the numbers can use"); Say(args.Context, "splash reload - re-read the config file"); Say(args.Context, "splash stats - pool and material state"); Say(args.Context, "splash conflicts - other mods that redraw the numbers"); Say(args.Context, "splash flash - test the screen-edge flash"); Say(args.Context, "splash on|off"); break; } }; <>c.<>9__1_0 = val; obj = (object)val; } object obj2 = <>c.<>9__1_1; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => new List<string> { "demo", "burst", "rain", "dot", "stop", "set", "get", "preset", "anim", "fonts", "reload", "stats", "conflicts", "flash", "on", "off" }; <>c.<>9__1_1 = val2; obj2 = (object)val2; } new ConsoleCommand("splash", "DamageSplash: demo | burst <n> | preset <name> | anim <name> | fonts | reload | stats", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false); } private static void Say(Terminal ctx, string line) { ctx.AddString(line); DamageSplashPlugin.Log.LogInfo((object)line); } private static void Set(ConsoleEventArgs args) { if (args.Length < 4) { Say(args.Context, "splash set <setting> <value>, for example \"splash set gravity 6\" or \"splash set Font Valheim-Norse\""); } else { Say(args.Context, "DamageSplash: " + PluginConfig.SetByName(args[2], args[3])); } } private static void Get(ConsoleEventArgs args) { List<string> list = PluginConfig.Describe((args.Length > 2) ? args[2] : null); Say(args.Context, "DamageSplash: " + list.Count + " setting(s)"); foreach (string item in list) { Say(args.Context, " " + item); } } private static void Preset(ConsoleEventArgs args) { string b = ((args.Length > 2) ? args[2] : ""); string[] presetNames = PluginConfig.PresetNames; foreach (string text in presetNames) { if (string.Equals(text, b, StringComparison.OrdinalIgnoreCase) && text != "Custom") { PluginConfig.ApplyPreset(text); Say(args.Context, "DamageSplash: preset " + text); return; } } Say(args.Context, "DamageSplash: preset is " + PluginConfig.Preset.Value + "; choose " + string.Join(" | ", PluginConfig.PresetNames)); } private static void Anim(ConsoleEventArgs args) { string b = ((args.Length > 2) ? args[2] : ""); string[] animPresetNames = PluginConfig.AnimPresetNames; foreach (string text in animPresetNames) { if (string.Equals(text, b, StringComparison.OrdinalIgnoreCase) && text != "Custom") { PluginConfig.ApplyAnimPreset(text); Say(args.Context, "DamageSplash: animation " + text); return; } } Say(args.Context, "DamageSplash: animation is " + PluginConfig.AnimPreset.Value + "; choose " + string.Join(" | ", PluginConfig.AnimPresetNames)); } private static void FontList(Terminal ctx) { Fonts.Refresh(); PluginConfig.RebindFontChoices(Fonts.Names); TMP_FontAsset val = Fonts.Resolve(PluginConfig.FontName.Value); Say(ctx, "DamageSplash: " + (Fonts.Names.Count - 1) + " font(s) loaded; config says \"" + PluginConfig.FontName.Value + "\", using " + (((Object)(object)val != (Object)null) ? ((Object)val).name : ("the vanilla prefab font" + (((Object)(object)SplashPool.PrefabFont != (Object)null) ? (" (" + ((Object)SplashPool.PrefabFont).name + ")") : "")))); foreach (string name in Fonts.Names) { Say(ctx, " " + name); } } private static void Conflicts(Terminal ctx) { Compat.Detect(); if (Compat.Conflict == null) { Say(ctx, "DamageSplash: no other damage-number mod found; drawing the numbers."); } else { Say(ctx, "DamageSplash: " + Compat.Conflict + " also redraws the numbers; DamageSplash is " + (Compat.ShouldYield ? "standing aside." : "drawing anyway (YieldToOtherMods is off), which means the two are racing.")); } } private static string Stats() { //IL_015d: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(256); stringBuilder.Append("DamageSplash: ").Append(PluginConfig.Enabled.Value ? "on" : "off").Append(", preset ") .Append(PluginConfig.Preset.Value) .Append('/') .Append(PluginConfig.AnimPreset.Value) .Append(", pool ") .Append(SplashPool.ActiveCount) .Append(" active / ") .Append(SplashPool.FreeCount) .Append(" free") .Append(SplashPool.Ready ? "" : " (not ready)") .Append(", prefab font ") .Append(((Object)(object)SplashPool.PrefabFont != (Object)null) ? ((Object)SplashPool.PrefabFont).name : "none") .Append(", prefab shader ") .Append(((Object)(object)SplashPool.PrefabMaterial != (Object)null) ? ((Object)SplashPool.PrefabMaterial.shader).name : "none") .Append(", visibility ") .Append(PluginConfig.Visibility.Value) .Append((Compat.Conflict == null) ? ", no conflicts" : ((Compat.ShouldYield ? ", yielding to " : ", racing ") + Compat.Conflict)) .Append(", game ") .Append(Version.CurrentVersion); return stringBuilder.ToString(); } } public static class Demo { private struct Item { public float At; public TextType Type; public string Text; public bool MySelf; public Vector3 Offset; public bool HasHit; public HitInfo Hit; public bool Kill; } private static readonly List<Item> _queue = new List<Item>(); private static float _hold; private static float _rainUntil; private static float _nextRain; private static float _dotUntil; private static float _nextDot; private const int DotTargetId = -4242; public static float DurationOverride { get; private set; } public static bool FreezeMotion { get; private set; } public static bool Running => _queue.Count > 0; public static string Start(float hold = 0f) { //IL_0062: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) _hold = hold; if ((Object)(object)Player.m_localPlayer == (Object)null) { return "no local player"; } if ((Object)(object)DamageText.instance == (Object)null) { return "no DamageText (not in a world?)"; } _queue.Clear(); float time = Time.time; float num = 0.45f; int num2 = 0; Plain(time + num * (float)num2++, (TextType)0, "37", new Vector3(-1.6f, 1.4f, 3f), 200f); Plain(time + num * (float)num2++, (TextType)2, "52", new Vector3(-0.6f, 1.4f, 3f), 200f); Plain(time + num * (float)num2++, (TextType)1, "12", new Vector3(0.4f, 1.4f, 3f), 200f); Plain(time + num * (float)num2++, (TextType)3, "0", new Vector3(1.4f, 1.4f, 3f), 200f); Plain(time + num * (float)num2++, (TextType)0, "312", new Vector3(-1f, 1.9f, 4.5f), 400f); Flag(time + num * (float)num2++, "210", new Vector3(-2.2f, 1.7f, 4f), 400f, sneak: true); Flag(time + num * (float)num2++, "180", new Vector3(0.2f, 1.7f, 4f), 400f, sneak: false, crit: true); Flag(time + num * (float)num2++, "95", new Vector3(2.2f, 1.7f, 4f), 120f, sneak: false, crit: false, kill: true); Element(time + num * (float)num2++, "14", new Vector3(-2.6f, 1.2f, 2.5f), 200f, (DamageType)32); Element(time + num * (float)num2++, "26", new Vector3(-1.3f, 1.2f, 2.5f), 200f, (DamageType)64); Element(time + num * (float)num2++, "33", new Vector3(1.3f, 1.2f, 2.5f), 200f, (DamageType)128); Element(time + num * (float)num2++, "9", new Vector3(2.6f, 1.2f, 2.5f), 200f, (DamageType)256); Add(time + num * (float)num2++, (TextType)6, "24", mySelf: false, new Vector3(-0.2f, 1.1f, 1.2f)); Add(time + num * (float)num2++, (TextType)4, "15", mySelf: true, new Vector3(0f, 1.7f, 0.5f)); Add(time + num * (float)num2++, (TextType)5, "0", mySelf: false, new Vector3(2.2f, 0.8f, 3f)); Add(time + num * (float)num2++, (TextType)7, "+3", mySelf: true, new Vector3(-2.2f, 0.8f, 3f)); Self(time + num * (float)num2++, "18", new Vector3(1.1f, 1.55f, 0.9f), 100f); Add(time + num * (float)num2++, (TextType)0, "0", mySelf: true, new Vector3(-1.1f, 1.55f, 0.9f)); Plain(time + num * (float)num2++, (TextType)0, "44", new Vector3(-2.8f, 2.1f, 12f), 200f); Plain(time + num * (float)num2++, (TextType)0, "61", new Vector3(5.5f, 2.6f, 25f), 200f); return "demo: " + _queue.Count + " numbers over " + (num * (float)num2).ToString("0.0") + " s" + ((hold > 0f) ? (", each held " + hold.ToString("0") + " s") : ""); } public static string Burst(int count) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return "no local player"; } _queue.Clear(); _hold = 0f; float time = Time.time; Vector3 offset = default(Vector3); for (int i = 0; i < count; i++) { ((Vector3)(ref offset))..ctor(Random.Range(-3f, 3f), Random.Range(0.8f, 2.2f), Random.Range(2f, 6f)); TextType type = (TextType)Random.Range(0, 3); Add(time + (float)i * 0.02f, type, Random.Range(3, 250).ToString(), mySelf: false, offset); } return "burst: " + count + " numbers"; } public static string Rain(float seconds) { if ((Object)(object)Player.m_localPlayer == (Object)null) { return "no local player"; } if (seconds <= 0f) { _rainUntil = 0f; return "rain off"; } _hold = 0f; _rainUntil = Time.time + seconds; return "raining numbers for " + seconds.ToString("0") + " s (splash rain 0 to stop)"; } public static string Dot(float seconds) { if ((Object)(object)Player.m_localPlayer == (Object)null) { return "no local player"; } if (seconds <= 0f) { _dotUntil = 0f; return "burning off"; } _hold = 0f; _dotUntil = Time.time + seconds; _nextDot = 0f; return "burning for " + seconds.ToString("0") + " s, one tick a second" + ((PluginConfig.DotMergeWindow.Value > 0f) ? "; they should add into one climbing number" : "; merging is off (DotMergeWindow is 0) so each tick gets its own number"); } public static void Stop() { _queue.Clear(); _rainUntil = 0f; _dotUntil = 0f; } private static void Add(float at, TextType type, string text, bool mySelf, Vector3 offset) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) _queue.Add(new Item { At = at, Type = type, Text = text, MySelf = mySelf, Offset = offset }); } private static void Plain(float at, TextType type, string text, Vector3 offset, float maxHealth) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) _queue.Add(new Item { At = at, Type = type, Text = text, Offset = offset, HasHit = true, Hit = new HitInfo { Damage = Parse(text), MaxHealth = maxHealth, Majority = (DamageType)2 } }); } private static void Flag(float at, string text, Vector3 offset, float maxHealth, bool sneak = false, bool crit = false, bool kill = false) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) _queue.Add(new Item { At = at, Type = (TextType)0, Text = text, Offset = offset, HasHit = true, Kill = kill, Hit = new HitInfo { Damage = Parse(text), MaxHealth = maxHealth, Sneak = sneak, StaggerCrit = crit, Majority = (DamageType)2 } }); } private static void Element(float at, string text, Vector3 offset, float maxHealth, DamageType type) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) _queue.Add(new Item { At = at, Type = (TextType)0, Text = text, Offset = offset, HasHit = true, Hit = new HitInfo { Damage = Parse(text), MaxHealth = maxHealth, Dot = true, Elemental = true, Majority = type } }); } private static void Self(float at, string text, Vector3 offset, float maxHealth) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_005f: Unknown result type (might be due to invalid IL or missing references) _queue.Add(new Item { At = at, Type = (TextType)0, Text = text, MySelf = true, Offset = offset, HasHit = true, Hit = new HitInfo { Damage = Parse(text), MaxHealth = maxHealth, Majority = (DamageType)1 } }); } private static float Parse(string text) { if (!float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return 0f; } return result; } public static void Update(float now) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) if (now < _dotUntil && now >= _nextDot) { _nextDot = now + 1f; float damage = Mathf.Round(Random.Range(4f, 9f)); _queue.Add(new Item { At = now, Type = (TextType)0, Text = damage.ToString("0.#", CultureInfo.InvariantCulture), Offset = new Vector3(0f, 1.6f, 3f), HasHit = true, Hit = new HitInfo { Damage = damage, MaxHealth = 200f, Dot = true, Elemental = true, Majority = (DamageType)32, TargetId = -4242 } }); } if (now < _rainUntil && now >= _nextRain) { _nextRain = now + 0.22f; TextType type = (TextType)Random.Range(0, 3); Add(now, type, Random.Range(2, 320).ToString(), Random.value < 0.15f, new Vector3(Random.Range(-2.5f, 2.5f), Random.Range(0.9f, 2.1f), Random.Range(2f, 7f))); } if (_queue.Count == 0) { return; } Player localPlayer = Player.m_localPlayer; DamageText instance = DamageText.instance; Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)mainCamera == (Object)null) { _queue.Clear(); return; } Transform transform = ((Component)localPlayer).transform; for (int i = 0; i < _queue.Count; i++) { Item item = _queue[i]; if (item.At > now) { continue; } _queue.RemoveAt(i--); Vector3 val = transform.position + transform.right * item.Offset.x + Vector3.up * item.Offset.y + transform.forward * item.Offset.z; float num = Vector3.Distance(((Component)mainCamera).transform.position, val); HitInfo info = HitContext.Take(); DurationOverride = _hold; FreezeMotion = _hold > 0f; try { if (item.HasHit) { HitInfo hit = item.Hit; hit.Pos = val; HitContext.Set(hit); } instance.AddInworldText(item.Type, val, num, item.Text, item.MySelf); if (item.Kill && PluginConfig.KillEnabled.Value) { Styles.ApplyKill(HitContext.Spawned); } } finally { DurationOverride = 0f; FreezeMotion = false; HitContext.Restore(info); } } } } public static class EdgeFlash { private const int TextureSize = 128; private static Image _image; private static Sprite _sprite; private static Texture2D _texture; private static float _builtThickness = -1f; private static float _intensity; public static bool Ready => (Object)(object)_image != (Object)null; public static void Trigger(float strength = 1f) { if (PluginConfig.EdgeFlash.Value && EnsureCreated()) { _intensity = Mathf.Max(_intensity, Mathf.Clamp01(strength)); ((Component)_image).gameObject.SetActive(true); Paint(); } } public static void Update(float dt) { if (!((Object)(object)_image == (Object)null) && !(_intensity <= 0f)) { float num = Mathf.Max(0.05f, PluginConfig.EdgeFlashFade.Value); _intensity -= dt / num; if (_intensity <= 0f) { _intensity = 0f; ((Component)_image).gameObject.SetActive(false); } else { Paint(); } } } public static void Invalidate() { if (_builtThickness >= 0f && !Mathf.Approximately(_builtThickness, PluginConfig.EdgeFlashThickness.Value)) { Rebuild(); } } public static void Destroy() { if ((Object)(object)_image != (Object)null) { Object.Destroy((Object)(object)((Component)_image).gameObject); } _image = null; _intensity = 0f; DestroyTexture(); } private static void Paint() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Color value = PluginConfig.EdgeFlashColor.Value; value.a *= _intensity; ((Graphic)_image).color = value; } private static bool EnsureCreated() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_image != (Object)null && (Object)(object)((Component)_image).gameObject != (Object)null) { return true; } Canvas val = FindCanvas(); if ((Object)(object)val == (Object)null) { return false; } GameObject val2 = new GameObject("DamageSplashEdgeFlash", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform val3 = (RectTransform)val2.transform; ((Transform)val3).SetParent(((Component)val).transform, false); val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; ((Transform)val3).SetAsFirstSibling(); _image = val2.GetComponent<Image>(); ((Graphic)_image).raycastTarget = false; DestroyTexture(); _image.sprite = BuildSprite(); _image.type = (Type)0; val2.SetActive(false); if (PluginConfig.Verbose.Value) { DamageSplashPlugin.Log.LogDebug((object)("edge flash attached to canvas " + ((Object)val).name)); } return true; } private static Canvas FindCanvas() { if ((Object)(object)DamageText.instance != (Object)null) { Canvas componentInParent = ((Component)DamageText.instance).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent != (Object)null) { if (!((Object)(object)componentInParent.rootCanvas != (Object)null)) { return componentInParent; } return componentInParent.rootCanvas; } } if ((Object)(object)Hud.instance != (Object)null) { Canvas componentInParent2 = ((Component)Hud.instance).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent2 != (Object)null) { if (!((Object)(object)componentInParent2.rootCanvas != (Object)null)) { return componentInParent2; } return componentInParent2.rootCanvas; } } return null; } private static void Rebuild() { if (!((Object)(object)_image == (Object)null)) { DestroyTexture(); _image.sprite = BuildSprite(); } } private static Sprite BuildSprite() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) float num = (_builtThickness = Mathf.Clamp(PluginConfig.EdgeFlashThickness.Value, 0.05f, 1f)); _texture = new Texture2D(128, 128, (TextureFormat)4, false); ((Texture)_texture).wrapMode = (TextureWrapMode)1; ((Texture)_texture).filterMode = (FilterMode)1; Color32[] array = (Color32[])(object)new Color32[16384]; float num2 = 1f - num; for (int i = 0; i < 128; i++) { float num3 = Mathf.Abs(((float)i + 0.5f) / 128f * 2f - 1f); for (int j = 0; j < 128; j++) { float num4 = Mathf.Max(Mathf.Abs(((float)j + 0.5f) / 128f * 2f - 1f), num3); float num5 = ((num2 >= 1f) ? 0f : Mathf.Clamp01((num4 - num2) / (1f - num2))); num5 *= num5; array[i * 128 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num5 * 255f)); } } _texture.SetPixels32(array); _texture.Apply(false); _sprite = Sprite.Create(_texture, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f)); return _sprite; } private static void DestroyTexture() { if ((Object)(object)_sprite != (Object)null) { Object.Destroy((Object)(object)_sprite); } if ((Object)(object)_texture != (Object)null) { Object.Destroy((Object)(object)_texture); } _sprite = null; _texture = null; _builtThickness = -1f; } } public static class Fonts { public const string VanillaName = "Vanilla"; private static readonly Dictionary<string, TMP_FontAsset> _byName = new Dictionary<string, TMP_FontAsset>(StringComparer.OrdinalIgnoreCase); private static List<string> _names = new List<string> { "Vanilla" }; private static readonly HashSet<string> _warned = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public static IList<string> Names => _names; public static bool Scanned { get; private set; } public static void Refresh() { _byName.Clear(); try { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && !((Object)(object)val.atlasTexture == (Object)null) && !_byName.ContainsKey(((Object)val).name)) { _byName[((Object)val).name] = val; } } } catch (Exception ex) { DamageSplashPlugin.Log.LogWarning((object)("font scan failed: " + ex.Message)); } List<string> list = new List<string>(_byName.Keys); list.Sort(delegate(string a, string b) { int num = Rank(a); int num2 = Rank(b); return (num == num2) ? string.Compare(a, b, StringComparison.OrdinalIgnoreCase) : num.CompareTo(num2); }); list.Insert(0, "Vanilla"); _names = list; Scanned = true; } private static int Rank(string name) { return (!name.StartsWith("Valheim", StringComparison.OrdinalIgnoreCase)) ? 1 : 0; } public static TMP_FontAsset Resolve(string name) { if (string.IsNullOrEmpty(name) || string.Equals(name, "Vanilla", StringComparison.OrdinalIgnoreCase)) { return null; } if (_byName.TryGetValue(name, out var value) && (Object)(object)value != (Object)null) { return value; } string text = Fuzzy(name); if (text != null && _byName.TryGetValue(text, out value) && (Object)(object)value != (Object)null) { return value; } if (Scanned && _warned.Add(name)) { DamageSplashPlugin.Log.LogWarning((object)("font \"" + name + "\" is not loaded; using the vanilla damage-text font")); } return null; } private static string Fuzzy(string name) { string[] array = name.Split(new char[3] { ' ', '-', '_' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return null; } foreach (string name2 in _names) { if (name2 == "Vanilla") { continue; } bool flag = true; string[] array2 = array; foreach (string value in array2) { if (name2.IndexOf(value, StringComparison.OrdinalIgnoreCase) < 0) { flag = false; break; } } if (flag) { return name2; } } return null; } public static string PreferredDisplay() { string text = Fuzzy("AveriaSansLibre"); if (text != null) { return text; } string text2 = Fuzzy("Norse"); if (text2 != null) { return text2; } return "Vanilla"; } } public static class Guard { private const int MaxReportsPerSite = 3; private static readonly Dictionary<string, int> _reports = new Dictionary<string, int>(); public static void Report(string site, Exception ex) { _reports.TryGetValue(site, out var value); value = (_reports[site] = value + 1); if (value <= 3) { DamageSplashPlugin.Log.LogError((object)(site + " failed; the game carries on without DamageSplash styling for it" + ((value == 3) ? " (further errors here are not logged)" : "") + ": " + ex)); } } } public struct HitInfo { public bool Valid; public Vector3 Pos; public float Damage; public float MaxHealth; public int TargetId; public int Frame; public bool WasAlive; public bool AttackerIsLocal; public bool TargetIsLocalPlayer; public bool Sneak; public bool StaggerCrit; public bool Dot; public bool Elemental; public DamageType Majority; public Splash Spawned; } public static class HitContext { private const float MatchDistanceSq = 1f; private static HitInfo _current; public static bool Has => _current.Valid; public static Splash Spawned => _current.Spawned; public static bool WasAlive => _current.WasAlive; public static void Set(HitInfo info) { info.Valid = true; info.Frame = Time.frameCount; _current = info; } public static void Clear() { _current = default(HitInfo); } public static HitInfo Take() { HitInfo current = _current; _current = default(HitInfo); return current; } public static void Restore(HitInfo info) { _current = info; } public unsafe static bool TryMatch(Vector3 pos, out HitInfo info) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) info = _current; if (!IsLive()) { info = default(HitInfo); return false; } Vector3 val = pos - _current.Pos; if (((Vector3)(ref val)).sqrMagnitude > 1f) { if (PluginConfig.Verbose.Value) { ManualLogSource log = DamageSplashPlugin.Log; val = pos; string? text = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); val = _current.Pos; log.LogDebug((object)("context ignored: text at " + text + " is not the hit at " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString())); } info = default(HitInfo); return false; } return true; } public static void SetSpawned(Vector3 pos, Splash splash) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (IsLive()) { Vector3 val = pos - _current.Pos; if (!(((Vector3)(ref val)).sqrMagnitude > 1f)) { _current.Spawned = splash; } } } private static bool IsLive() { if (_current.Valid) { return _current.Frame == Time.frameCount; } return false; } } public static class Merger { public static int KeyFor(Style style, TextType type, bool mySelf) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected I4, but got Unknown if (style.TargetId == 0 || style.Tagged || WindowFor(style) <= 0f) { return 0; } int targetId = style.TargetId; targetId = targetId * 31 + type; targetId = targetId * 31 + (mySelf ? 1 : 0); targetId = targetId * 31 + (style.Dot ? 1 : 0); if (targetId != 0) { return targetId; } return 1; } public static float WindowFor(Style style) { if (!style.Dot) { return PluginConfig.HitMergeWindow.Value; } return PluginConfig.DotMergeWindow.Value; } public static Splash TryMerge(Style style, TextType type, int key, Vector3 worldPos) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) if (key == 0) { return null; } Splash splash = SplashPool.FindMergeable(key, Time.time, WindowFor(style), PluginConfig.MergeMaxLife.Value); if (splash == null) { return null; } splash.Value += style.Value; splash.Number = Styles.NumberText(type, splash.Value); splash.Text.text = splash.Number; splash.Text.fontSize = splash.BaseFontSize * Styles.ScaleForValue(splash.Value, splash.MaxHealth); splash.Origin = worldPos; splash.Offset = Vector3.zero; splash.Velocity = Animation.InitialVelocity(ref splash.Anim); splash.Anim.Bounced = false; splash.Timer = 0f; splash.Tr.localScale = Vector3.one * ((splash.Anim.PopDuration > 0f) ? splash.Anim.PopFrom : 1f); return splash; } } public static class OutgoingHits { private const int Capacity = 16; private const float MatchDistanceSq = 0.0625f; private const float MaxAge = 3f; private static readonly Vector3[] _points = (Vector3[])(object)new Vector3[16]; private static readonly float[] _times = new float[16]; private static int _next; public static void Record(Vector3 point) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) _points[_next] = point; _times[_next] = Time.time; _next = (_next + 1) % 16; } public static bool Matches(Vector3 pos) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; for (int i = 0; i < 16; i++) { float num = time - _times[i]; if (_times[i] > 0f && num >= 0f && num <= 3f) { Vector3 val = pos - _points[i]; if (((Vector3)(ref val)).sqrMagnitude <= 0.0625f) { return true; } } } return false; } } public sealed class Splash { public GameObject Go; public Transform Tr; public TMP_Text Text; public Vector3 Origin; public Vector3 Offset; public Vector3 Velocity; public float Timer; public float Duration; public float Tilt; public float BaseFontSize; public string Number; public float Value; public float MaxHealth; public int MergeKey; public float FirstSpawn; public AnimParams Anim; public Color Color; public TextType Type; public bool Visible; } public static class SplashPool { private static readonly List<Splash> _active = new List<Splash>(64); private static readonly Stack<Splash> _free = new Stack<Splash>(64); private static Transform _parent; private static GameObject _prefab; private static bool _ready; public static TMP_FontAsset PrefabFont { get; private set; } public static Material PrefabMaterial { get; private set; } public static int ActiveCount => _active.Count; public static int FreeCount => _free.Count; public static bool Ready => _ready; public static void Init(DamageText dt) { Clear(); _parent = ((Component)dt).transform; _prefab = dt.m_worldTextBase; TMP_Text val = (((Object)(object)_prefab != (Object)null) ? _prefab.GetComponent<TMP_Text>() : null); PrefabFont = (((Object)(object)val != (Object)null) ? val.font : null); PrefabMaterial = (((Object)(object)val != (Object)null) ? val.fontSharedMaterial : null); _ready = (Object)(object)_prefab != (Object)null && (Object)(object)val != (Object)null; if (!_ready) { DamageSplashPlugin.Log.LogWarning((object)"DamageText prefab has no TMP_Text; leaving vanilla in charge"); } else if (PluginConfig.Verbose.Value) { DamageSplashPlugin.Log.LogDebug((object)("pool ready: prefab font " + (((Object)(object)PrefabFont != (Object)null) ? ((Object)PrefabFont).name : "none") + ", material " + (((Object)(object)PrefabMaterial != (Object)null) ? (((Object)PrefabMaterial).name + " / " + ((Object)PrefabMaterial.shader).name) : "none"))); } } public static void Clear() { foreach (Splash item in _active) { if ((Object)(object)item.Go != (Object)null) { Object.Destroy((Object)(object)item.Go); } } foreach (Splash item2 in _free) { if ((Object)(object)item2.Go != (Object)null) { Object.Destroy((Object)(object)item2.Go); } } _active.Clear(); _free.Clear(); _ready = false; } public static Splash FindMergeable(int key, float now, float window, float maxLife) { if (key == 0) { return null; } for (int num = _active.Count - 1; num >= 0; num--) { Splash splash = _active[num]; if (splash.MergeKey == key && !((Object)(object)splash.Go == (Object)null) && !(splash.Timer > window) && !(now - splash.FirstSpawn > maxLife)) { return splash; } } return null; } public static Splash Spawn(Style style, string text, Vector3 worldPos, float distance, TextType type, int mergeKey = 0) { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references