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 Skaldsong v1.0.0
plugins\Skaldsong.dll
Decompiled 3 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; 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: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Skaldsong")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Skaldsong")] [assembly: AssemblyTitle("Skaldsong")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Skaldsong { [BepInPlugin("com.TwoStubbornStudios.skaldsong", "Skaldsong", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string GUID = "com.TwoStubbornStudios.skaldsong"; public const string Name = "Skaldsong"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static Plugin Instance; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> SuppressVanillaMessage; internal static ConfigEntry<float> VerticalOffset; internal static ConfigEntry<float> HoldDuration; internal static ConfigEntry<float> BarFillDuration; internal static ConfigEntry<float> BarFillStartDelay; internal static ConfigEntry<bool> UseParchment; internal static ConfigEntry<string> PanelSpriteName; internal static ConfigEntry<string> PanelColor; internal static ConfigEntry<float> PanelOpacity; internal static ConfigEntry<string> BarTrackColor; internal static ConfigEntry<string> BarFillColor; internal static ConfigEntry<string> TextColor; internal static ConfigEntry<float> TextOutlineOpacity; internal static ConfigEntry<string> LevelSeparator; internal static ConfigEntry<float> SoundVolume; internal static ConfigEntry<bool> PlayOwnSound; internal static ConfigEntry<string> DisabledSkills; internal static ConfigEntry<bool> ShowPanelBorder; internal static ConfigEntry<string> PanelBorderColor; internal static ConfigEntry<float> PanelBorderThickness; private Harmony _harmony; private static readonly HashSet<SkillType> _disabledSkillSet = new HashSet<SkillType>(); internal ToastController Toast { get; private set; } internal SkillSoundPlayer Sound { get; private set; } private void Awake() { //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enables the skill level-up toast and sound."); SuppressVanillaMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SuppressVanillaMessage", true, "When true, suppresses vanilla's own \"Skill increased\" center/top-left message so only the Skaldsong toast is shown. Vanilla's level-up sound and particle effect are unaffected."); VerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Toast", "VerticalOffset", 0.25f, "Vertical position of the toast, as a fraction (0-1) of the HUD canvas height measured from the bottom edge."); HoldDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Toast", "HoldDuration", 2f, "How long, in seconds, the toast stays fully visible before fading out."); BarFillDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Toast", "BarFillDuration", 1f, "Seconds for the fill bar to sweep from 0% to 100%."); BarFillStartDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Toast", "BarFillStartDelay", 0.1f, "Pause, in seconds, after the toast finishes sliding in before the fill bar begins filling."); UseParchment = ((BaseUnityPlugin)this).Config.Bind<bool>("Toast", "UseParchment", true, "When true, render the toast background using a native Valheim parchment/panel sprite found at runtime. When false, always use the flat tinted panel."); PanelSpriteName = ((BaseUnityPlugin)this).Config.Bind<string>("Toast", "PanelSpriteName", "", "Optional: exact (case-insensitive) sprite name to pin the toast background to, overriding the automatic scorer. See the log for the candidate list. Leave empty to use automatic scoring."); PanelColor = ((BaseUnityPlugin)this).Config.Bind<string>("Toast", "PanelColor", "#FFFFFF", "Hex tint color applied to the toast background (parchment sprite, or the flat panel when UseParchment is false / no sprite is found)."); PanelOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Toast", "PanelOpacity", 1f, new ConfigDescription("Opacity of the toast background panel (0-1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); BarTrackColor = ((BaseUnityPlugin)this).Config.Bind<string>("Toast", "BarTrackColor", "#000000", "Hex color of the fill bar's background track."); BarFillColor = ((BaseUnityPlugin)this).Config.Bind<string>("Toast", "BarFillColor", "#5FC9E8", "Hex color of the fill bar itself, used for all skills (no longer per-skill palette colored)."); TextColor = ((BaseUnityPlugin)this).Config.Bind<string>("Toast", "TextColor", "#F2E8D5", "Hex color of the toast's skill name and level text."); TextOutlineOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Toast", "TextOutlineOpacity", 0.35f, new ConfigDescription("Opacity of the black text outline (0-1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); LevelSeparator = ((BaseUnityPlugin)this).Config.Bind<string>("Toast", "LevelSeparator", "LVL", "Text shown between the skill name and the level number, e.g. \"Wood Cutting LVL 68\"."); SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sound", "SoundVolume", 1f, new ConfigDescription("Volume of the level-up sound (0-1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); PlayOwnSound = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound", "PlayOwnSound", false, "When true, Skaldsong plays its own copy of the level-up sound (using SoundVolume). When false (default), it relies on vanilla's own level-up sound (which already plays alongside the golden halo effect) and does not duplicate it."); DisabledSkills = ((BaseUnityPlugin)this).Config.Bind<string>("Skills", "DisabledSkills", "", "Comma-separated list of skill names to disable the Skaldsong toast (and, if PlayOwnSound is true, the sound) for. Case-insensitive, whitespace trimmed, unknown names ignored. Vanilla's own message suppression is unaffected by this list. Accepted names: " + string.Join(", ", GetAllSkillNames()) + ". Example: WoodCutting,Sneak"); ShowPanelBorder = ((BaseUnityPlugin)this).Config.Bind<bool>("Toast", "ShowPanelBorder", true, "When true, draws a thin dark outline framing the entire toast panel."); PanelBorderColor = ((BaseUnityPlugin)this).Config.Bind<string>("Toast", "PanelBorderColor", "#000000", "Hex color of the thin outline drawn around the toast panel."); PanelBorderThickness = ((BaseUnityPlugin)this).Config.Bind<float>("Toast", "PanelBorderThickness", 2.5f, "Thickness, in pixels, of the outline band shown around the toast panel."); Toast = ((Component)this).gameObject.AddComponent<ToastController>(); Sound = ((Component)this).gameObject.AddComponent<SkillSoundPlayer>(); _harmony = new Harmony("com.TwoStubbornStudios.skaldsong"); _harmony.PatchAll(); RegisterConsoleCommands(); ParseDisabledSkills(); Log.LogInfo((object)"Skaldsong 1.0.0 loaded."); } internal void ShowLevelUpToast(SkillType skillType, int level) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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) try { if (_disabledSkillSet.Contains(skillType)) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)((Character)localPlayer).GetSkills() == (Object)null)) { Sprite icon = null; SkillDef val = ((Character)localPlayer).GetSkills().m_skills.Find((SkillDef s) => s.m_skill == skillType); if (val != null) { icon = val.m_icon; } string displayName = SkillNames.GetDisplayName(skillType); Toast.Show(skillType, level, icon, displayName, VerticalOffset.Value, HoldDuration.Value, BarFillDuration.Value, BarFillStartDelay.Value, PanelColor.Value, PanelOpacity.Value, BarTrackColor.Value, UseParchment.Value, TextColor.Value, TextOutlineOpacity.Value, LevelSeparator.Value, BarFillColor.Value, ShowPanelBorder.Value, PanelBorderColor.Value, PanelBorderThickness.Value); if (PlayOwnSound.Value) { Sound.PlayLevelUp(SoundVolume.Value); } } } catch (Exception arg) { Log.LogError((object)$"[Skaldsong] Error showing level-up toast: {arg}"); } } private unsafe static void ParseDisabledSkills() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) _disabledSkillSet.Clear(); string value = DisabledSkills.Value; if (string.IsNullOrWhiteSpace(value)) { return; } List<string> list = new List<string>(); string[] array = value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } if (TryParseSkillType(text, out var result)) { if (_disabledSkillSet.Add(result)) { list.Add(((object)(*(SkillType*)(&result))/*cast due to .constrained prefix*/).ToString()); } } else { Log.LogWarning((object)("[Skaldsong] DisabledSkills: unknown skill name '" + text + "' ignored.")); } } if (list.Count > 0) { Log.LogInfo((object)("[Skaldsong] Toasts disabled for skills: " + string.Join(", ", list))); } } private static List<string> GetAllSkillNames() { //IL_0023: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 List<string> list = new List<string>(); foreach (SkillType value in Enum.GetValues(typeof(SkillType))) { if ((int)value != 0 && (int)value != 999) { list.Add(((object)value/*cast due to .constrained prefix*/).ToString()); } } return list; } private void RegisterConsoleCommands() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand("skaldsong_test", "skaldsong_test <skillname> <level> - shows a Skaldsong level-up toast without gaining a level.", (ConsoleEvent)delegate(ConsoleEventArgs args) { //IL_0002: 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) try { SkillType result = (SkillType)13; if (args.Length > 1 && !TryParseSkillType(args[1], out result)) { args.Context.AddString("[Skaldsong] Unknown skill '" + args[1] + "'."); } else { int level = args.TryParameterInt(2, Random.Range(1, 101)); ShowLevelUpToast(result, level); } } catch (Exception arg) { Log.LogError((object)$"[Skaldsong] Error in skaldsong_test command: {arg}"); } }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static bool TryParseSkillType(string name, out SkillType result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_002c: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected I4, but got Unknown foreach (SkillType value in Enum.GetValues(typeof(SkillType))) { if ((int)value != 0 && (int)value != 999 && string.Equals(((object)value/*cast due to .constrained prefix*/).ToString(), name, StringComparison.OrdinalIgnoreCase)) { result = (SkillType)(int)value; return true; } } result = (SkillType)0; return false; } } [HarmonyPatch(typeof(Player), "OnSkillLevelup")] public static class SkillLevelupPatch { private static void Postfix(Player __instance, SkillType skill, float level) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) try { Plugin.Log.LogInfo((object)$"[Skaldsong] Skill leveled: {skill} -> {(int)level}"); if (Plugin.Enabled.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { Plugin.Instance.ShowLevelUpToast(skill, (int)level); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Skaldsong] Error in SkillLevelupPatch: {arg}"); } } } [HarmonyPatch(typeof(Player), "Message")] public static class PlayerMessageSuppressPatch { private const string SkillUpToken = "$msg_skillup"; private static bool _localizedPrefixResolved; private static string _localizedSkillUpPrefix; private static bool Prefix(string msg) { try { if (!Plugin.SuppressVanillaMessage.Value || string.IsNullOrEmpty(msg)) { return true; } if (msg.StartsWith("$msg_skillup", StringComparison.Ordinal)) { return false; } string localizedSkillUpPrefix = GetLocalizedSkillUpPrefix(); if (!string.IsNullOrEmpty(localizedSkillUpPrefix) && msg.StartsWith(localizedSkillUpPrefix, StringComparison.Ordinal)) { return false; } return true; } catch (Exception arg) { Plugin.Log.LogError((object)$"[Skaldsong] Error in PlayerMessageSuppressPatch: {arg}"); return true; } } private static string GetLocalizedSkillUpPrefix() { if (_localizedPrefixResolved) { return _localizedSkillUpPrefix; } _localizedPrefixResolved = true; if (Localization.instance != null) { string text = Localization.instance.Localize("$msg_skillup"); if (!string.IsNullOrEmpty(text) && text != "$msg_skillup") { _localizedSkillUpPrefix = text; } } return _localizedSkillUpPrefix; } } internal static class SkillNames { public unsafe static string GetDisplayName(SkillType skillType) { string text = ((object)(*(SkillType*)(&skillType))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(); string text2 = "$skill_" + text; string text3 = Localization.instance.Localize(text2); if (text3.StartsWith("[") && text3.EndsWith("]")) { return SpacedTitleCase(((object)(*(SkillType*)(&skillType))/*cast due to .constrained prefix*/).ToString()); } return text3; } private static string SpacedTitleCase(string enumName) { StringBuilder stringBuilder = new StringBuilder(enumName.Length + 4); for (int i = 0; i < enumName.Length; i++) { char c = enumName[i]; if (i > 0 && char.IsUpper(c) && !char.IsUpper(enumName[i - 1])) { stringBuilder.Append(' '); } stringBuilder.Append(c); } return stringBuilder.ToString(); } } internal static class SkillPalette { private static readonly Color FallbackColor = HexToColor("#C8C8C8"); private static readonly Dictionary<SkillType, Color> Colors = new Dictionary<SkillType, Color> { { (SkillType)1, HexToColor("#9CC4E4") }, { (SkillType)2, HexToColor("#5FD8C8") }, { (SkillType)3, HexToColor("#78889C") }, { (SkillType)4, HexToColor("#A79BD8") }, { (SkillType)5, HexToColor("#6FA8D4") }, { (SkillType)7, HexToColor("#4E93A8") }, { (SkillType)11, HexToColor("#B5BCC4") }, { (SkillType)8, HexToColor("#B89AE0") }, { (SkillType)14, HexToColor("#8E6FD0") }, { (SkillType)9, HexToColor("#54D0F0") }, { (SkillType)10, HexToColor("#E0607F") }, { (SkillType)6, HexToColor("#E0C04A") }, { (SkillType)108, HexToColor("#C9A96E") }, { (SkillType)13, HexToColor("#5CA84B") }, { (SkillType)12, HexToColor("#8FA085") }, { (SkillType)104, HexToColor("#4FA88C") }, { (SkillType)106, HexToColor("#9CC44E") }, { (SkillType)107, HexToColor("#C87F3F") }, { (SkillType)105, HexToColor("#E8944A") }, { (SkillType)100, HexToColor("#8FE0F0") }, { (SkillType)101, HexToColor("#4E8A94") }, { (SkillType)102, HexToColor("#3FC9A8") }, { (SkillType)103, HexToColor("#3FA8D8") }, { (SkillType)110, HexToColor("#6FBFC4") } }; public static Color GetColor(SkillType skillType) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (Colors.TryGetValue(skillType, out var value)) { return value; } return FallbackColor; } private static Color HexToColor(string hex) { //IL_000c: 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) Color result = default(Color); if (ColorUtility.TryParseHtmlString(hex, ref result)) { return result; } return FallbackColor; } } internal class SkillSoundPlayer : MonoBehaviour { private AudioSource _audioSource; private AudioClip _cachedClip; private bool _resolutionAttempted; private bool _missingClipWarningLogged; private void Awake() { _audioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); _audioSource.playOnAwake = false; _audioSource.spatialBlend = 0f; } public void PlayLevelUp(float volume) { try { AudioClip levelUpClip = GetLevelUpClip(); if ((Object)(object)levelUpClip == (Object)null) { if (!_missingClipWarningLogged) { _missingClipWarningLogged = true; Plugin.Log.LogWarning((object)"[Skaldsong] Could not resolve vanilla skill level-up sound clip; skipping playback."); } } else { _audioSource.PlayOneShot(levelUpClip, Mathf.Clamp01(volume)); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Skaldsong] Error in SkillSoundPlayer.PlayLevelUp: {arg}"); } } private AudioClip GetLevelUpClip() { if ((Object)(object)_cachedClip != (Object)null) { return _cachedClip; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } if (_resolutionAttempted) { return null; } _resolutionAttempted = true; EffectList skillLevelupEffects = localPlayer.m_skillLevelupEffects; if (skillLevelupEffects?.m_effectPrefabs == null) { return null; } EffectData[] effectPrefabs = skillLevelupEffects.m_effectPrefabs; foreach (EffectData val in effectPrefabs) { if (val.m_enabled && !((Object)(object)val.m_prefab == (Object)null)) { ZSFX componentInChildren = val.m_prefab.GetComponentInChildren<ZSFX>(); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.m_audioClips != null && componentInChildren.m_audioClips.Length != 0) { _cachedClip = componentInChildren.m_audioClips[0]; return _cachedClip; } AudioSource componentInChildren2 = val.m_prefab.GetComponentInChildren<AudioSource>(); if ((Object)(object)componentInChildren2 != (Object)null && (Object)(object)componentInChildren2.clip != (Object)null) { _cachedClip = componentInChildren2.clip; return _cachedClip; } } } return null; } } internal class ToastController : MonoBehaviour { private struct SpriteCandidate { public string Label; public string ObjectName; public Sprite Sprite; public int Score; } private struct ToastRequest { public SkillType SkillType; public int Level; public Sprite Icon; public string DisplayName; public float VerticalOffsetFraction; public float HoldDuration; public float BarFillDuration; public float BarFillStartDelay; public string PanelColorHex; public float PanelOpacity; public string BarTrackColorHex; public bool UseParchment; public string TextColorHex; public float TextOutlineOpacity; public string LevelSeparator; public string BarFillColorHex; public bool ShowPanelBorder; public string PanelBorderColorHex; public float PanelBorderThickness; } private const float SlideInDuration = 0.25f; private const float NumberTickDuration = 0.2f; private const float FadeOutDuration = 0.5f; private const float SlideDistance = 40f; private const float ToastWidth = 360f; private const float ToastHeight = 72f; private const float BarHeight = 8f; private const float TrackAlpha = 0.7f; private const float TextOutlineWidth = 0f; private const string DefaultLevelSeparator = "LVL"; private static readonly Color DefaultPanelColor = new Color(2f / 51f, 2f / 51f, 2f / 51f, 1f); private static readonly Color DefaultTrackColor = Color.black; private static readonly Color DefaultTextColor = Color32.op_Implicit(new Color32((byte)242, (byte)232, (byte)213, byte.MaxValue)); private static readonly Color DefaultBarFillColor = Color32.op_Implicit(new Color32((byte)95, (byte)201, (byte)232, byte.MaxValue)); private static readonly Color DefaultPanelBorderColor = Color.black; private const int MaxQueueSize = 20; private static bool _panelLookupDone; private static Sprite _cachedPanelSprite; private static bool _parchmentDisabledLogged; private RectTransform _root; private CanvasGroup _canvasGroup; private Image _panelBorder; private Image _background; private Image _icon; private RectTransform _textContainer; private TextMeshProUGUI _nameText; private TextMeshProUGUI _levelText; private Image _barTrack; private Image _barFill; private Coroutine _animCoroutine; private bool _hudMissingWarningLogged; private readonly Queue<ToastRequest> _queue = new Queue<ToastRequest>(); public void Show(SkillType skillType, int level, Sprite icon, string displayName, float verticalOffsetFraction, float holdDuration, float barFillDuration, float barFillStartDelay, string panelColorHex, float panelOpacity, string barTrackColorHex, bool useParchment, string textColorHex, float textOutlineOpacity, string levelSeparator, string barFillColorHex, bool showPanelBorder, string panelBorderColorHex, float panelBorderThickness) { //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) try { ToastRequest request = new ToastRequest { SkillType = skillType, Level = level, Icon = icon, DisplayName = displayName, VerticalOffsetFraction = verticalOffsetFraction, HoldDuration = holdDuration, BarFillDuration = barFillDuration, BarFillStartDelay = barFillStartDelay, PanelColorHex = panelColorHex, PanelOpacity = panelOpacity, BarTrackColorHex = barTrackColorHex, UseParchment = useParchment, TextColorHex = textColorHex, TextOutlineOpacity = textOutlineOpacity, LevelSeparator = levelSeparator, BarFillColorHex = barFillColorHex, ShowPanelBorder = showPanelBorder, PanelBorderColorHex = panelBorderColorHex, PanelBorderThickness = panelBorderThickness }; EnqueueRequest(request); TryPlayNext(); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Skaldsong] Error enqueuing toast: {arg}"); } } private void EnqueueRequest(ToastRequest request) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (_queue.Count < 20) { _queue.Enqueue(request); } else if (!TryCollapseDuplicate(request)) { Plugin.Log.LogWarning((object)$"[Skaldsong] Toast queue full ({20}); dropping level-up for {request.SkillType} -> {request.Level}."); } } private bool TryCollapseDuplicate(ToastRequest incoming) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (_queue.Count == 0) { return false; } List<ToastRequest> list = new List<ToastRequest>(_queue); bool flag = false; for (int i = 0; i < list.Count; i++) { if (list[i].SkillType == incoming.SkillType) { if (incoming.Level > list[i].Level) { ToastRequest value = list[i]; value.Level = incoming.Level; value.Icon = incoming.Icon; value.DisplayName = incoming.DisplayName; list[i] = value; } flag = true; break; } } if (flag) { _queue.Clear(); foreach (ToastRequest item in list) { _queue.Enqueue(item); } } return flag; } private void TryPlayNext() { if (_animCoroutine == null && _queue.Count != 0) { PlayRequest(_queue.Dequeue()); } } private void PlayRequest(ToastRequest request) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: 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_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) Hud instance = Hud.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_rootObject == (Object)null) { if (!_hudMissingWarningLogged) { _hudMissingWarningLogged = true; Plugin.Log.LogWarning((object)"[Skaldsong] Hud.instance not available; skipping toast."); } return; } _hudMissingWarningLogged = false; BuildIfNeeded(instance); if (!((Object)(object)_root == (Object)null)) { Color panelColor = ParseHexColor(request.PanelColorHex, DefaultPanelColor); panelColor.a = Mathf.Clamp01(request.PanelOpacity); ApplyBackground(request.UseParchment, panelColor); Color color = ParseHexColor(request.BarTrackColorHex, DefaultTrackColor); color.a = 0.7f; ((Graphic)_barTrack).color = color; Color val = ParseHexColor(request.BarFillColorHex, DefaultBarFillColor); ((Graphic)_barFill).color = new Color(val.r, val.g, val.b, 1f); Color color2 = ParseHexColor(request.TextColorHex, DefaultTextColor); ((Graphic)_nameText).color = color2; ((Graphic)_levelText).color = color2; string text = (string.IsNullOrEmpty(request.LevelSeparator) ? "LVL" : request.LevelSeparator); int num = Mathf.Max(1, request.Level - 1); ((TMP_Text)_nameText).text = request.DisplayName + " " + text + " "; ((TMP_Text)_levelText).text = num.ToString(); ((TMP_Text)_levelText).rectTransform.anchoredPosition = new Vector2(((TMP_Text)_nameText).GetPreferredValues(((TMP_Text)_nameText).text, 0f, 0f).x, 0f); ((Transform)((TMP_Text)_levelText).rectTransform).localScale = Vector3.one; Color color3 = ParseHexColor(request.PanelBorderColorHex, DefaultPanelBorderColor); ((Graphic)_panelBorder).color = color3; ((Behaviour)_panelBorder).enabled = request.ShowPanelBorder; float num2 = Mathf.Max(0f, request.PanelBorderThickness); RectTransform val2 = (RectTransform)((Component)_panelBorder).transform; val2.offsetMin = new Vector2(0f - num2, 0f - num2); val2.offsetMax = new Vector2(num2, num2); _icon.sprite = request.Icon; ((Behaviour)_icon).enabled = (Object)(object)request.Icon != (Object)null; _barFill.fillAmount = 0f; _canvasGroup.alpha = 0f; float targetY = GetCanvasHeight(instance) * Mathf.Clamp01(request.VerticalOffsetFraction); ((Component)_root).gameObject.SetActive(true); _animCoroutine = ((MonoBehaviour)this).StartCoroutine(Animate(targetY, Mathf.Max(0f, request.HoldDuration), request.Level, Mathf.Max(0.01f, request.BarFillDuration), Mathf.Max(0f, request.BarFillStartDelay))); } } private void BuildIfNeeded(Hud hud) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_010a: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: 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_01c6: 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_020d: Expected O, but got Unknown //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Expected O, but got Unknown //IL_0411: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Expected O, but got Unknown //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_04c5: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Expected O, but got Unknown //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root != (Object)null)) { GameObject val = new GameObject("SkaldsongToast", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(hud.m_rootObject.transform, false); _root = val.GetComponent<RectTransform>(); _root.anchorMin = new Vector2(0.5f, 0f); _root.anchorMax = new Vector2(0.5f, 0f); _root.pivot = new Vector2(0.5f, 0f); _root.sizeDelta = new Vector2(360f, 72f); _canvasGroup = val.AddComponent<CanvasGroup>(); _canvasGroup.alpha = 0f; _canvasGroup.blocksRaycasts = false; _canvasGroup.interactable = false; GameObject val2 = new GameObject("PanelBorder", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent((Transform)(object)_root, false); RectTransform val3 = (RectTransform)val2.transform; val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; _panelBorder = val2.AddComponent<Image>(); ((Graphic)_panelBorder).raycastTarget = false; GameObject val4 = new GameObject("Background", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent((Transform)(object)_root, false); RectTransform val5 = (RectTransform)val4.transform; val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; val5.offsetMin = Vector2.zero; val5.offsetMax = Vector2.zero; _background = val4.AddComponent<Image>(); ((Graphic)_background).raycastTarget = false; Sprite val6 = FindNativePanelSprite(); GameObject val7 = new GameObject("Icon", new Type[1] { typeof(RectTransform) }); val7.transform.SetParent((Transform)(object)_root, false); RectTransform val8 = (RectTransform)val7.transform; val8.anchorMin = new Vector2(0f, 0.64f); val8.anchorMax = new Vector2(0f, 0.64f); val8.pivot = new Vector2(0f, 0.5f); val8.anchoredPosition = new Vector2(8f, 0f); val8.sizeDelta = new Vector2(44f, 44f); _icon = val7.AddComponent<Image>(); ((Graphic)_icon).color = Color.white; _icon.preserveAspect = true; ((Graphic)_icon).raycastTarget = false; GameObject val9 = new GameObject("TextRow", new Type[1] { typeof(RectTransform) }); val9.transform.SetParent((Transform)(object)_root, false); _textContainer = (RectTransform)val9.transform; _textContainer.anchorMin = new Vector2(0f, 0.28f); _textContainer.anchorMax = new Vector2(1f, 1f); _textContainer.offsetMin = new Vector2(60f, 2f); _textContainer.offsetMax = new Vector2(-12f, -2f); TMP_FontAsset font = null; if ((Object)(object)MessageHud.instance != (Object)null && (Object)(object)MessageHud.instance.m_messageText != (Object)null) { font = MessageHud.instance.m_messageText.font; } _nameText = CreateTextLabel("NameText", _textContainer, font); _levelText = CreateTextLabel("LevelText", _textContainer, font); GameObject val10 = new GameObject("BarTrack", new Type[1] { typeof(RectTransform) }); val10.transform.SetParent((Transform)(object)_root, false); RectTransform val11 = (RectTransform)val10.transform; val11.anchorMin = new Vector2(0f, 0f); val11.anchorMax = new Vector2(1f, 0f); val11.offsetMin = new Vector2(12f, 6f); val11.offsetMax = new Vector2(-12f, 14f); _barTrack = val10.AddComponent<Image>(); ((Graphic)_barTrack).color = new Color(0f, 0f, 0f, 0.7f); ((Graphic)_barTrack).raycastTarget = false; GameObject val12 = new GameObject("BarFill", new Type[1] { typeof(RectTransform) }); val12.transform.SetParent((Transform)(object)val11, false); RectTransform val13 = (RectTransform)val12.transform; val13.anchorMin = Vector2.zero; val13.anchorMax = Vector2.one; val13.offsetMin = Vector2.zero; val13.offsetMax = Vector2.zero; _barFill = val12.AddComponent<Image>(); _barFill.sprite = (((Object)(object)val6 != (Object)null) ? val6 : Resources.GetBuiltinResource<Sprite>("UI/Skin/UISprite.psd")); _barFill.type = (Type)3; _barFill.fillMethod = (FillMethod)0; _barFill.fillOrigin = 0; _barFill.fillAmount = 0f; ((Graphic)_barFill).raycastTarget = false; val.SetActive(false); } } private static TextMeshProUGUI CreateTextLabel(string goName, RectTransform parent, TMP_FontAsset font) { //IL_0014: 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_0026: Unknown result type (might be due to invalid IL or missing references) //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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_005b: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(goName, new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)parent, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = new Vector2(0f, 0.5f); val2.anchorMax = new Vector2(0f, 0.5f); val2.pivot = new Vector2(0f, 0.5f); val2.anchoredPosition = Vector2.zero; val2.sizeDelta = new Vector2(260f, 32f); TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val3).alignment = (TextAlignmentOptions)4097; ((TMP_Text)val3).fontSize = 24f; ((TMP_Text)val3).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val3).overflowMode = (TextOverflowModes)0; ((Graphic)val3).raycastTarget = false; if ((Object)(object)font != (Object)null) { ((TMP_Text)val3).font = font; } ((TMP_Text)val3).outlineWidth = 0f; ((TMP_Text)val3).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)0); return val3; } private static Color ParseHexColor(string hex, Color fallback) { //IL_0014: 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) Color result = default(Color); if (!string.IsNullOrEmpty(hex) && ColorUtility.TryParseHtmlString(hex, ref result)) { return result; } return fallback; } private void ApplyBackground(bool useParchment, Color panelColor) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) Sprite val = (useParchment ? FindNativePanelSprite() : null); if (!useParchment && !_parchmentDisabledLogged) { _parchmentDisabledLogged = true; Plugin.Log.LogInfo((object)"[Skaldsong] UseParchment=false; toast background forced to the flat tinted panel."); } if ((Object)(object)val != (Object)null) { _background.sprite = val; _background.type = (Type)1; } else { _background.sprite = null; _background.type = (Type)0; } ((Graphic)_background).color = panelColor; } private static Sprite FindNativePanelSprite() { //IL_02e3: Unknown result type (might be due to invalid IL or missing references) if (_panelLookupDone) { return _cachedPanelSprite; } _panelLookupDone = true; List<SpriteCandidate> list = new List<SpriteCandidate>(); if ((Object)(object)InventoryGui.instance != (Object)null) { CollectCandidates("InventoryGui.instance", ((Component)InventoryGui.instance).transform, list); } if ((Object)(object)StoreGui.instance != (Object)null && (Object)(object)StoreGui.instance.m_rootPanel != (Object)null) { CollectCandidates("StoreGui.instance.m_rootPanel", StoreGui.instance.m_rootPanel.transform, list); } if ((Object)(object)TextViewer.instance != (Object)null && (Object)(object)TextViewer.instance.m_root != (Object)null) { CollectCandidates("TextViewer.instance.m_root", TextViewer.instance.m_root.transform, list); } if ((Object)(object)Menu.instance != (Object)null && (Object)(object)Menu.instance.m_root != (Object)null) { CollectCandidates("Menu.instance.m_root", Menu.instance.m_root, list); } if ((Object)(object)Chat.instance != (Object)null) { CollectCandidates("Chat.instance.m_chatWindow", (Transform)(object)((Terminal)Chat.instance).m_chatWindow, list); } if ((Object)(object)TextInput.instance != (Object)null && (Object)(object)TextInput.instance.m_panel != (Object)null) { CollectCandidates("TextInput.instance.m_panel", TextInput.instance.m_panel.transform, list); } if (list.Count == 0) { Plugin.Log.LogInfo((object)"[Skaldsong] No native 9-sliced parchment/panel sprite found reachable at runtime; toast background falls back to a flat tinted panel."); _cachedPanelSprite = null; return null; } Dictionary<Sprite, SpriteCandidate> dictionary = new Dictionary<Sprite, SpriteCandidate>(); foreach (SpriteCandidate item in list) { if (!dictionary.ContainsKey(item.Sprite)) { dictionary[item.Sprite] = item; } } SpriteCandidate spriteCandidate = default(SpriteCandidate); bool flag = false; string text = ((Plugin.PanelSpriteName != null) ? Plugin.PanelSpriteName.Value : null); if (!string.IsNullOrEmpty(text)) { foreach (SpriteCandidate value in dictionary.Values) { if (string.Equals(((Object)value.Sprite).name, text, StringComparison.OrdinalIgnoreCase)) { spriteCandidate = value; flag = true; break; } } if (flag) { Plugin.Log.LogInfo((object)("[Skaldsong] PanelSpriteName pin '" + text + "' matched a candidate; overriding scored selection.")); } else { Plugin.Log.LogInfo((object)("[Skaldsong] PanelSpriteName pin '" + text + "' did not match any candidate; falling back to scored selection.")); } } if (!flag) { foreach (SpriteCandidate value2 in dictionary.Values) { if (!flag || value2.Score > spriteCandidate.Score) { spriteCandidate = value2; flag = true; } } } Plugin.Log.LogInfo((object)$"[Skaldsong] Toast background sprite resolved from {spriteCandidate.Label} -> child '{spriteCandidate.ObjectName}' (sprite '{((Object)spriteCandidate.Sprite).name}', border {spriteCandidate.Sprite.border}, score {spriteCandidate.Score})."); if (dictionary.Count > 1) { List<string> list2 = new List<string>(); int num = 0; foreach (SpriteCandidate value3 in dictionary.Values) { if (!((Object)(object)value3.Sprite == (Object)(object)spriteCandidate.Sprite)) { if (num >= 10) { list2.Add($"+{dictionary.Count - 1 - num} more"); break; } list2.Add($"{value3.Label}/{value3.ObjectName}='{((Object)value3.Sprite).name}'(score {value3.Score})"); num++; } } Plugin.Log.LogInfo((object)("[Skaldsong] Other candidate parchment/panel sprites found: " + string.Join(", ", list2))); } _cachedPanelSprite = spriteCandidate.Sprite; return spriteCandidate.Sprite; } private static void CollectCandidates(string label, Transform root, List<SpriteCandidate> candidates) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } Image[] componentsInChildren = ((Component)root).GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { Sprite sprite = val.sprite; if ((Object)(object)sprite == (Object)null || sprite.border == Vector4.zero) { continue; } string text = ((((Object)sprite).name != null) ? ((Object)sprite).name.ToLowerInvariant() : string.Empty); if (!(text == "uisprite") && !(text == "background") && !text.Contains("mask")) { Rect rect = sprite.rect; if (!(((Rect)(ref rect)).width < 24f) && !(((Rect)(ref rect)).height < 24f)) { candidates.Add(new SpriteCandidate { Label = label, ObjectName = ((Object)((Component)val).gameObject).name, Sprite = sprite, Score = ScoreSpriteName(text) }); } } } } private static int ScoreSpriteName(string nameLower) { if (nameLower.Contains("woodpanel")) { if (!nameLower.Contains("container") && !nameLower.Contains("info") && !nameLower.Contains("trophys") && !nameLower.Contains("trophy")) { return 5; } return 6; } if (nameLower.Contains("crafting_panel_bkg")) { return 6; } if (nameLower.Contains("parchment") || nameLower.Contains("vellum")) { return 3; } if (nameLower.Contains("paper") || nameLower.Contains("panel") || nameLower.Contains("window") || nameLower.Contains("frame")) { return 2; } if (nameLower.Contains("bkg") || nameLower.Contains("bg") || nameLower.Contains("border")) { return 1; } return 0; } private float GetCanvasHeight(Hud hud) { //IL_002b: 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_0040: 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) Canvas componentInParent = hud.m_rootObject.GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent != (Object)null) { Transform transform = ((Component)componentInParent).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val != (Object)null) { Rect rect = val.rect; if (((Rect)(ref rect)).height > 0f) { rect = val.rect; return ((Rect)(ref rect)).height; } } } return Screen.height; } private IEnumerator Animate(float targetY, float holdDuration, int level, float barFillDuration, float barFillStartDelay) { float startY = targetY - 40f; float t = 0f; while (t < 0.25f) { if ((Object)(object)_root == (Object)null) { yield break; } t += Time.unscaledDeltaTime; float num = Mathf.Clamp01(t / 0.25f); float num2 = 1f - Mathf.Pow(1f - num, 3f); _root.anchoredPosition = new Vector2(0f, Mathf.Lerp(startY, targetY, num2)); _canvasGroup.alpha = num2; yield return null; } if ((Object)(object)_root == (Object)null) { yield break; } _root.anchoredPosition = new Vector2(0f, targetY); _canvasGroup.alpha = 1f; float d = 0f; while (d < barFillStartDelay) { if ((Object)(object)_root == (Object)null) { yield break; } d += Time.unscaledDeltaTime; yield return null; } t = 0f; while (t < barFillDuration) { if ((Object)(object)_root == (Object)null) { yield break; } t += Time.unscaledDeltaTime; float num3 = Mathf.Clamp01(t / barFillDuration); _barFill.fillAmount = 1f - Mathf.Pow(1f - num3, 3f); yield return null; } _barFill.fillAmount = 1f; ((TMP_Text)_levelText).text = level.ToString(); RectTransform levelRect = ((TMP_Text)_levelText).rectTransform; t = 0f; while (t < 0.2f) { if ((Object)(object)_root == (Object)null) { yield break; } t += Time.unscaledDeltaTime; float num4 = Mathf.Clamp01(t / 0.2f); float num5 = 1f + 0.3f * Mathf.Sin(num4 * (float)Math.PI); ((Transform)levelRect).localScale = new Vector3(num5, num5, 1f); yield return null; } ((Transform)levelRect).localScale = Vector3.one; float h = 0f; while (h < holdDuration) { if ((Object)(object)_root == (Object)null) { yield break; } h += Time.unscaledDeltaTime; yield return null; } t = 0f; while (t < 0.5f) { if ((Object)(object)_root == (Object)null) { yield break; } t += Time.unscaledDeltaTime; _canvasGroup.alpha = 1f - Mathf.Clamp01(t / 0.5f); yield return null; } if ((Object)(object)_root != (Object)null) { _canvasGroup.alpha = 0f; ((Component)_root).gameObject.SetActive(false); } _animCoroutine = null; TryPlayNext(); } } }