using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MycopunkShared;
using Pigeon.UI;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MycopunkAbilityCooldown")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+fe8cef1291afd0a7f7ea8a9ddfd28d3607c4cdd5")]
[assembly: AssemblyProduct("MycopunkAbilityCooldown")]
[assembly: AssemblyTitle("MycopunkAbilityCooldown")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.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 MycopunkAbilityCooldown
{
internal sealed class CooldownLabel : MonoBehaviour
{
private sealed class Tag
{
public GameObject Root;
public TextMeshProUGUI Text;
public string Shown = "";
public void Show(string text)
{
if ((object)text != Shown && !(text == Shown))
{
Shown = text;
((TMP_Text)Text).text = text;
bool flag = text.Length > 0;
if (Root.activeSelf != flag)
{
Root.SetActive(flag);
}
}
}
}
[HarmonyPatch(typeof(AbilityRechargeUI), "Setup")]
internal static class SetupPatch
{
[HarmonyPostfix]
private static void Postfix(AbilityRechargeUI __instance)
{
Attach(__instance);
}
}
private const string Prefix = "MycoCooldown";
private AbilityRechargeUI _ui;
private bool _built;
private Graphic _shade;
private TextMeshProUGUI _big;
private Tag _timer;
private Tag _count;
private readonly RechargeEstimate _estimate = new RechargeEstimate();
private readonly SecondsText _seconds = new SecondsText();
private CooldownMode _mode;
private string _shownSeconds = "";
private int _shownCount = -1;
public static void AttachExisting()
{
AbilityRechargeUI[] array = Object.FindObjectsByType<AbilityRechargeUI>((FindObjectsInactive)1);
for (int i = 0; i < array.Length; i++)
{
Attach(array[i]);
}
}
private void OnDestroy()
{
if ((Object)(object)_shade != (Object)null)
{
Object.Destroy((Object)(object)((Component)_shade).gameObject);
}
if ((Object)(object)_big != (Object)null)
{
Object.Destroy((Object)(object)((Component)_big).gameObject);
}
if ((Object)(object)_timer?.Root != (Object)null && (Object)(object)_timer.Root.transform.parent != (Object)null)
{
Object.Destroy((Object)(object)((Component)_timer.Root.transform.parent).gameObject);
}
}
private static void Attach(AbilityRechargeUI ui)
{
try
{
CooldownLabel cooldownLabel = ((Component)ui).GetComponent<CooldownLabel>();
if ((Object)(object)cooldownLabel == (Object)null)
{
cooldownLabel = ((Component)ui).gameObject.AddComponent<CooldownLabel>();
}
cooldownLabel._ui = ui;
cooldownLabel._estimate.Reset();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Cooldown label could not be added: " + ex));
}
}
private void LateUpdate()
{
if ((Object)(object)_ui == (Object)null)
{
return;
}
try
{
IActivatedAbility ability = _ui.ability;
if (ability == null || !Plugin.Enabled.Value)
{
if (_built)
{
Apply(CooldownView.Of(0f, 1, float.NaN), "", hideCount: true);
}
return;
}
float charge = ability.Charge;
int maxCharges = ability.MaxCharges;
float seconds = _estimate.Update(Time.time, charge, maxCharges);
CooldownView view = CooldownView.Of(charge, maxCharges, seconds);
if ((_built || (view.Mode == CooldownMode.None && !view.ShowCount) || Build()) && _built)
{
Apply(view, _seconds.Get(seconds), hideCount: false);
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Cooldown label failed and is turned off: " + ex));
((Behaviour)this).enabled = false;
}
}
private void Apply(CooldownView view, string seconds, bool hideCount)
{
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: 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)
if (view.Mode != _mode || (object)seconds != _shownSeconds)
{
_mode = view.Mode;
_shownSeconds = seconds;
bool flag = view.Mode == CooldownMode.Empty;
((Behaviour)_shade).enabled = flag;
((TMP_Text)_big).text = (flag ? seconds : "");
_timer.Show((view.Mode == CooldownMode.Recharging) ? seconds : "");
}
int num = ((hideCount || !view.ShowCount) ? (-1) : view.Count);
if (num != _shownCount)
{
_shownCount = num;
_count.Show((num < 0) ? "" : num.ToString());
}
Color val = default(Color);
((Color)(ref val))..ctor(0f, 0f, 0f, Mathf.Clamp01(Plugin.ShadeAlpha.Value));
if (_shade.color != val)
{
_shade.color = val;
}
float value = Plugin.FontSize.Value;
if (((TMP_Text)_big).fontSize != value)
{
((TMP_Text)_big).fontSize = value;
}
float value2 = Plugin.SmallFontSize.Value;
if (((TMP_Text)_timer.Text).fontSize != value2)
{
((TMP_Text)_timer.Text).fontSize = value2;
((TMP_Text)_count.Text).fontSize = value2;
}
}
private bool Build()
{
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_018b: Unknown result type (might be due to invalid IL or missing references)
Image icon = _ui.icon;
TextMeshProUGUI keybindText = _ui.keybindText;
if ((Object)(object)icon == (Object)null || (Object)(object)keybindText == (Object)null || (Object)(object)((TMP_Text)keybindText).font == (Object)null)
{
((Behaviour)this).enabled = false;
Plugin.Log.LogWarning((object)"AbilityRechargeUI has no icon or keybind text; no cooldown number for it.");
return false;
}
Graphic chargedBackground = _ui.chargedBackground;
BevelRect val = (((Object)(object)chargedBackground != (Object)null && (Object)(object)((Component)chargedBackground).transform.parent != (Object)null) ? ((Component)((Component)chargedBackground).transform.parent).GetComponent<BevelRect>() : null);
RectTransform shape = (((Object)(object)val != (Object)null) ? ((Graphic)val).rectTransform : ((Graphic)icon).rectTransform);
Transform parent = ((Component)icon).transform.parent;
int num = ((Component)icon).transform.GetSiblingIndex() + 1;
GameObject val2 = Sibling(parent, "MycoCooldownShade", shape, num);
_shade = (Graphic)(((Object)(object)val != (Object)null) ? ((object)Bevel(val2, val)) : ((object)val2.AddComponent<Image>()));
_shade.raycastTarget = false;
((Behaviour)_shade).enabled = false;
_big = Text(Sibling(parent, "MycoCooldown", shape, num + 1), keybindText, Plugin.FontSize.Value, (TextAlignmentOptions)514);
GameObject val3 = Sibling(parent, "MycoCooldownTags", shape, num + 2);
_timer = NewTag(val3.transform, "Timer", new Vector2(1f, 0f), val, keybindText);
_count = NewTag(val3.transform, "Count", new Vector2(1f, 1f), val, keybindText);
_mode = CooldownMode.None;
_shownSeconds = "";
_shownCount = -1;
_built = true;
return true;
}
private static Tag NewTag(Transform parent, string name, Vector2 corner, BevelRect bkg, TextMeshProUGUI font)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_004c: 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_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: 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_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: 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_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Expected O, but got Unknown
//IL_0140: 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_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: 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_019a: Expected O, but got Unknown
GameObject val = new GameObject("MycoCooldown" + name, new Type[1] { typeof(RectTransform) });
val.layer = ((Component)parent).gameObject.layer;
RectTransform val2 = (RectTransform)val.transform;
((Transform)val2).SetParent(parent, false);
Vector2 val3 = (val2.pivot = corner);
Vector2 anchorMin = (val2.anchorMax = val3);
val2.anchorMin = anchorMin;
val2.anchoredPosition = new Vector2((corner.x > 0.5f) ? (-2f) : 2f, (corner.y > 0.5f) ? (-2f) : 2f);
((Transform)val2).localScale = Vector3.one;
Graphic val6;
if ((Object)(object)bkg != (Object)null)
{
BevelRect obj = val.AddComponent<BevelRect>();
obj.SetCorners(3f);
val6 = (Graphic)(object)obj;
}
else
{
val6 = (Graphic)(object)val.AddComponent<Image>();
}
val6.color = new Color(0f, 0f, 0f, 0.8f);
val6.raycastTarget = false;
HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
((LayoutGroup)obj2).padding = new RectOffset(4, 4, 1, 1);
((LayoutGroup)obj2).childAlignment = (TextAnchor)4;
bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true);
((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = childControlWidth;
childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false);
((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = childControlWidth;
ContentSizeFitter obj3 = val.AddComponent<ContentSizeFitter>();
FitMode horizontalFit = (FitMode)2;
obj3.verticalFit = (FitMode)2;
obj3.horizontalFit = horizontalFit;
GameObject val7 = new GameObject("Text", new Type[1] { typeof(RectTransform) })
{
layer = val.layer
};
val7.transform.SetParent((Transform)(object)val2, false);
TextMeshProUGUI text = Text(val7, font, Plugin.SmallFontSize.Value, (TextAlignmentOptions)514);
val.SetActive(false);
return new Tag
{
Root = val,
Text = text
};
}
private static BevelRect Bevel(GameObject go, BevelRect like)
{
BevelRect obj = go.AddComponent<BevelRect>();
obj.TopLeft = like.TopLeft;
obj.TopRight = like.TopRight;
obj.BottomLeft = like.BottomLeft;
obj.BottomRight = like.BottomRight;
return obj;
}
private static TextMeshProUGUI Text(GameObject go, TextMeshProUGUI font, float size, TextAlignmentOptions align)
{
//IL_0026: 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)
TextMeshProUGUI obj = go.AddComponent<TextMeshProUGUI>();
((TMP_Text)obj).font = ((TMP_Text)font).font;
((TMP_Text)obj).fontSharedMaterial = ((TMP_Text)font).fontSharedMaterial;
((TMP_Text)obj).fontSize = size;
((Graphic)obj).color = Color.white;
((TMP_Text)obj).alignment = align;
((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0;
((TMP_Text)obj).overflowMode = (TextOverflowModes)0;
((Graphic)obj).raycastTarget = false;
((TMP_Text)obj).text = "";
return obj;
}
private static GameObject Sibling(Transform parent, string name, RectTransform shape, int index)
{
//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_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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_0050: 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_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: 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)
//IL_006a: 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_0076: 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_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) })
{
layer = ((Component)shape).gameObject.layer
};
RectTransform val2 = (RectTransform)val.transform;
((Transform)val2).SetParent(parent, false);
((Transform)val2).SetSiblingIndex(index);
val2.anchorMin = shape.anchorMin;
val2.anchorMax = shape.anchorMax;
val2.pivot = shape.pivot;
val2.sizeDelta = shape.sizeDelta;
val2.anchoredPosition = shape.anchoredPosition;
((Transform)val2).localRotation = Quaternion.identity;
((Transform)val2).localScale = Vector3.one;
return val;
}
}
internal enum CooldownMode
{
None,
Empty,
Recharging
}
internal readonly struct CooldownView
{
public readonly CooldownMode Mode;
public readonly int Count;
public readonly bool ShowCount;
private CooldownView(CooldownMode mode, int count, bool showCount)
{
Mode = mode;
Count = count;
ShowCount = showCount;
}
public static CooldownView Of(float charge, int maxCharges, float seconds)
{
int num = ((!(charge <= 0f)) ? ((int)Math.Floor(charge)) : 0);
if (num > maxCharges)
{
num = maxCharges;
}
bool showCount = maxCharges > 1;
if (float.IsNaN(seconds) || num >= maxCharges)
{
return new CooldownView(CooldownMode.None, num, showCount);
}
return new CooldownView((num == 0) ? CooldownMode.Empty : CooldownMode.Recharging, num, showCount);
}
}
internal static class MenuText
{
private static readonly Dictionary<string, Dictionary<string, string>> Names = new Dictionary<string, Dictionary<string, string>>
{
["en"] = new Dictionary<string, string> { ["ability.cooldown"] = "Cooldown seconds on ability icons" },
["ja"] = new Dictionary<string, string> { ["ability.cooldown"] = "アビリティの再使用時間を表示" }
};
private static readonly Dictionary<string, Dictionary<string, string>> Descriptions = new Dictionary<string, Dictionary<string, string>> { ["ja"] = new Dictionary<string, string> { ["ability.cooldown"] = "各アビリティのアイコンに次の使用までの秒数を表示します。この変更は即時に反映されます。" } };
public static object[] Label(string key)
{
return ModsMenuTag.Label(key, (IDictionary<string, Dictionary<string, string>>)Names, (IDictionary<string, Dictionary<string, string>>)Descriptions);
}
}
[BepInPlugin("t4t5u0.mycopunk.abilitycooldown", "Mycopunk Ability Cooldown", "0.2.2")]
[BepInDependency("doku_macaron.mycopunk.macaroncore", "1.1.0")]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "t4t5u0.mycopunk.abilitycooldown";
public const string Name = "Mycopunk Ability Cooldown";
public const string Version = "0.2.2";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<float> FontSize;
internal static ConfigEntry<float> ShadeAlpha;
internal static ConfigEntry<float> SmallFontSize;
private Harmony _harmony;
private void Awake()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, new ConfigDescription("Show the seconds until the next charge over each ability icon (grenade, movement ability...). Takes effect at once.", (AcceptableValueBase)null, MenuText.Label("ability.cooldown")));
FontSize = ((BaseUnityPlugin)this).Config.Bind<float>("General", "FontSize", 22f, "Font size of the seconds, in HUD units.");
ShadeAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ShadeAlpha", 0.8f, "How dark the shade over the icon is while it recharges (0 = none, 1 = black), so the number stays readable.");
SmallFontSize = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SmallFontSize", 13f, "Font size of the corner tags (the charge count, and the seconds while charges are left), in HUD units.");
_harmony = new Harmony("t4t5u0.mycopunk.abilitycooldown");
ModSetup.Try(Log, "cooldown labels", (Action)delegate
{
_harmony.CreateClassProcessor(typeof(CooldownLabel.SetupPatch)).Patch();
CooldownLabel.AttachExisting();
});
ModSetup.Try(Log, "MODS tab", (Action)delegate
{
ModsMenu.Install(_harmony, (BaseUnityPlugin)(object)this);
});
ModSetup.Try(Log, "hotkey report", (Action)delegate
{
Hotkeys.ReportConflicts((BaseUnityPlugin)(object)this);
});
Log.LogInfo((object)("Mycopunk Ability Cooldown 0.2.2 loaded (enabled=" + Enabled.Value + ")."));
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
internal sealed class RechargeEstimate
{
public const float Window = 0.5f;
private bool _started;
private float _t0 = float.NaN;
private float _c0;
private float _lastT;
private float _lastC;
private float _prevT;
private float _rate;
public float Update(float time, float charge, int maxCharges)
{
if (maxCharges <= 0 || charge >= (float)maxCharges)
{
Reset();
return float.NaN;
}
if (!_started || charge < _lastC)
{
Reset();
_started = true;
_lastT = (_prevT = time);
_lastC = charge;
return float.NaN;
}
if (charge > _lastC)
{
if (float.IsNaN(_t0))
{
_t0 = _prevT;
_c0 = _lastC;
}
_lastT = time;
_lastC = charge;
}
_prevT = time;
if (time - _lastT > 0.5f)
{
_t0 = float.NaN;
_rate = 0f;
return float.NaN;
}
if (!float.IsNaN(_t0))
{
float num = _lastT - _t0;
if (num >= 0.25f)
{
_rate = (_lastC - _c0) / num;
if (num > 0.5f)
{
_t0 = _lastT;
_c0 = _lastC;
}
}
}
if (_rate <= 0f)
{
return float.NaN;
}
return ((float)Math.Floor(charge) + 1f - charge) / _rate;
}
public void Reset()
{
_started = false;
_t0 = float.NaN;
_c0 = (_lastC = (_lastT = (_prevT = 0f)));
_rate = 0f;
}
}
internal sealed class SecondsText
{
private int _tenths = int.MinValue;
private string _text = "";
public string Get(float seconds)
{
int num = ((float.IsNaN(seconds) || seconds < 0f) ? (-1) : ((seconds >= 10f) ? ((int)Math.Ceiling(seconds) * 10) : ((int)Math.Ceiling(seconds * 10f))));
if (num != _tenths)
{
_tenths = num;
_text = ((num < 0) ? "" : ((num >= 100) ? (num / 10).ToString() : (num / 10 + "." + num % 10)));
}
return _text;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}