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 ShowForgiveMeTimer v1.0.2
ShowForgiveMeTimer.dll
Decompiled 18 hours agousing System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Projectile; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ShowForgiveMeTimer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("ShowForgiveMeTimer")] [assembly: AssemblyTitle("ShowForgiveMeTimer")] [assembly: AssemblyVersion("1.0.2.0")] namespace ShowForgiveMeTimer; [DisallowMultipleComponent] internal sealed class BarsDisplay : MonoBehaviour { private sealed class Column { public GameObject Root; public RectTransform RootRect; public RectTransform Bar; public RectTransform Inner; public RectTransform Fill; public Image FillImage; public RectTransform Label; public TextMeshProUGUI Text; public string LastText; public float LastFontMax; public bool Visible; } private const int Slots = 3; private static readonly Color FrameColor = new Color(0.8f, 0.85f, 0.89f, 0.75f); private static readonly Color BackColor = new Color(0.06f, 0.08f, 0.1f, 0.82f); private static readonly Color CalmColor = new Color(0.36f, 0.87f, 0.75f, 1f); private static readonly Color ShortColor = new Color(1f, 0.75f, 0.3f, 1f); private static readonly Color LastColor = new Color(1f, 0.39f, 0.39f, 1f); private static readonly Color WaitingColor = new Color(0.62f, 0.68f, 0.76f, 1f); private HUD hud; private EquipmentIcon icon; private Canvas canvas; private RectTransform panel; private CanvasGroup group; private Column[] columns; private bool panelVisible; private bool reportedError; private readonly TrackedDoll[] assigned = new TrackedDoll[3]; private readonly Vector3[] corners = (Vector3[])(object)new Vector3[4]; private void Awake() { hud = ((Component)this).GetComponent<HUD>(); } private void LateUpdate() { try { Refresh(); } catch (Exception ex) { if (!reportedError) { reportedError = true; Plugin.Log.LogError((object)("Erro ao desenhar as barras: " + ex)); } } } private void OnDisable() { SetPanelVisible(visible: false); } private void OnDestroy() { DestroyPanel(); } private void Refresh() { Settings settings = Plugin.Settings; if (!Object.op_Implicit((Object)(object)hud) || settings == null || !EnsureBuilt()) { return; } CharacterMaster targetMaster = hud.targetMaster; UpdateAssignments(targetMaster); bool value = settings.Preview.Value; bool flag = false; for (int i = 0; i < 3; i++) { flag |= assigned[i] != null; } if (!((Component)icon).gameObject.activeInHierarchy || !(value || flag)) { SetPanelVisible(visible: false); return; } SetPanelVisible(visible: true); group.alpha = settings.Opacity.Value; Layout(settings); bool value2 = settings.ShowTenths.Value; float sinceFixedStep = Time.time - Time.fixedTime; for (int j = 0; j < 3; j++) { DrawColumn(j, value, value2, sinceFixedStep); } } private void UpdateAssignments(CharacterMaster master) { for (int i = 0; i < 3; i++) { TrackedDoll trackedDoll = assigned[i]; if (trackedDoll != null && (!trackedDoll.Alive || !Object.op_Implicit((Object)(object)master) || (Object)(object)trackedDoll.OwnerMaster != (Object)(object)master)) { assigned[i] = null; } } if (!Object.op_Implicit((Object)(object)master)) { return; } IReadOnlyList<TrackedDoll> all = DollTracker.All; for (int j = 0; j < all.Count; j++) { TrackedDoll trackedDoll2 = all[j]; if (trackedDoll2.Alive && !((Object)(object)trackedDoll2.OwnerMaster != (Object)(object)master) && !IsAssigned(trackedDoll2)) { int num = FirstFreeSlot(); if (num < 0) { break; } assigned[num] = trackedDoll2; } } } private bool IsAssigned(TrackedDoll d) { for (int i = 0; i < 3; i++) { if (assigned[i] == d) { return true; } } return false; } private int FirstFreeSlot() { for (int i = 0; i < 3; i++) { if (assigned[i] == null) { return i; } } return -1; } private void DrawColumn(int i, bool preview, bool tenths, float sinceFixedStep) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) Column column = columns[i]; float remaining; float fullLifetime; bool flag; string text; if (preview) { float num = (Time.unscaledTime + (float)i * 3f) % 9f; remaining = 9f - num; fullLifetime = 9f; flag = false; text = TimerMath.Format(remaining, tenths); } else { TrackedDoll trackedDoll = assigned[i]; if (trackedDoll == null) { SetColumnVisible(column, visible: false); return; } if (!trackedDoll.EverStuck) { remaining = 1f; fullLifetime = 1f; flag = true; text = "..."; } else { remaining = (trackedDoll.Paused ? trackedDoll.Remaining : TimerMath.Smooth(trackedDoll.Remaining, sinceFixedStep, Time.fixedDeltaTime)); fullLifetime = trackedDoll.FullLifetime; flag = trackedDoll.Paused; text = TimerMath.Format(remaining, tenths); } } SetColumnVisible(column, visible: true); float num2 = TimerMath.Fraction(remaining, fullLifetime); column.Fill.anchorMax = new Vector2(1f, num2); Color color = (Color)(flag ? WaitingColor : (TimerMath.Urgency(remaining) switch { 2 => LastColor, 1 => ShortColor, _ => CalmColor, })); ((Graphic)column.FillImage).color = color; if (!string.Equals(column.LastText, text, StringComparison.Ordinal)) { column.LastText = text; ((TMP_Text)column.Text).text = text; } } private void Layout(Settings s) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: 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_018c: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_019e: 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_01b1: 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_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) Camera val = (((int)canvas.renderMode == 0) ? null : canvas.worldCamera); ((RectTransform)((Component)icon).transform).GetWorldCorners(corners); Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, corners[0]); Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, corners[2]); float num = Mathf.Min(val2.x, val3.x); float num2 = Mathf.Max(val2.x, val3.x); float num3 = Mathf.Max(val2.y, val3.y); num3 = Mathf.Max(num3, StockTextTop(val)); float dpi = Screen.dpi; float num4 = TimerMath.CmToPixels(s.HeightCm.Value, dpi); float num5 = TimerMath.CmToPixels(s.GapAboveIconCm.Value, dpi); float num6 = TimerMath.CmToPixels(s.HorizontalOffsetCm.Value, dpi); float num7 = Mathf.Max(6f, (num2 - num) * s.GroupWidth.Value); float num8 = num7 / 3f; float num9 = Mathf.Clamp(num8 * 0.75f, 10f, 48f) * s.TextSize.Value; float num10 = (num + num2) * 0.5f + num6; Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(num10 - num7 * 0.5f, num3 + num5); Vector2 val5 = default(Vector2); ((Vector2)(ref val5))..ctor(num10 + num7 * 0.5f, num3 + num5 + num4 + num9); RectTransform val6 = (RectTransform)((Transform)panel).parent; Vector2 val7 = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(val6, val4, val, ref val7); Vector2 val8 = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(val6, val5, val, ref val8); ((Transform)panel).localPosition = new Vector3(val7.x, val7.y, 0f); panel.sizeDelta = new Vector2(Mathf.Max(1f, val8.x - val7.x), Mathf.Max(1f, val8.y - val7.y)); float num11 = (val8.x - val7.x) / Mathf.Max(1f, val5.x - val4.x); float num12 = num4 / (num4 + num9); float num13 = Mathf.Clamp01(s.BarThickness.Value); float num14 = Mathf.Max(1f, Mathf.Round(num8 * 0.06f)) * num11; float num15 = num9 * 0.9f * num11; for (int i = 0; i < 3; i++) { Column column = columns[i]; column.RootRect.anchorMin = new Vector2((float)i / 3f, 0f); column.RootRect.anchorMax = new Vector2((float)(i + 1) / 3f, 1f); column.Bar.anchorMin = new Vector2((1f - num13) * 0.5f, 0f); column.Bar.anchorMax = new Vector2((1f + num13) * 0.5f, num12); column.Inner.offsetMin = new Vector2(num14, num14); column.Inner.offsetMax = new Vector2(0f - num14, 0f - num14); column.Label.anchorMin = new Vector2(0f, num12); column.Label.anchorMax = new Vector2(1f, 1f); if (!Mathf.Approximately(column.LastFontMax, num15)) { column.LastFontMax = num15; ((TMP_Text)column.Text).fontSizeMax = num15; ((TMP_Text)column.Text).fontSizeMin = num15 * 0.35f; ((Graphic)column.Text).SetVerticesDirty(); } } } private float StockTextTop(Camera cam) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_005c: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI stockText = icon.stockText; if (!Object.op_Implicit((Object)(object)stockText) || !((Component)stockText).gameObject.activeInHierarchy || string.IsNullOrEmpty(((TMP_Text)stockText).text)) { return float.MinValue; } Bounds textBounds = ((TMP_Text)stockText).textBounds; if (((Bounds)(ref textBounds)).size.y <= 0f) { return float.MinValue; } Vector3 val = ((Transform)((TMP_Text)stockText).rectTransform).TransformPoint(new Vector3(((Bounds)(ref textBounds)).center.x, ((Bounds)(ref textBounds)).max.y, 0f)); return RectTransformUtility.WorldToScreenPoint(cam, val).y; } private bool EnsureBuilt() { EquipmentIcon val = FindEquipmentIcon(); if (Object.op_Implicit((Object)(object)panel) && Object.op_Implicit((Object)(object)canvas) && Object.op_Implicit((Object)(object)val) && (Object)(object)val == (Object)(object)icon) { return true; } DestroyPanel(); icon = val; if (!Object.op_Implicit((Object)(object)icon)) { return false; } canvas = ((Component)icon).GetComponentInParent<Canvas>(); if (!Object.op_Implicit((Object)(object)canvas)) { return false; } BuildPanel(); return true; } private EquipmentIcon FindEquipmentIcon() { EquipmentIcon[] equipmentIcons = hud.equipmentIcons; if (equipmentIcons == null) { return null; } for (int i = 0; i < equipmentIcons.Length; i++) { if (Object.op_Implicit((Object)(object)equipmentIcons[i]) && !equipmentIcons[i].displayAlternateEquipment) { return equipmentIcons[i]; } } for (int j = 0; j < equipmentIcons.Length; j++) { if (Object.op_Implicit((Object)(object)equipmentIcons[j])) { return equipmentIcons[j]; } } return null; } private void BuildPanel() { //IL_004a: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_017b: 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_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0204: 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_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0228: 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_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) int layer = ((Component)canvas).gameObject.layer; panel = CreateRect("ShowForgiveMeTimer", ((Component)canvas).transform, layer); RectTransform obj = panel; RectTransform obj2 = panel; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); obj2.anchorMax = val; obj.anchorMin = val; panel.pivot = Vector2.zero; ((Transform)panel).SetAsLastSibling(); ((Component)panel).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; group = ((Component)panel).gameObject.AddComponent<CanvasGroup>(); group.interactable = false; group.blocksRaycasts = false; TMP_FontAsset font = null; Material material = null; PickFont(ref font, ref material); columns = new Column[3]; for (int i = 0; i < 3; i++) { Column column = new Column(); column.RootRect = CreateRect("Boneco" + (i + 1), (Transform)(object)panel, layer); column.Root = ((Component)column.RootRect).gameObject; val = (column.RootRect.offsetMin = (column.RootRect.offsetMax = Vector2.zero)); column.Bar = CreateRect("Barra", (Transform)(object)column.RootRect, layer); val = (column.Bar.offsetMin = (column.Bar.offsetMax = Vector2.zero)); AddImage(column.Bar, FrameColor); column.Inner = CreateRect("Fundo", (Transform)(object)column.Bar, layer); column.Inner.anchorMin = Vector2.zero; column.Inner.anchorMax = Vector2.one; AddImage(column.Inner, BackColor); column.Fill = CreateRect("Tempo", (Transform)(object)column.Inner, layer); column.Fill.anchorMin = Vector2.zero; column.Fill.anchorMax = Vector2.one; val = (column.Fill.offsetMin = (column.Fill.offsetMax = Vector2.zero)); column.FillImage = AddImage(column.Fill, CalmColor); column.Label = CreateRect("Segundos", (Transform)(object)column.RootRect, layer); val = (column.Label.offsetMin = (column.Label.offsetMax = Vector2.zero)); TextMeshProUGUI val6 = ((Component)column.Label).gameObject.AddComponent<TextMeshProUGUI>(); if (Object.op_Implicit((Object)(object)font)) { ((TMP_Text)val6).font = font; } if (Object.op_Implicit((Object)(object)material)) { ((TMP_Text)val6).fontSharedMaterial = material; } ((TMP_Text)val6).alignment = (TextAlignmentOptions)1026; ((TMP_Text)val6).enableWordWrapping = false; ((TMP_Text)val6).overflowMode = (TextOverflowModes)0; ((TMP_Text)val6).enableAutoSizing = true; ((TMP_Text)val6).fontSizeMin = 6f; ((TMP_Text)val6).fontSizeMax = 14f; ((TMP_Text)val6).richText = false; ((Graphic)val6).raycastTarget = false; ((Graphic)val6).color = Color.white; ((TMP_Text)val6).text = string.Empty; column.Text = val6; column.Root.SetActive(false); column.Visible = false; columns[i] = column; } ((Component)panel).gameObject.SetActive(false); panelVisible = false; Array.Clear(assigned, 0, assigned.Length); } private void PickFont(ref TMP_FontAsset font, ref Material material) { TMP_Text val = null; if (Object.op_Implicit((Object)(object)icon.cooldownText) && Object.op_Implicit((Object)(object)((TMP_Text)icon.cooldownText).font)) { val = (TMP_Text)(object)icon.cooldownText; } else if (Object.op_Implicit((Object)(object)icon.stockText) && Object.op_Implicit((Object)(object)((TMP_Text)icon.stockText).font)) { val = (TMP_Text)(object)icon.stockText; } if (Object.op_Implicit((Object)(object)val)) { font = val.font; material = val.fontSharedMaterial; return; } font = HGTextMeshProUGUI.defaultLanguageFont; if (!Object.op_Implicit((Object)(object)font)) { font = TMP_Settings.defaultFontAsset; } } private static RectTransform CreateRect(string name, Transform parent, int layer) { //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_0025: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }) { layer = layer }.transform; ((Transform)val).SetParent(parent, false); ((Transform)val).localScale = Vector3.one; ((Transform)val).localRotation = Quaternion.identity; val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.pivot = new Vector2(0.5f, 0.5f); val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; return val; } private static Image AddImage(RectTransform rt, Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)rt).gameObject.AddComponent<Image>(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } private void SetPanelVisible(bool visible) { if (Object.op_Implicit((Object)(object)panel) && panelVisible != visible) { panelVisible = visible; ((Component)panel).gameObject.SetActive(visible); } } private static void SetColumnVisible(Column col, bool visible) { if (col.Visible != visible) { col.Visible = visible; col.Root.SetActive(visible); } } private void DestroyPanel() { if (Object.op_Implicit((Object)(object)panel)) { Object.Destroy((Object)(object)((Component)panel).gameObject); } panel = null; group = null; columns = null; panelVisible = false; } } internal sealed class TrackedDoll { public readonly DeathProjectile Doll; public readonly ProjectileController Controller; public readonly ProjectileStickOnImpact Stick; public readonly int Order; public CharacterMaster OwnerMaster; public bool EverStuck; public float FullLifetime; public float Remaining; public bool Paused; public bool Alive => Object.op_Implicit((Object)(object)Doll); public TrackedDoll(DeathProjectile doll, int order) { Doll = doll; Order = order; Controller = ((Component)doll).GetComponent<ProjectileController>(); Stick = ((Component)doll).GetComponent<ProjectileStickOnImpact>(); } } internal static class DollTracker { private static readonly List<TrackedDoll> dolls = new List<TrackedDoll>(); private static int nextOrder; private static FieldRef<DeathProjectile, float> durationRef; private static FieldRef<DeathProjectile, float> fixedAgeRef; public static bool Ready { get; private set; } public static IReadOnlyList<TrackedDoll> All => dolls; public static bool Init() { try { FieldInfo fieldInfo = AccessTools.Field(typeof(DeathProjectile), "duration"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(DeathProjectile), "fixedAge"); if (fieldInfo == null || fieldInfo2 == null || fieldInfo.FieldType != typeof(float) || fieldInfo2.FieldType != typeof(float)) { Plugin.Log.LogError((object)"Não achei os campos 'duration'/'fixedAge' do Forgive Me Please. O jogo pode ter mudado; o cronômetro ficará desligado."); return Ready = false; } durationRef = AccessTools.FieldRefAccess<DeathProjectile, float>(fieldInfo); fixedAgeRef = AccessTools.FieldRefAccess<DeathProjectile, float>(fieldInfo2); return Ready = true; } catch (Exception ex) { Plugin.Log.LogError((object)("Falha ao preparar o cronômetro: " + ex)); return Ready = false; } } public static void Register(DeathProjectile doll) { if (!Object.op_Implicit((Object)(object)doll)) { return; } for (int i = 0; i < dolls.Count; i++) { if ((Object)(object)dolls[i].Doll == (Object)(object)doll) { return; } } dolls.Add(new TrackedDoll(doll, nextOrder++)); } public static void Tick() { for (int num = dolls.Count - 1; num >= 0; num--) { if (!dolls[num].Alive) { dolls.RemoveAt(num); } } if (!Ready) { return; } float fixedDeltaTime = Time.fixedDeltaTime; for (int i = 0; i < dolls.Count; i++) { TrackedDoll trackedDoll = dolls[i]; if (!Object.op_Implicit((Object)(object)trackedDoll.OwnerMaster)) { trackedDoll.OwnerMaster = FindOwner(trackedDoll); } float num2 = durationRef.Invoke(trackedDoll.Doll); float fixedAge = fixedAgeRef.Invoke(trackedDoll.Doll); float removalTime = trackedDoll.Doll.removalTime; bool flag = Object.op_Implicit((Object)(object)trackedDoll.Stick) && trackedDoll.Stick.stuck; if (num2 <= 0f) { trackedDoll.Remaining = TimerMath.Remaining(num2, fixedAge, removalTime, fixedDeltaTime); if (!trackedDoll.EverStuck) { trackedDoll.EverStuck = true; trackedDoll.FullLifetime = Mathf.Max(trackedDoll.Remaining, 0.01f); } trackedDoll.Paused = false; } else if (flag) { trackedDoll.Remaining = TimerMath.Remaining(num2, fixedAge, removalTime, fixedDeltaTime); if (!trackedDoll.EverStuck) { trackedDoll.EverStuck = true; trackedDoll.FullLifetime = Mathf.Max(trackedDoll.Remaining, 0.01f); } trackedDoll.Paused = false; } else if (trackedDoll.EverStuck) { trackedDoll.Paused = true; } } } public static void Clear() { dolls.Clear(); } private static CharacterMaster FindOwner(TrackedDoll d) { GameObject val = (Object.op_Implicit((Object)(object)d.Controller) ? d.Controller.owner : null); if (Object.op_Implicit((Object)(object)val)) { CharacterBody component = val.GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.master)) { return component.master; } CharacterMaster component2 = val.GetComponent<CharacterMaster>(); if (Object.op_Implicit((Object)(object)component2)) { return component2; } } Deployable component3 = ((Component)d.Doll).GetComponent<Deployable>(); if (Object.op_Implicit((Object)(object)component3) && Object.op_Implicit((Object)(object)component3.ownerMaster)) { return component3.ownerMaster; } return null; } } [HarmonyPatch(typeof(DeathProjectile), "Awake")] internal static class DeathProjectileAwakePatch { [HarmonyPostfix] private static void Postfix(DeathProjectile __instance) { try { DollTracker.Register(__instance); } catch (Exception ex) { Plugin.Log.LogError((object)ex); } } } [BepInPlugin("com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.samuelcallai.showforgivemetimer"; public const string Name = "Show Forgive Me Timer"; public const string Version = "1.0.2"; internal static ManualLogSource Log; internal static Settings Settings; private Harmony harmony; private float nextHudScan; private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Settings = new Settings(((BaseUnityPlugin)this).Config); if (DollTracker.Init()) { harmony = new Harmony("com.samuelcallai.showforgivemetimer"); harmony.CreateClassProcessor(typeof(DeathProjectileAwakePatch)).Patch(); } if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { try { RiskOfOptionsCompat.Register(Settings); } catch (Exception ex) { Log.LogWarning((object)("Não foi possível colocar as opções no menu do Risk of Options: " + ex.Message)); } } Run.onRunDestroyGlobal += delegate { DollTracker.Clear(); }; Log.LogInfo((object)"Show Forgive Me Timer 1.0.2 carregado."); } private void Update() { DollTracker.Tick(); if (!(Time.unscaledTime >= nextHudScan)) { return; } nextHudScan = Time.unscaledTime + 0.5f; ReadOnlyCollection<HUD> readOnlyInstanceList = HUD.readOnlyInstanceList; for (int i = 0; i < readOnlyInstanceList.Count; i++) { HUD val = readOnlyInstanceList[i]; if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<BarsDisplay>())) { ((Component)val).gameObject.AddComponent<BarsDisplay>(); } } } } internal static class RiskOfOptionsCompat { public const string Guid = "com.rune580.riskofoptions"; [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void Register(Settings s) { //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown ModSettingsManager.SetModDescription("Uma barra vertical para cada boneco do Forgive Me Please (máximo de 3), acima do ícone do equipamento (Q), com os segundos até ele sumir e liberar a vaga para lançar outro. Ligue a Prévia para ajustar a posição.", "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer"); Sprite val = LoadIcon(); if (Object.op_Implicit((Object)(object)val)) { ModSettingsManager.SetModIcon(val, "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer"); } Step(s.HeightCm, 1f, 10f, 0.1f, "{0:0.0} cm"); Step(s.GapAboveIconCm, 0f, 5f, 0.1f, "{0:0.0} cm"); Step(s.GroupWidth, 0.5f, 2f, 0.05f, "{0:0%}"); Step(s.BarThickness, 0.2f, 1f, 0.05f, "{0:0%}"); Step(s.HorizontalOffsetCm, -5f, 5f, 0.1f, "{0:0.0} cm"); Step(s.Opacity, 0.2f, 1f, 0.05f, "{0:0%}"); Step(s.TextSize, 0.5f, 2f, 0.05f, "{0:0%}"); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(s.ShowTenths), "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer"); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(s.Preview), "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer"); } private static void Step(ConfigEntry<float> entry, float min, float max, float increment, string format) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown StepSliderConfig val = new StepSliderConfig { min = min, max = max, increment = increment, FormatString = format }; ModSettingsManager.AddOption((BaseOption)new StepSliderOption(entry, val), "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer"); } private static Sprite LoadIcon() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) try { using Stream stream = typeof(RiskOfOptionsCompat).Assembly.GetManifestResourceStream("ShowForgiveMeTimer.icon.png"); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } catch (IOException) { return null; } } } internal sealed class Settings { internal const string SectionBars = "Barras"; internal const string SectionText = "Texto"; internal const string SectionTest = "Teste"; public readonly ConfigEntry<float> HeightCm; public readonly ConfigEntry<float> GapAboveIconCm; public readonly ConfigEntry<float> GroupWidth; public readonly ConfigEntry<float> BarThickness; public readonly ConfigEntry<float> HorizontalOffsetCm; public readonly ConfigEntry<float> Opacity; public readonly ConfigEntry<float> TextSize; public readonly ConfigEntry<bool> ShowTenths; public readonly ConfigEntry<bool> Preview; public Settings(ConfigFile config) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown HeightCm = config.Bind<float>("Barras", "AlturaCm", 3.2f, new ConfigDescription("Altura das barras, em centímetros (aproximado: usa o DPI do Windows).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); GapAboveIconCm = config.Bind<float>("Barras", "DistanciaAcimaDoQCm", 0.1f, new ConfigDescription("Espaço entre o topo do ícone do Q (ou do número de cargas) e o pé das barras, em centímetros.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); GroupWidth = config.Bind<float>("Barras", "LarguraDoConjunto", 1f, new ConfigDescription("Largura das três barras juntas, comparada com o ícone do Q. 1 = mesma largura do ícone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); BarThickness = config.Bind<float>("Barras", "GrossuraDasBarras", 0.6f, new ConfigDescription("Quanto de cada coluna a barra ocupa. 1 = barras encostadas umas nas outras.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>())); HorizontalOffsetCm = config.Bind<float>("Barras", "DeslocamentoHorizontalCm", 0f, new ConfigDescription("Empurra as barras para a esquerda (negativo) ou para a direita (positivo), em centímetros.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>())); Opacity = config.Bind<float>("Barras", "Opacidade", 0.3f, new ConfigDescription("Opacidade das barras e dos números. 1 = totalmente sólido.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>())); TextSize = config.Bind<float>("Texto", "TamanhoDoTexto", 1f, new ConfigDescription("Tamanho dos números acima das barras (1 = padrão).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); ShowTenths = config.Bind<bool>("Texto", "MostrarDecimos", true, "Mostra os segundos com uma casa decimal (6.4). Desligado, mostra só segundos inteiros (7)."); Preview = config.Bind<bool>("Teste", "Previa", false, "Mostra três barras de exemplo durante a partida, sem precisar lançar bonecos. Serve para ajustar a posição e o tamanho. Lembre de desligar depois."); } } public static class TimerMath { public const float ShortTimeThreshold = 3f; public const float LastSecondThreshold = 1f; public static float Remaining(float duration, float fixedAge, float removalTime) { float num = Math.Max(0f, removalTime); float num2 = Math.Max(0f, fixedAge); if (duration > 0f) { float num3 = (float)Math.Ceiling(duration); return Math.Max(0f, num3 - Math.Min(num2, 1f) + num); } return Math.Max(0f, num - num2); } public static float Remaining(float duration, float fixedAge, float removalTime, float fixedDeltaTime) { if (!(fixedDeltaTime > 0.0005f) || !(fixedDeltaTime <= 0.5f)) { return Remaining(duration, fixedAge, removalTime); } float target = Math.Max(0f, removalTime); float start = Math.Max(0f, fixedAge); if (duration > 0f) { int num = (int)Math.Ceiling(duration); return (float)(StepsUntil(start, 1f, fixedDeltaTime) + (num - 1) * StepsUntil(0f, 1f, fixedDeltaTime) + StepsUntil(0f, target, fixedDeltaTime)) * fixedDeltaTime; } return (float)StepsUntil(start, target, fixedDeltaTime) * fixedDeltaTime; } public static int StepsUntil(float start, float target, float dt) { float num = start; int num2 = 0; do { num += dt; num2++; } while (num < target && num2 < 100000); return num2; } public static float Smooth(float remaining, float sinceLastFixedStep, float fixedDeltaTime) { float val = Math.Max(0f, fixedDeltaTime); float num = Math.Min(Math.Max(0f, sinceLastFixedStep), val); return Math.Max(0f, remaining - num); } public static float Fraction(float remaining, float fullLifetime) { if (fullLifetime <= 0.01f) { if (!(remaining > 0f)) { return 0f; } return 1f; } float num = remaining / fullLifetime; if (num < 0f) { return 0f; } if (num > 1f) { return 1f; } return num; } public static int Urgency(float remaining) { if (remaining <= 1f) { return 2; } if (remaining <= 3f) { return 1; } return 0; } public static string Format(float remaining, bool tenths) { float num = Math.Max(0f, remaining); if (tenths) { double num2 = Math.Ceiling((double)num * 10.0 - 0.0001) / 10.0; if (num2 <= 0.0) { return "0.0"; } return num2.ToString("0.0", CultureInfo.InvariantCulture); } return Math.Max(0, (int)Math.Ceiling((double)num - 0.0001)).ToString(CultureInfo.InvariantCulture); } public static float CmToPixels(float cm, float dpi) { float num = ((dpi >= 50f && dpi <= 600f) ? dpi : 96f); return cm / 2.54f * num; } }