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 ValheimBubble v1.1.1
ValheimBubble.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [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("ValheimBubble")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1+7370c90c7ac5d69be715e71aca3187b4136c95fe")] [assembly: AssemblyProduct("Valheim Bubble")] [assembly: AssemblyTitle("ValheimBubble")] [assembly: AssemblyVersion("1.1.1.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 ValheimBubble { internal class BubbleCycle : MonoBehaviour { private class HandSnapshot { public ItemData Right; public ItemData Left; public bool Hidden; } private static readonly FieldRef<Humanoid, ItemData> RightItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_rightItem"); private static readonly FieldRef<Humanoid, ItemData> LeftItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_leftItem"); private static readonly FieldRef<Humanoid, ItemData> HiddenRightItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenRightItem"); private static readonly FieldRef<Humanoid, ItemData> HiddenLeftItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenLeftItem"); private const float RestoreTimeout = 30f; private bool _running; private void Update() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!_running && IsShortcutDown(ValheimBubblePlugin.Keybind.Value)) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && CanTakeInput(localPlayer)) { ((MonoBehaviour)this).StartCoroutine(Run(localPlayer)); } } } private static bool IsShortcutDown(KeyboardShortcut shortcut) { //IL_0002: 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) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((KeyCode key) => ZInput.GetKey(key, false)); } return false; } private static bool CanTakeInput(Player player) { if ((Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()) || Console.IsVisible() || TextInput.IsVisible() || StoreGui.IsVisible() || InventoryGui.IsVisible() || Menu.IsVisible() || Minimap.IsOpen()) { return false; } if (!((Character)player).IsDead() && !((Character)player).InCutscene()) { return !((Character)player).IsTeleporting(); } return false; } private IEnumerator Run(Player player) { _running = true; try { ItemData staff = FindStaff(player); if (staff == null) { yield break; } HandSnapshot snapshot = Snapshot(player); if (RightItem.Invoke((Humanoid)(object)player) != staff) { ((Humanoid)player).EquipItem(staff, true); } float timeout = ValheimBubblePlugin.CastTimeout.Value; float deadline = Time.time + timeout; bool started = false; while (!started && Time.time < deadline && Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead()) { yield return null; if (RightItem.Invoke((Humanoid)(object)player) == staff) { started = ((Character)player).StartAttack((Character)null, false); } } if (started) { deadline = Time.time + timeout; while (Object.op_Implicit((Object)(object)player) && !((Character)player).InAttack() && Time.time < deadline) { yield return null; } while (Object.op_Implicit((Object)(object)player) && ((Character)player).InAttack() && Time.time < deadline) { yield return null; } yield return null; } else if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead()) { Fail(player, "Could not cast the protection staff"); } deadline = Time.time + 30f; while (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !Restore(player, snapshot)) { if (Time.time >= deadline) { Fail(player, "Could not re-equip your previous weapon"); break; } yield return null; } } finally { _running = false; } } internal static ItemData BestStaff(Player player) { string prefab = ValheimBubblePlugin.StaffPrefab.Value; return (from item in ((Humanoid)player).GetInventory().GetAllItems() where (Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == prefab && (!item.m_shared.m_useDurability || item.m_durability > 0f) orderby item.m_quality descending, item.m_durability descending select item).FirstOrDefault(); } private static ItemData FindStaff(Player player) { if (((Character)player).InAttack() || ((Character)player).InDodge() || ((Character)player).InMinorAction() || ((Character)player).IsAttached() || (((Character)player).IsSwimming() && !((Character)player).IsOnGround())) { return null; } ItemData val = BestStaff(player); if (val == null) { Fail(player, "Missing " + ValheimBubblePlugin.StaffPrefab.Value + " in inventory"); return null; } float attackEitr = val.m_shared.m_attack.GetAttackEitr((Character)(object)player, val); if (attackEitr <= 0f) { return val; } if (((Character)player).GetMaxEitr() <= 0f) { ((Character)player).Message((MessageType)2, "$hud_eitrrequired", 0, (Sprite)null, false); return null; } if (!((Character)player).HaveEitr(attackEitr + 0.1f)) { Hud.instance.EitrBarEmptyFlash(); ValheimBubblePlugin.Log.LogInfo((object)$"Not enough Eitr to cast ({player.GetEitr():0}/{attackEitr:0})."); return null; } return val; } private static HandSnapshot Snapshot(Player player) { return new HandSnapshot { Right = (RightItem.Invoke((Humanoid)(object)player) ?? HiddenRightItem.Invoke((Humanoid)(object)player)), Left = (LeftItem.Invoke((Humanoid)(object)player) ?? HiddenLeftItem.Invoke((Humanoid)(object)player)), Hidden = (RightItem.Invoke((Humanoid)(object)player) == null && LeftItem.Invoke((Humanoid)(object)player) == null && (HiddenRightItem.Invoke((Humanoid)(object)player) != null || HiddenLeftItem.Invoke((Humanoid)(object)player) != null)) }; } private static bool Restore(Player player, HandSnapshot snapshot) { if (((Character)player).InAttack() || ((Character)player).InDodge() || (((Character)player).IsSwimming() && !((Character)player).IsOnGround())) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); ItemData val = Expected(inventory, snapshot.Right); ItemData val2 = Expected(inventory, snapshot.Left); if (!snapshot.Hidden || RightItem.Invoke((Humanoid)(object)player) != null || LeftItem.Invoke((Humanoid)(object)player) != null) { ItemData val3 = RightItem.Invoke((Humanoid)(object)player); if (val != null) { ((Humanoid)player).EquipItem(val, true); } if (val2 != null) { ((Humanoid)player).EquipItem(val2, true); } if (val3 != null && val3 != val && RightItem.Invoke((Humanoid)(object)player) == val3) { ((Humanoid)player).UnequipItem(val3, true); } if (snapshot.Hidden) { ((Humanoid)player).HideHandItems(false, false); } } if (!snapshot.Hidden) { if (RightItem.Invoke((Humanoid)(object)player) == val) { return LeftItem.Invoke((Humanoid)(object)player) == val2; } return false; } if (RightItem.Invoke((Humanoid)(object)player) == null && LeftItem.Invoke((Humanoid)(object)player) == null && HiddenRightItem.Invoke((Humanoid)(object)player) == val) { return HiddenLeftItem.Invoke((Humanoid)(object)player) == val2; } return false; } private static ItemData Expected(Inventory inventory, ItemData item) { if (item == null || !inventory.ContainsItem(item)) { return null; } return item; } private static void Fail(Player player, string reason) { ((Character)player).Message((MessageType)2, reason, 0, (Sprite)null, false); ValheimBubblePlugin.Log.LogInfo((object)reason); } } internal static class Chime { private const int SampleRate = 44100; private const float ToneSeconds = 0.35f; public static AudioClip Build(string name, params float[] tones) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown int num = 15435; float[] data = new float[num * tones.Length]; for (int i = 0; i < tones.Length; i++) { for (int j = 0; j < num; j++) { float num2 = (float)j / 44100f; float num3 = Mathf.Min(1f, (float)j / 220f) * Mathf.Exp((0f - num2) * 7f); float num4 = Mathf.Sin((float)Math.PI * 2f * tones[i] * num2) + 0.3f * Mathf.Sin((float)Math.PI * 4f * tones[i] * num2); data[i * num + j] = 0.5f * num3 * num4; } } int position = 0; return AudioClip.Create(name, data.Length, 1, 44100, false, (PCMReaderCallback)delegate(float[] buffer) { for (int k = 0; k < buffer.Length; k++) { buffer[k] = ((position < data.Length) ? data[position++] : 0f); } }); } public static AudioSource AddSource(GameObject host) { AudioSource obj = host.AddComponent<AudioSource>(); obj.playOnAwake = false; obj.spatialBlend = 0f; return obj; } } internal class FoodWarning : MonoBehaviour { private AudioSource _audio; private AudioClip _chime; private readonly Dictionary<Food, bool> _armed = new Dictionary<Food, bool>(); private void Awake() { _audio = Chime.AddSource(((Component)this).gameObject); _chime = Chime.Build("ValheimBubbleFood", 523f, 784f); } private void Update() { Player localPlayer = Player.m_localPlayer; if (!ValheimBubblePlugin.FoodEnabled.Value || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { _armed.Clear(); return; } List<Food> foods = localPlayer.GetFoods(); foreach (Food item in _armed.Keys.Where((Food food) => !foods.Contains(food)).ToList()) { _armed.Remove(item); } float num = (float)ValheimBubblePlugin.FoodWarnPercent.Value / 100f; foreach (Food item2 in foods) { SharedData shared = item2.m_item.m_shared; if (!(shared.m_food <= 0f) || !(shared.m_foodStamina <= 0f)) { bool flag = Strength(item2) > num; if (!_armed.TryGetValue(item2, out var value) || flag) { _armed[item2] = flag; } else if (value) { _armed[item2] = false; Warn(localPlayer, item2); } } } } private static float Strength(Food food) { float foodBurnTime = food.m_item.m_shared.m_foodBurnTime; if (!(foodBurnTime > 0f)) { return 1f; } return Mathf.Pow(Mathf.Clamp01(food.m_time / foodBurnTime), 0.3f); } private void Warn(Player player, Food food) { SharedData shared = food.m_item.m_shared; string text = ((shared.m_food > 0f && shared.m_foodStamina > 0f) ? "Health & Stamina" : ((shared.m_food > 0f) ? "Health" : "Stamina")); ((Character)player).Message((MessageType)2, "Low " + text + " - eat!\n" + shared.m_name + " is wearing off", 0, (Sprite)null, false); _audio.PlayOneShot(_chime, ValheimBubblePlugin.FoodVolume.Value); } } internal class LowEitrWarning : MonoBehaviour { private const string Message = "Low Eitr - eat!"; private AudioSource _audio; private AudioClip _chime; private bool _armed; private void Awake() { _audio = Chime.AddSource(((Component)this).gameObject); _chime = Chime.Build("ValheimBubbleLowEitr", 988f, 740f); } private void Update() { Player localPlayer = Player.m_localPlayer; if (!ValheimBubblePlugin.LowEitrEnabled.Value || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { _armed = false; return; } ItemData val = BubbleCycle.BestStaff(localPlayer); if (val == null) { return; } float attackEitr = val.m_shared.m_attack.GetAttackEitr((Character)(object)localPlayer, val); if (!(attackEitr <= 0f)) { float num = attackEitr * (float)ValheimBubblePlugin.LowEitrCasts.Value; if (((Character)localPlayer).GetMaxEitr() >= num) { _armed = true; } else if (_armed) { _armed = false; ((Character)localPlayer).Message((MessageType)2, "Low Eitr - eat!", 0, (Sprite)null, false); _audio.PlayOneShot(_chime, ValheimBubblePlugin.LowEitrVolume.Value); } } } } public enum ExpiryCue { None, Flash, Sound, Both } [BepInPlugin("com.syloreon.valheimbubble", "Valheim Bubble", "1.1.1")] public class ValheimBubblePlugin : BaseUnityPlugin { public const string PluginGuid = "com.syloreon.valheimbubble"; public const string PluginName = "Valheim Bubble"; public const string PluginVersion = "1.1.1"; internal static ManualLogSource Log; internal static ConfigEntry<KeyboardShortcut> Keybind; internal static ConfigEntry<string> StaffPrefab; internal static ConfigEntry<float> CastTimeout; internal static ConfigEntry<bool> TimerEnabled; internal static ConfigEntry<float> TimerOffsetX; internal static ConfigEntry<float> TimerOffsetY; internal static ConfigEntry<int> TimerFontSize; internal static ConfigEntry<ExpiryCue> Cue; internal static ConfigEntry<float> CueVolume; internal static ConfigEntry<float> WarningSeconds; internal static ConfigEntry<bool> LowEitrEnabled; internal static ConfigEntry<int> LowEitrCasts; internal static ConfigEntry<float> LowEitrVolume; internal static ConfigEntry<bool> FoodEnabled; internal static ConfigEntry<int> FoodWarnPercent; internal static ConfigEntry<float> FoodVolume; private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Expected O, but got Unknown //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Expected O, but got Unknown //IL_030c: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Keybind = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Keybind", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Key that swaps to the protection staff, casts the bubble and swaps back to your weapon. A key, optionally with modifiers held first, e.g. F6, F12, or A + LeftControl."); StaffPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("Gear", "StaffPrefab", "StaffShield", "Prefab name of the staff to cast with (vanilla Staff of Protection = StaffShield)."); CastTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("Gear", "CastTimeoutSeconds", 6f, "Give up and restore gear if the cast has not finished after this many seconds."); TimerEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Timer", "Enabled", true, "Show a countdown while a protection bubble is active."); TimerOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Timer", "OffsetX", 0f, "Horizontal offset in pixels from the status-effect bar."); TimerOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Timer", "OffsetY", 70f, "Vertical offset in pixels below the status-effect bar."); TimerFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Timer", "FontSize", 20, "Font size of the countdown."); Cue = ((BaseUnityPlugin)this).Config.Bind<ExpiryCue>("Timer", "ExpiryCue", ExpiryCue.Both, "Flash: \"Bubble down!\" when the bubble expires or breaks. Sound: a chime WarningSeconds before the bubble expires."); CueVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Timer", "CueVolume", 0.4f, new ConfigDescription("Volume of the warning chime.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); WarningSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timer", "WarningSeconds", 5f, new ConfigDescription("Seconds before the bubble expires that the chime plays.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>())); LowEitrEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("LowEitr", "Enabled", true, "Chime and show \"Low Eitr - eat!\" when your Eitr food has worn down too far to keep casting bubbles."); LowEitrCasts = ((BaseUnityPlugin)this).Config.Bind<int>("LowEitr", "CastsLeft", 2, new ConfigDescription("Warn when your maximum Eitr can no longer hold this many bubble casts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); LowEitrVolume = ((BaseUnityPlugin)this).Config.Bind<float>("LowEitr", "Volume", 0.4f, new ConfigDescription("Volume of the Low Eitr chime.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); FoodEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Food", "Enabled", true, "Chime and show \"Low Health - eat!\" or \"Low Stamina - eat!\" when a health or stamina food wears off."); FoodWarnPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Food", "WarnAtPercent", 50, new ConfigDescription("Warn when a food's health/stamina has faded to this percent of its full value.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 95), Array.Empty<object>())); FoodVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Food", "Volume", 0.4f, new ConfigDescription("Volume of the food chime.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ((Component)this).gameObject.AddComponent<BubbleCycle>(); ((Component)this).gameObject.AddComponent<ShieldTimerHud>(); ((Component)this).gameObject.AddComponent<LowEitrWarning>(); ((Component)this).gameObject.AddComponent<FoodWarning>(); Log.LogInfo((object)string.Format("{0} v{1} loaded. Keybind: {2}", "Valheim Bubble", "1.1.1", Keybind.Value)); Keybind.SettingChanged += delegate { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Log.LogInfo((object)$"Keybind changed to {Keybind.Value}"); }; } } internal class ShieldTimerHud : MonoBehaviour { private const float FlashSeconds = 3f; private StatusEffect _shield; private float _remaining; private bool _warned; private AudioClip _cueClip; private float _flashUntil; private AudioSource _audio; private GUIStyle _style; private void Awake() { _audio = ((Component)this).gameObject.AddComponent<AudioSource>(); _audio.playOnAwake = false; _audio.spatialBlend = 0f; } private void Update() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { _shield = null; return; } StatusEffect val = ((IEnumerable<StatusEffect>)((Character)localPlayer).GetSEMan().GetStatusEffects()).FirstOrDefault((Func<StatusEffect, bool>)((StatusEffect se) => se is SE_Shield)); if ((Object)(object)val != (Object)null) { if ((Object)(object)val != (Object)(object)_shield) { _cueClip = FindClip((SE_Shield)val); } _shield = val; _remaining = val.GetRemaningTime(); UpdateWarning(); } else if ((Object)(object)_shield != (Object)null) { _shield = null; _warned = false; ExpiryCue value = ValheimBubblePlugin.Cue.Value; if (value == ExpiryCue.Flash || value == ExpiryCue.Both) { _flashUntil = Time.time + 3f; } } } private void UpdateWarning() { if (_remaining > ValheimBubblePlugin.WarningSeconds.Value) { _warned = false; } else if (!_warned) { _warned = true; ExpiryCue value = ValheimBubblePlugin.Cue.Value; if ((value == ExpiryCue.Sound || value == ExpiryCue.Both) && (Object)(object)_cueClip != (Object)null) { _audio.PlayOneShot(_cueClip, ValheimBubblePlugin.CueVolume.Value); } } } private static AudioClip FindClip(SE_Shield shield) { return shield.m_breakEffects.m_effectPrefabs.Where((EffectData effect) => (Object)(object)effect.m_prefab != (Object)null).SelectMany((EffectData effect) => effect.m_prefab.GetComponentsInChildren<ZSFX>(true)).SelectMany((ZSFX sfx) => sfx.m_audioClips) .FirstOrDefault((Func<AudioClip, bool>)((AudioClip clip) => (Object)(object)clip != (Object)null)); } private void OnGUI() { //IL_00ad: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown if (!ValheimBubblePlugin.TimerEnabled.Value || (Object)(object)Hud.instance == (Object)null || Hud.instance.m_userHidden || !Hud.instance.m_rootObject.activeInHierarchy) { return; } string text; Color val = default(Color); if ((Object)(object)_shield != (Object)null) { int num = Mathf.CeilToInt(Mathf.Max(0f, _remaining)); text = $"Bubble {num / 60}:{num % 60:00}"; val = (Color)((_remaining <= Mathf.Max(10f, ValheimBubblePlugin.WarningSeconds.Value)) ? new Color(1f, 0.75f, 0.2f) : Color.white); } else { if (!(Time.time < _flashUntil)) { return; } text = "Bubble down!"; ((Color)(ref val))..ctor(1f, 0.25f, 0.25f, Mathf.PingPong(Time.time * 4f, 1f) * 0.7f + 0.3f); } if (_style == null) { _style = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)2, fontStyle = (FontStyle)1 }; } _style.fontSize = ValheimBubblePlugin.TimerFontSize.Value; Vector2 val2 = StatusBarAnchor(); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(val2.x - 300f + ValheimBubblePlugin.TimerOffsetX.Value, val2.y + ValheimBubblePlugin.TimerOffsetY.Value, 300f, (float)_style.fontSize * 2f); GUI.color = new Color(0f, 0f, 0f, val.a * 0.8f); GUI.Label(new Rect(((Rect)(ref val3)).x + 2f, ((Rect)(ref val3)).y + 2f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, _style); GUI.color = val; GUI.Label(val3, text, _style); GUI.color = Color.white; } private static Vector2 StatusBarAnchor() { //IL_0025: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) RectTransform statusEffectListRoot = Hud.instance.m_statusEffectListRoot; if ((Object)(object)statusEffectListRoot == (Object)null) { return new Vector2((float)Screen.width - 20f, 20f); } Canvas componentInParent = ((Component)statusEffectListRoot).GetComponentInParent<Canvas>(); Vector2 val = RectTransformUtility.WorldToScreenPoint(((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null, ((Transform)statusEffectListRoot).position); return new Vector2(val.x, (float)Screen.height - val.y); } } }