using System;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using FishNet;
using FishNet.Managing.Timing;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: AssemblyDescription("Shows the exact synchronized time remaining before the active boss leaves.")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyCompany("evansvl")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace HowToFish.BossTimer;
[BepInPlugin("community.howtofish.bosstimer", "Boss Timer", "0.1.4")]
public sealed class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "community.howtofish.bosstimer";
public const string PluginName = "Boss Timer";
public const string PluginVersion = "0.1.4";
private const float LegacyTopOffset = 125f;
private const float DefaultTopOffset = 175f;
private ConfigEntry<bool> _enabled;
private ConfigEntry<bool> _showLabel;
private ConfigEntry<bool> _showTenths;
private ConfigEntry<float> _scale;
private ConfigEntry<float> _opacity;
private ConfigEntry<float> _topOffset;
private GameObject _root;
private RectTransform _panel;
private CanvasGroup _canvasGroup;
private TextMeshProUGUI _text;
private bool _nativeStyleApplied;
private BossUI _nativeBossUi;
private CanvasGroup _nativeCountdownGroup;
private void Awake()
{
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Expected O, but got Unknown
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Expected O, but got Unknown
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Expected O, but got Unknown
_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Enabled", true, "Show the boss departure countdown while a boss is active.");
_showLabel = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "ShowLabel", true, "Show 'BOSS LEAVES IN' before the remaining time.");
_showTenths = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "ShowTenths", true, "Show tenths of a second.");
_scale = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Scale", 1f, new ConfigDescription("HUD scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 1.8f), new object[0]));
_opacity = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Opacity", 1f, new ConfigDescription("HUD opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), new object[0]));
_topOffset = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "TopOffset", 175f, new ConfigDescription("Distance from the top of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 350f), new object[0]));
if (Mathf.Approximately(_topOffset.Value, 125f))
{
_topOffset.Value = 175f;
}
CreateHud();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded. Countdown reads BossManager's synchronized leave tick and never changes gameplay state.");
}
private void Update()
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
if (!_enabled.Value || !IsGameplayHudVisible() || !TryGetRemainingSeconds(out var seconds))
{
SetVisible(visible: false);
return;
}
ApplyNativeStyleWhenAvailable();
ApplyLiveSettings();
((TMP_Text)_text).text = (_showLabel.Value ? "BOSS LEAVES IN " : string.Empty) + FormatRemaining(seconds);
((Graphic)_text).color = CountdownColor(seconds, _opacity.Value);
float nativeCountdownAlpha = GetNativeCountdownAlpha();
_canvasGroup.alpha = ((nativeCountdownAlpha > 0.001f) ? Mathf.MoveTowards(_canvasGroup.alpha, 0f, Time.unscaledDeltaTime * 2f) : 1f);
SetVisible(_canvasGroup.alpha > 0.001f);
}
private static bool IsGameplayHudVisible()
{
if (MainMenuManager.IsInMenu || PauseManager.IsPaused)
{
return false;
}
try
{
return PlayerUI.BossCanvasActive;
}
catch
{
return false;
}
}
private static bool TryGetRemainingSeconds(out double seconds)
{
seconds = 0.0;
if (MainMenuManager.IsInMenu)
{
return false;
}
Creature boss = BossManager.Boss;
if ((Object)(object)boss == (Object)null || boss.IsDead)
{
return false;
}
TimeManager timeManager = InstanceFinder.TimeManager;
if ((Object)(object)timeManager == (Object)null || timeManager.TickRate == 0)
{
return false;
}
uint bossTotalTimeInTicks = BossManager.BossTotalTimeInTicks;
if (bossTotalTimeInTicks == 0)
{
return false;
}
uint num = BossManager.BossLeavesTick - timeManager.Tick;
if (num > bossTotalTimeInTicks)
{
return false;
}
seconds = (double)num / (double)(int)timeManager.TickRate;
return true;
}
private string FormatRemaining(double seconds)
{
if (_showTenths.Value)
{
double num = Math.Ceiling(Math.Max(0.0, seconds) * 10.0) / 10.0;
int num2 = (int)(num / 60.0);
double num3 = num - (double)num2 * 60.0;
return string.Format(CultureInfo.InvariantCulture, "{0:00}:{1:00.0}", num2, num3);
}
int num4 = (int)Math.Ceiling(Math.Max(0.0, seconds));
return string.Format(CultureInfo.InvariantCulture, "{0:00}:{1:00}", num4 / 60, num4 % 60);
}
private void CreateHud()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Expected O, but got Unknown
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Expected O, but got Unknown
//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
_root = new GameObject("BossTimerHUD", new Type[3]
{
typeof(RectTransform),
typeof(Canvas),
typeof(CanvasScaler)
});
Object.DontDestroyOnLoad((Object)(object)_root);
Canvas component = _root.GetComponent<Canvas>();
component.renderMode = (RenderMode)0;
component.sortingOrder = 32761;
CanvasScaler component2 = _root.GetComponent<CanvasScaler>();
component2.uiScaleMode = (ScaleMode)1;
component2.referenceResolution = new Vector2(1920f, 1080f);
component2.screenMatchMode = (ScreenMatchMode)0;
component2.matchWidthOrHeight = 0.5f;
GameObject val = new GameObject("Anchor", new Type[2]
{
typeof(RectTransform),
typeof(CanvasGroup)
});
val.transform.SetParent(_root.transform, false);
_panel = val.GetComponent<RectTransform>();
_canvasGroup = val.GetComponent<CanvasGroup>();
RectTransform panel = _panel;
Vector2 anchorMin = (_panel.anchorMax = new Vector2(0.5f, 1f));
panel.anchorMin = anchorMin;
_panel.pivot = new Vector2(0.5f, 1f);
_panel.sizeDelta = new Vector2(700f, 64f);
GameObject val3 = new GameObject("Countdown", new Type[3]
{
typeof(RectTransform),
typeof(CanvasRenderer),
typeof(TextMeshProUGUI)
});
val3.transform.SetParent((Transform)(object)_panel, false);
_text = val3.GetComponent<TextMeshProUGUI>();
RectTransform rectTransform = ((TMP_Text)_text).rectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.offsetMin = Vector2.zero;
rectTransform.offsetMax = Vector2.zero;
((TMP_Text)_text).fontSize = 31f;
((TMP_Text)_text).alignment = (TextAlignmentOptions)258;
((TMP_Text)_text).enableWordWrapping = false;
((Graphic)_text).raycastTarget = false;
((TMP_Text)_text).overflowMode = (TextOverflowModes)0;
((TMP_Text)_text).outlineColor = new Color32((byte)20, (byte)18, (byte)18, byte.MaxValue);
((TMP_Text)_text).outlineWidth = 0.18f;
_root.SetActive(false);
}
private float GetNativeCountdownAlpha()
{
if ((Object)(object)_nativeBossUi == (Object)null || (Object)(object)_nativeCountdownGroup == (Object)null)
{
FindNativeCountdownGroup();
}
if ((Object)(object)_nativeCountdownGroup == (Object)null || !((Component)_nativeCountdownGroup).gameObject.activeInHierarchy)
{
return 0f;
}
return Mathf.Clamp01(_nativeCountdownGroup.alpha);
}
private void FindNativeCountdownGroup()
{
_nativeBossUi = null;
_nativeCountdownGroup = null;
FieldInfo field = typeof(BossUI).GetField("_countdownGroup", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
{
return;
}
BossUI[] array = Resources.FindObjectsOfTypeAll<BossUI>();
BossUI[] array2 = array;
foreach (BossUI val in array2)
{
if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy)
{
object? value = field.GetValue(val);
CanvasGroup val2 = (CanvasGroup)((value is CanvasGroup) ? value : null);
if (!((Object)(object)val2 == (Object)null))
{
_nativeBossUi = val;
_nativeCountdownGroup = val2;
break;
}
}
}
}
private void ApplyNativeStyleWhenAvailable()
{
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
if (_nativeStyleApplied)
{
return;
}
TextMeshProUGUI val = FindNativeCountdownText();
if ((Object)(object)val == (Object)null)
{
val = FindVersionText();
}
if (!((Object)(object)val == (Object)null) && !((Object)(object)((TMP_Text)val).font == (Object)null))
{
((TMP_Text)_text).font = ((TMP_Text)val).font;
if ((Object)(object)((TMP_Text)val).fontSharedMaterial != (Object)null)
{
((TMP_Text)_text).fontSharedMaterial = ((TMP_Text)val).fontSharedMaterial;
}
((TMP_Text)_text).characterSpacing = ((TMP_Text)val).characterSpacing;
((TMP_Text)_text).outlineColor = new Color32((byte)20, (byte)18, (byte)18, byte.MaxValue);
((TMP_Text)_text).outlineWidth = 0.18f;
_nativeStyleApplied = true;
}
}
private static TextMeshProUGUI FindNativeCountdownText()
{
BossUI[] array = Resources.FindObjectsOfTypeAll<BossUI>();
FieldInfo field = typeof(BossUI).GetField("_timeCountdownText", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
{
return null;
}
BossUI[] array2 = array;
foreach (BossUI val in array2)
{
if (!((Object)(object)val == (Object)null))
{
object? value = field.GetValue(val);
TextMeshProUGUI val2 = (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null);
if ((Object)(object)val2 != (Object)null)
{
return val2;
}
}
}
return null;
}
private static TextMeshProUGUI FindVersionText()
{
TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();
TextMeshProUGUI[] array2 = array;
foreach (TextMeshProUGUI val in array2)
{
if ((Object)(object)val != (Object)null && ((TMP_Text)val).text != null && ((TMP_Text)val).text.IndexOf("Version", StringComparison.OrdinalIgnoreCase) >= 0)
{
return val;
}
}
return null;
}
private void ApplyLiveSettings()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: 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)
((Transform)_panel).localScale = Vector3.one * _scale.Value;
_panel.anchoredPosition = new Vector2(0f, 0f - _topOffset.Value);
}
private static Color CountdownColor(double seconds, float opacity)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: 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)
if (seconds <= 5.0)
{
return new Color(1f, 0.24f, 0.13f, opacity);
}
if (seconds <= 10.0)
{
return new Color(1f, 0.53f, 0.08f, opacity);
}
return new Color(1f, 1f, 1f, opacity);
}
private void SetVisible(bool visible)
{
if ((Object)(object)_root != (Object)null && _root.activeSelf != visible)
{
_root.SetActive(visible);
}
}
private void OnDestroy()
{
if ((Object)(object)_root != (Object)null)
{
Object.Destroy((Object)(object)_root);
}
}
}