using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 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("pixx; TactiKot")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Numerical stamina and affliction values for current PEAK builds.")]
[assembly: AssemblyFileVersion("1.3.7.0")]
[assembly: AssemblyInformationalVersion("1.3.7+7441897f07d7f8fb69e84e4656e79cea9531f0de")]
[assembly: AssemblyProduct("StaminaStatsTactikot")]
[assembly: AssemblyTitle("StaminaStatsTactikot")]
[assembly: AssemblyVersion("1.3.7.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 StaminaStatsTactikot
{
internal static class HudController
{
private static StaminaHudView attachedView;
internal static void AttachTo(StaminaBar bar)
{
if ((Object)(object)bar == (Object)null)
{
return;
}
GUIManager instance = GUIManager.instance;
if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.bar == (Object)null) && !((Object)(object)instance.bar != (Object)(object)bar))
{
StaminaHudView staminaHudView = ((Component)bar).GetComponent<StaminaHudView>();
if ((Object)(object)staminaHudView == (Object)null)
{
staminaHudView = ((Component)bar).gameObject.AddComponent<StaminaHudView>();
}
staminaHudView.Initialize(bar);
attachedView = staminaHudView;
}
}
internal static void Cleanup()
{
if ((Object)(object)attachedView != (Object)null)
{
Object.Destroy((Object)(object)attachedView);
attachedView = null;
}
}
}
internal static class HudLabelLayout
{
private const float LaneGapRatio = 0.1f;
internal static float CalculateLaneStep(float renderedTextHeight)
{
if (renderedTextHeight < 0f || float.IsNaN(renderedTextHeight) || float.IsInfinity(renderedTextHeight))
{
throw new ArgumentOutOfRangeException("renderedTextHeight");
}
return renderedTextHeight + renderedTextHeight * 0.1f;
}
}
internal static class HudLabelRowLayout
{
internal static void AssignLanes(float[] centers, float[] widths, float[] rowYs, int count, int laneCount, float gap, float rowTolerance, int[] lanes, int[] orderWorkspace, float[] laneRightWorkspace)
{
if (centers == null)
{
throw new ArgumentNullException("centers");
}
if (widths == null)
{
throw new ArgumentNullException("widths");
}
if (rowYs == null)
{
throw new ArgumentNullException("rowYs");
}
if (lanes == null)
{
throw new ArgumentNullException("lanes");
}
if (orderWorkspace == null)
{
throw new ArgumentNullException("orderWorkspace");
}
if (laneRightWorkspace == null)
{
throw new ArgumentNullException("laneRightWorkspace");
}
if (count < 0 || count > centers.Length || count > widths.Length || count > rowYs.Length || count > lanes.Length || count > orderWorkspace.Length)
{
throw new ArgumentOutOfRangeException("count");
}
if (laneCount <= 0 || laneCount > laneRightWorkspace.Length)
{
throw new ArgumentOutOfRangeException("laneCount");
}
if (gap < 0f || float.IsNaN(gap) || float.IsInfinity(gap))
{
throw new ArgumentOutOfRangeException("gap");
}
if (rowTolerance < 0f || float.IsNaN(rowTolerance) || float.IsInfinity(rowTolerance))
{
throw new ArgumentOutOfRangeException("rowTolerance");
}
for (int i = 0; i < count; i++)
{
orderWorkspace[i] = i;
}
for (int j = 1; j < count; j++)
{
int num = orderWorkspace[j];
int num2 = j - 1;
while (num2 >= 0 && (rowYs[orderWorkspace[num2]] > rowYs[num] || (rowYs[orderWorkspace[num2]] == rowYs[num] && centers[orderWorkspace[num2]] > centers[num])))
{
orderWorkspace[num2 + 1] = orderWorkspace[num2];
num2--;
}
orderWorkspace[num2 + 1] = num;
}
int num3 = 0;
while (num3 < count)
{
float num4 = rowYs[orderWorkspace[num3]];
int k;
for (k = num3 + 1; k < count && Math.Abs(rowYs[orderWorkspace[k]] - num4) <= rowTolerance; k++)
{
}
for (int l = num3 + 1; l < k; l++)
{
int num5 = orderWorkspace[l];
int num6 = l - 1;
while (num6 >= num3 && centers[orderWorkspace[num6]] > centers[num5])
{
orderWorkspace[num6 + 1] = orderWorkspace[num6];
num6--;
}
orderWorkspace[num6 + 1] = num5;
}
for (int m = 0; m < laneCount; m++)
{
laneRightWorkspace[m] = float.NegativeInfinity;
}
for (int n = num3; n < k; n++)
{
int num7 = orderWorkspace[n];
float num8 = Math.Max(0f, widths[num7]) * 0.5f;
float num9 = centers[num7] - num8;
float num10 = centers[num7] + num8;
int num11 = -1;
for (int num12 = 0; num12 < laneCount; num12++)
{
if (num9 >= laneRightWorkspace[num12] + gap)
{
num11 = num12;
break;
}
}
if (num11 < 0)
{
num11 = 0;
for (int num13 = 1; num13 < laneCount; num13++)
{
if (laneRightWorkspace[num13] < laneRightWorkspace[num11])
{
num11 = num13;
}
}
}
lanes[num7] = num11;
laneRightWorkspace[num11] = num10;
}
num3 = k;
}
}
}
internal static class HudTextColor
{
internal static float GetWhiteBlend(float red, float green, float blue, bool highContrast)
{
float num = 0.2126f * red + 0.7152f * green + 0.0722f * blue;
float num2 = (highContrast ? 0.75f : 0.55f);
if (num >= num2)
{
return 0f;
}
return (num2 - num) / (1f - num);
}
}
internal enum HudValueKind
{
Hidden,
Number
}
internal readonly struct HudValuePresentation
{
internal HudValueKind Kind { get; }
internal int Value { get; }
internal bool IsVisible => Kind != HudValueKind.Hidden;
private HudValuePresentation(HudValueKind kind, int value)
{
Kind = kind;
Value = value;
}
internal static HudValuePresentation Create(int roundedValue, bool enabled, bool sourceVisible, bool showZero)
{
if (!enabled || !sourceVisible)
{
return new HudValuePresentation(HudValueKind.Hidden, 0);
}
if (roundedValue == 0 && !showZero)
{
return new HudValuePresentation(HudValueKind.Hidden, 0);
}
return new HudValuePresentation(HudValueKind.Number, roundedValue);
}
}
internal static class MinimaxRounding
{
internal enum RoundingProtection : byte
{
ForceUp,
None,
ForceDown
}
internal readonly struct Remainder
{
internal int Index { get; }
internal double Fraction { get; }
internal RoundingProtection Protection { get; }
internal Remainder(int index, double fraction, RoundingProtection protection)
{
Index = index;
Fraction = fraction;
Protection = protection;
}
}
private sealed class ExactRemainderComparer : IComparer<Remainder>
{
internal static readonly ExactRemainderComparer Instance = new ExactRemainderComparer();
public int Compare(Remainder left, Remainder right)
{
int num = right.Fraction.CompareTo(left.Fraction);
if (num == 0)
{
return left.Index.CompareTo(right.Index);
}
return num;
}
}
private sealed class StableRemainderComparer : IComparer<Remainder>
{
internal static readonly StableRemainderComparer Instance = new StableRemainderComparer();
public int Compare(Remainder left, Remainder right)
{
if (left.Protection != right.Protection)
{
return left.Protection.CompareTo(right.Protection);
}
int num = right.Fraction.CompareTo(left.Fraction);
if (num == 0)
{
return left.Index.CompareTo(right.Index);
}
return num;
}
}
internal static int[] Round(IReadOnlyList<double> values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
int count = values.Count;
int[] result = new int[count];
if (count == 0)
{
return result;
}
double[] array = new double[count];
for (int i = 0; i < count; i++)
{
array[i] = values[i];
}
Remainder[] workspace = new Remainder[count];
RoundInto(array, count, result, workspace, null, null, null, 0.0, stable: false);
return result;
}
internal static void RoundInto(double[] values, int count, int[] result, Remainder[] workspace, int[] previousRoundedValues, double[] previousExactValues, bool[] hasPreviousValues, double directionTolerance, bool stable)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
if (workspace == null)
{
throw new ArgumentNullException("workspace");
}
if (count < 0 || count > values.Length || count > result.Length || count > workspace.Length)
{
throw new ArgumentOutOfRangeException("count");
}
if (previousRoundedValues != null && previousRoundedValues.Length < count)
{
throw new ArgumentException("Previous values buffer is too small.", "previousRoundedValues");
}
if (previousExactValues != null && previousExactValues.Length < count)
{
throw new ArgumentException("Previous exact values buffer is too small.", "previousExactValues");
}
if (hasPreviousValues != null && hasPreviousValues.Length < count)
{
throw new ArgumentException("Previous-value flags buffer is too small.", "hasPreviousValues");
}
if (directionTolerance < 0.0 || double.IsNaN(directionTolerance))
{
throw new ArgumentOutOfRangeException("directionTolerance");
}
if (count == 0)
{
return;
}
double num = 0.0;
long num2 = 0L;
int num3 = 0;
for (int i = 0; i < count; i++)
{
double num4 = values[i];
if (double.IsNaN(num4) || double.IsInfinity(num4))
{
throw new ArgumentOutOfRangeException("values", "Values must be finite.");
}
double num5 = Math.Floor(num4);
if (num5 < -2147483648.0 || num5 > 2147483647.0)
{
throw new ArgumentOutOfRangeException("values", "Values are outside the supported range.");
}
int num6 = (result[i] = (int)num5);
num2 += num6;
num += num4;
if (num4 != num5)
{
RoundingProtection protection = ResolveProtection(num4, num6, i, previousRoundedValues, previousExactValues, hasPreviousValues, directionTolerance);
workspace[num3++] = new Remainder(i, num4 - num5, protection);
}
}
long num7 = checked((long)Math.Round(num, MidpointRounding.AwayFromZero)) - num2;
if (num7 < 0 || num7 > num3)
{
throw new InvalidOperationException("The rounded total cannot be reached.");
}
IComparer<Remainder> comparer;
if (!stable)
{
IComparer<Remainder> instance = ExactRemainderComparer.Instance;
comparer = instance;
}
else
{
IComparer<Remainder> instance = StableRemainderComparer.Instance;
comparer = instance;
}
IComparer<Remainder> comparer2 = comparer;
for (int j = 1; j < num3; j++)
{
Remainder remainder = workspace[j];
int num8 = j - 1;
while (num8 >= 0 && comparer2.Compare(workspace[num8], remainder) > 0)
{
workspace[num8 + 1] = workspace[num8];
num8--;
}
workspace[num8 + 1] = remainder;
}
for (int k = 0; k < num7; k++)
{
result[workspace[k].Index]++;
}
}
private static RoundingProtection ResolveProtection(double value, int floorValue, int index, int[] previousRoundedValues, double[] previousExactValues, bool[] hasPreviousValues, double tolerance)
{
if (previousRoundedValues == null || previousExactValues == null || hasPreviousValues == null || !hasPreviousValues[index])
{
return RoundingProtection.None;
}
int num = previousRoundedValues[index];
double num2 = previousExactValues[index];
bool num3 = (double)num > num2 + tolerance;
bool flag = (double)num < num2 - tolerance;
if (num3 && value >= num2 - tolerance && floorValue < num)
{
return RoundingProtection.ForceUp;
}
if (flag && value <= num2 + tolerance && floorValue + 1 > num)
{
return RoundingProtection.ForceDown;
}
return RoundingProtection.None;
}
}
internal enum RoundingMode
{
Balanced,
Standard,
Truncate
}
internal static class NumericRounding
{
private const double IntegerSnapTolerancePerScale = 1E-05;
internal static int GetScale(int decimalPlaces)
{
return decimalPlaces switch
{
0 => 1,
1 => 10,
2 => 100,
_ => throw new ArgumentOutOfRangeException("decimalPlaces"),
};
}
internal static double Scale(double value, int decimalPlaces)
{
int scale = GetScale(decimalPlaces);
double num = value * (double)scale;
double num2 = Math.Round(num, MidpointRounding.AwayFromZero);
if (!(Math.Abs(num - num2) <= 1E-05 * (double)scale))
{
return num;
}
return num2;
}
internal static int RoundIndependent(double value, int decimalPlaces, RoundingMode mode)
{
double num = Scale(value, decimalPlaces);
double num2 = ((mode == RoundingMode.Truncate) ? Math.Floor(num) : Math.Round(num, MidpointRounding.AwayFromZero));
if (num2 < -2147483648.0 || num2 > 2147483647.0)
{
throw new ArgumentOutOfRangeException("value");
}
return (int)num2;
}
}
[BepInPlugin("com.tactikot.StaminaStatsTactikot", "StaminaStatsTactikot", "1.3.7")]
[BepInProcess("PEAK.exe")]
[BepInIncompatibility("com.StaminaStats")]
public sealed class Plugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(StaminaBar), "Start")]
private static class StaminaBarStartPatch
{
private static void Postfix(StaminaBar __instance)
{
try
{
HudController.AttachTo(__instance);
}
catch (Exception exception)
{
ReportOnce("StaminaBar.Start patch failed", exception);
}
}
}
[HarmonyPatch(typeof(GUIManager), "Start")]
private static class GUIManagerStartPatch
{
private static void Postfix(GUIManager __instance)
{
try
{
HudController.AttachTo(__instance.bar);
}
catch (Exception exception)
{
ReportOnce("GUIManager.Start patch failed", exception);
}
}
}
public const string PluginGuid = "com.tactikot.StaminaStatsTactikot";
public const string PluginName = "StaminaStatsTactikot";
public const string PluginVersion = "1.3.7";
private const int MaximumReportedErrors = 64;
private static readonly HashSet<string> ReportedErrors = new HashSet<string>();
private Harmony harmony;
internal static ManualLogSource Log { get; private set; }
internal static ConfigEntry<bool> Enabled { get; private set; }
internal static ConfigEntry<bool> ShowStamina { get; private set; }
internal static ConfigEntry<bool> ShowBonusStamina { get; private set; }
internal static ConfigEntry<bool> ShowAfflictions { get; private set; }
internal static ConfigEntry<bool> ShowPercentageSign { get; private set; }
internal static ConfigEntry<bool> ShowZeroValues { get; private set; }
internal static ConfigEntry<RoundingMode> RoundingMode { get; private set; }
internal static ConfigEntry<int> DecimalPlaces { get; private set; }
internal static ConfigEntry<int> StaminaFontSize { get; private set; }
internal static ConfigEntry<int> AfflictionFontSize { get; private set; }
internal static ConfigEntry<float> TextOutlineThickness { get; private set; }
internal static ConfigEntry<float> HudOpacity { get; private set; }
internal static ConfigEntry<float> StaminaVerticalOffset { get; private set; }
internal static ConfigEntry<float> AfflictionVerticalOffset { get; private set; }
internal static ConfigEntry<int> MaxAfflictionLabelLanes { get; private set; }
internal static ConfigEntry<float> AfflictionLaneTransitionDuration { get; private set; }
internal static ConfigEntry<bool> HighContrastMode { get; private set; }
internal static ConfigEntry<bool> FollowGameColorblindMode { get; private set; }
internal static ConfigEntry<int> ValueRefreshRate { get; private set; }
internal static ConfigEntry<bool> VerboseLogging { get; private set; }
internal static int DisplaySettingsVersion { get; private set; }
private void Awake()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
bool hadCurrentConfig = File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath);
BindConfig();
MigrateLegacyConfig(hadCurrentConfig);
harmony = new Harmony("com.tactikot.StaminaStatsTactikot");
harmony.PatchAll();
Log.LogInfo((object)"StaminaStatsTactikot v1.3.7 loaded.");
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
HudController.Cleanup();
}
private void BindConfig()
{
Enabled = BindDisplay("Enabled", defaultValue: true, "Enable the numeric HUD overlay.");
ShowStamina = BindDisplay("ShowStamina", defaultValue: true, "Show current stamina.");
ShowBonusStamina = BindDisplay("ShowBonusStamina", defaultValue: true, "Show bonus stamina independently of the main value.");
ShowAfflictions = BindDisplay("ShowAfflictions", defaultValue: true, "Show values for visible affliction segments.");
ShowPercentageSign = BindDisplay("ShowPercentageSign", defaultValue: false, "Show a percentage sign (%) after values.");
ShowZeroValues = BindDisplay("ShowZeroValues", defaultValue: false, "Show values that round to zero.");
RoundingMode = BindDisplay("RoundingMode", StaminaStatsTactikot.RoundingMode.Balanced, "Value rounding: Balanced preserves the combined total and favors stable rounding; Standard rounds independently; Truncate discards extra digits.");
DecimalPlaces = BindDisplay("DecimalPlaces", 0, "Number of digits shown after the decimal point.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2));
StaminaFontSize = BindDisplay("StaminaFontSize", 18, "Font size for stamina values.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 36));
AfflictionFontSize = BindDisplay("AfflictionFontSize", 16, "Font size for affliction values.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 32));
TextOutlineThickness = BindDisplay("TextOutlineThickness", 0.1f, "Text outline thickness. Set to 0 to disable the outline.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.3f));
HudOpacity = BindDisplay("HudOpacity", 1f, "Opacity of numeric labels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 1f));
StaminaVerticalOffset = BindDisplay("StaminaVerticalOffset", 25f, "Vertical offset of stamina labels relative to the native bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, 120f));
AfflictionVerticalOffset = BindDisplay("AfflictionVerticalOffset", -15f, "Vertical offset of affliction labels relative to their native segments.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 100f));
MaxAfflictionLabelLanes = BindDisplay("MaxAfflictionLabelLanes", 3, "Maximum label rows used to prevent overlapping affliction values.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3));
AfflictionLaneTransitionDuration = BindDisplay("AfflictionLaneTransitionDuration", 0.12f, "Seconds used to smoothly move labels between rows. Set to 0 for instant movement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f));
HighContrastMode = BindDisplay("HighContrastMode", defaultValue: false, "Lighten numeric labels further and use a stronger outline.");
FollowGameColorblindMode = BindDisplay("FollowGameColorblindMode", defaultValue: true, "Use PEAK's HUD hues, including color-blind adjustments; dark shades are brightened for readability.");
ValueRefreshRate = BindDisplay("ValueRefreshRate", 20, "Numeric value refreshes per second. Position and visibility still update every frame.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 60));
VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Enable detailed diagnostic logging.");
}
private ConfigEntry<T> BindDisplay<T>(string key, T defaultValue, string description)
{
return BindDisplay(key, defaultValue, description, null);
}
private ConfigEntry<T> BindDisplay<T>(string key, T defaultValue, string description, AcceptableValueBase acceptableValues)
{
//IL_001a: 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_0020: Expected O, but got Unknown
ConfigDescription val = ((acceptableValues == null) ? new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()) : new ConfigDescription(description, acceptableValues, Array.Empty<object>()));
ConfigEntry<T> obj = ((BaseUnityPlugin)this).Config.Bind<T>("Display", key, defaultValue, val);
obj.SettingChanged += OnDisplaySettingChanged;
return obj;
}
private static void OnDisplaySettingChanged(object sender, EventArgs eventArgs)
{
DisplaySettingsVersion++;
}
private void MigrateLegacyConfig(bool hadCurrentConfig)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
if (hadCurrentConfig)
{
return;
}
string text = Path.Combine(Paths.ConfigPath, "com.StaminaStats.cfg");
if (!File.Exists(text))
{
return;
}
try
{
ConfigFile val = new ConfigFile(text, false);
ShowPercentageSign.Value = val.Bind<bool>("Display", "ShowPercentageSign", ShowPercentageSign.Value, (ConfigDescription)null).Value;
StaminaFontSize.Value = val.Bind<int>("Display", "StaminaFontSize", StaminaFontSize.Value, (ConfigDescription)null).Value;
AfflictionFontSize.Value = val.Bind<int>("Display", "AfflictionFontSize", AfflictionFontSize.Value, (ConfigDescription)null).Value;
TextOutlineThickness.Value = val.Bind<float>("Display", "TextOutlineThickness", TextOutlineThickness.Value, (ConfigDescription)null).Value;
VerboseLogging.Value = val.Bind<bool>("Debug", "VerboseLogging", VerboseLogging.Value, (ConfigDescription)null).Value;
((BaseUnityPlugin)this).Config.Save();
Log.LogInfo((object)"Migrated settings from com.StaminaStats.cfg.");
}
catch (Exception exception)
{
ReportOnce("Legacy config migration failed", exception);
}
}
internal static void ReportOnce(string operation, Exception exception)
{
string item = operation + ":" + exception.GetType().FullName;
if (ReportedErrors.Count >= 64 || !ReportedErrors.Add(item))
{
return;
}
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)(operation + ": " + exception.Message));
}
if (VerboseLogging != null && VerboseLogging.Value)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogError((object)exception);
}
}
}
}
internal sealed class StaminaHudView : MonoBehaviour
{
private struct PresentationState
{
private HudValueKind kind;
private int value;
private bool percentage;
private int decimalPlaces;
private bool initialized;
internal bool Matches(HudValuePresentation presentation, bool showPercentage, int displayedDecimalPlaces)
{
if (initialized && kind == presentation.Kind && value == presentation.Value && percentage == showPercentage)
{
return decimalPlaces == displayedDecimalPlaces;
}
return false;
}
internal void Set(HudValuePresentation presentation, bool showPercentage, int displayedDecimalPlaces)
{
kind = presentation.Kind;
value = presentation.Value;
percentage = showPercentage;
decimalPlaces = displayedDecimalPlaces;
initialized = true;
}
}
private const int MaximumAfflictions = 32;
private const float LabelGap = 1f;
private const float LabelRowTolerance = 1f;
private const float RoundingChangeTolerance = 0.0001f;
private static readonly Color FallbackMainColor = new Color(0.72f, 1f, 0.72f);
private static readonly Color FallbackBonusColor = new Color(1f, 0.92f, 0.25f);
private readonly BarAffliction[] afflictions = (BarAffliction[])(object)new BarAffliction[32];
private readonly RectTransform[] afflictionRects = (RectTransform[])(object)new RectTransform[32];
private readonly Image[] afflictionImages = (Image[])(object)new Image[32];
private readonly TextMeshProUGUI[] afflictionTexts = (TextMeshProUGUI[])(object)new TextMeshProUGUI[32];
private readonly PresentationState[] afflictionPresentationStates = new PresentationState[32];
private readonly int[] roundedAfflictionValues = new int[32];
private readonly int[] previousRoundedByItem = new int[33];
private readonly double[] roundingValues = new double[33];
private readonly int[] roundingResults = new int[33];
private readonly int[] previousRoundingResults = new int[33];
private readonly double[] previousExactRoundingValues = new double[33];
private readonly bool[] hasPreviousRoundingValues = new bool[33];
private readonly int[] roundingItemIndexes = new int[33];
private readonly MinimaxRounding.Remainder[] roundingWorkspace = new MinimaxRounding.Remainder[33];
private readonly double[] previousExactByItem = new double[33];
private readonly bool[] hasPreviousExactByItem = new bool[33];
private readonly int[] activeAfflictionIndexes = new int[32];
private readonly float[] labelCenters = new float[32];
private readonly float[] labelWidths = new float[32];
private readonly float[] labelBaseY = new float[32];
private readonly int[] labelLanes = new int[32];
private readonly int[] labelOrderWorkspace = new int[32];
private readonly float[] laneRightWorkspace = new float[3];
private readonly float[] currentLaneOffsets = new float[32];
private readonly float[] laneOffsetVelocities = new float[32];
private readonly bool[] laneOffsetInitialized = new bool[32];
private StaminaBar bar;
private Character previousObservedCharacter;
private RectTransform overlayRoot;
private TextMeshProUGUI staminaText;
private TextMeshProUGUI bonusText;
private Image staminaImage;
private Image bonusImage;
private Material sharedTextMaterial;
private int afflictionCount;
private int appliedSettingsVersion = -1;
private RoundingMode appliedRoundingMode;
private int appliedDecimalPlaces = -1;
private float nextValueRefreshTime;
private int previousActiveLabelCount = -1;
private int previousLabelLaneCount;
private bool initialized;
private bool faulted;
private PresentationState staminaPresentationState;
private PresentationState bonusPresentationState;
internal void Initialize(StaminaBar sourceBar)
{
if ((Object)(object)sourceBar == (Object)null)
{
return;
}
if (initialized)
{
int num = afflictionCount;
CacheAfflictions();
if (afflictionCount != num)
{
ApplySettings(force: true);
}
return;
}
bar = sourceBar;
BuildView();
CacheAfflictions();
ApplySettings(force: true);
initialized = true;
nextValueRefreshTime = 0f;
if (Plugin.VerboseLogging.Value)
{
Plugin.Log.LogInfo((object)$"Attached numeric HUD to {((Object)bar).name} with {afflictionCount} affliction slots.");
}
}
private void LateUpdate()
{
if (!initialized || faulted)
{
return;
}
try
{
Character observedCharacter = Character.observedCharacter;
if (previousObservedCharacter != observedCharacter)
{
previousObservedCharacter = observedCharacter;
ResetRoundingHistory();
for (int i = 0; i < afflictionCount; i++)
{
ResetLaneTransition(i);
}
nextValueRefreshTime = 0f;
}
bool flag = ShouldBeVisible(observedCharacter);
SetOverlayVisible(flag);
if (flag)
{
ApplySettings(force: false);
if (Time.unscaledTime >= nextValueRefreshTime)
{
UpdateValues(observedCharacter);
nextValueRefreshTime = Time.unscaledTime + 1f / (float)Plugin.ValueRefreshRate.Value;
}
LayoutAfflictionLabels();
}
}
catch (Exception exception)
{
faulted = true;
SetOverlayVisible(visible: false);
Plugin.ReportOnce("Stamina HUD disabled after an update failure", exception);
}
}
private void OnDestroy()
{
if ((Object)(object)sharedTextMaterial != (Object)null)
{
Object.Destroy((Object)(object)sharedTextMaterial);
sharedTextMaterial = null;
}
if ((Object)(object)overlayRoot != (Object)null)
{
Object.Destroy((Object)(object)((Component)overlayRoot).gameObject);
overlayRoot = null;
}
}
private void BuildView()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
//IL_006f: 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_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: 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_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Expected O, but got Unknown
GameObject val = new GameObject("StaminaStatsTactikot", new Type[2]
{
typeof(RectTransform),
typeof(Canvas)
});
val.layer = ((Component)bar).gameObject.layer;
overlayRoot = (RectTransform)val.transform;
((Transform)overlayRoot).SetParent(((Component)bar).transform, false);
overlayRoot.anchorMin = Vector2.zero;
overlayRoot.anchorMax = Vector2.one;
overlayRoot.offsetMin = Vector2.zero;
overlayRoot.offsetMax = Vector2.zero;
((Transform)overlayRoot).localScale = Vector3.one;
Canvas component = val.GetComponent<Canvas>();
Canvas componentInParent = ((Component)bar).GetComponentInParent<Canvas>();
component.overrideSorting = true;
if ((Object)(object)componentInParent != (Object)null)
{
component.sortingLayerID = componentInParent.sortingLayerID;
component.sortingOrder = componentInParent.sortingOrder + 1;
}
TMP_FontAsset val2 = (((Object)(object)bar.moraleBoostText != (Object)null) ? ((TMP_Text)bar.moraleBoostText).font : TMP_Settings.defaultFontAsset);
Material val3 = (((Object)(object)bar.moraleBoostText != (Object)null) ? ((TMP_Text)bar.moraleBoostText).fontSharedMaterial : (((Object)(object)val2 != (Object)null) ? ((TMP_Asset)val2).material : null));
if ((Object)(object)val3 != (Object)null)
{
sharedTextMaterial = new Material(val3)
{
name = "StaminaStatsTactikot Shared Text Material"
};
}
staminaText = CreateText("StaminaValue", val2, (TextAlignmentOptions)1028);
ConfigureRect(((TMP_Text)staminaText).rectTransform, new Vector2(1f, 0f), new Vector2(0f, 0.5f));
bonusText = CreateText("BonusStaminaValue", val2, (TextAlignmentOptions)1025);
ConfigureRect(((TMP_Text)bonusText).rectTransform, new Vector2(0f, 0f), new Vector2(0f, 0.5f));
staminaImage = (((Object)(object)bar.staminaBar != (Object)null) ? ((Component)bar.staminaBar).GetComponent<Image>() : null);
bonusImage = (((Object)(object)bar.extraBar != (Object)null) ? ((Component)bar.extraBar).GetComponent<Image>() : null);
}
private void CacheAfflictions()
{
int num = ((bar.afflictions != null) ? Mathf.Min(bar.afflictions.Length, 32) : 0);
for (int i = 0; i < num; i++)
{
CacheAffliction(bar.afflictions[i]);
}
if ((Object)(object)bar.petrifyAffliction != (Object)null && !ContainsAffliction(bar.petrifyAffliction))
{
CacheAffliction(bar.petrifyAffliction);
}
BarAffliction[] array = bar.afflictions;
if (((array != null) ? array.Length : 0) + (((Object)(object)bar.petrifyAffliction != (Object)null && !ContainsAffliction(bar.petrifyAffliction)) ? 1 : 0) > 32)
{
Plugin.Log.LogWarning((object)$"Only the first {32} affliction segments can be displayed.");
}
}
private void CacheAffliction(BarAffliction affliction)
{
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)affliction == (Object)null) && afflictionCount < 32 && !ContainsAffliction(affliction))
{
int num = afflictionCount++;
afflictions[num] = affliction;
afflictionRects[num] = (((Object)(object)affliction.rtf != (Object)null) ? affliction.rtf : ((Component)affliction).GetComponent<RectTransform>());
afflictionImages[num] = (((Object)(object)affliction.icon != (Object)null) ? affliction.icon : ((Component)affliction).GetComponentInChildren<Image>());
TextMeshProUGUI val = CreateText(((object)Unsafe.As<STATUSTYPE, STATUSTYPE>(ref affliction.afflictionType)/*cast due to .constrained prefix*/).ToString() + "Value", ((TMP_Text)staminaText).font, (TextAlignmentOptions)514);
ConfigureRect(((TMP_Text)val).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f));
((Component)val).gameObject.SetActive(false);
afflictionTexts[num] = val;
}
}
private bool ContainsAffliction(BarAffliction candidate)
{
for (int i = 0; i < afflictionCount; i++)
{
if ((Object)(object)afflictions[i] == (Object)(object)candidate)
{
return true;
}
}
return false;
}
private TextMeshProUGUI CreateText(string name, TMP_FontAsset font, TextAlignmentOptions alignment)
{
//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_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) })
{
layer = ((Component)bar).gameObject.layer
};
val.transform.SetParent((Transform)(object)overlayRoot, false);
TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
((Graphic)obj).raycastTarget = false;
((TMP_Text)obj).font = font;
((TMP_Text)obj).fontSharedMaterial = sharedTextMaterial;
((TMP_Text)obj).alignment = alignment;
((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0;
((TMP_Text)obj).overflowMode = (TextOverflowModes)0;
((TMP_Text)obj).enableAutoSizing = false;
((TMP_Text)obj).fontStyle = (FontStyles)1;
((TMP_Text)obj).text = string.Empty;
return obj;
}
private static void ConfigureRect(RectTransform rect, Vector2 pivot, Vector2 anchor)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
rect.anchorMin = anchor;
rect.anchorMax = anchor;
rect.pivot = pivot;
rect.sizeDelta = new Vector2(40f, 24f);
}
private bool ShouldBeVisible(Character observed)
{
if (!Plugin.Enabled.Value || (Object)(object)bar == (Object)null || !((Component)bar).gameObject.activeInHierarchy || (Object)(object)observed == (Object)null || (Object)(object)observed.data == (Object)null || observed.data.dead || observed.data.fullyPassedOut)
{
return false;
}
GUIManager instance = GUIManager.instance;
if ((Object)(object)instance == (Object)null || (Object)(object)instance.bar != (Object)(object)bar)
{
return false;
}
if ((Object)(object)instance.hudCanvas != (Object)null && !((Behaviour)instance.hudCanvas).enabled)
{
return false;
}
if (!((Object)(object)instance.staminaCanvasGroup == (Object)null))
{
return instance.staminaCanvasGroup.alpha > 0.01f;
}
return true;
}
private void ApplySettings(bool force)
{
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
if (!force && appliedSettingsVersion == Plugin.DisplaySettingsVersion)
{
return;
}
appliedSettingsVersion = Plugin.DisplaySettingsVersion;
RoundingMode value = Plugin.RoundingMode.Value;
int value2 = Plugin.DecimalPlaces.Value;
if (value != appliedRoundingMode || value2 != appliedDecimalPlaces)
{
ResetRoundingHistory();
appliedRoundingMode = value;
appliedDecimalPlaces = value2;
}
((TMP_Text)staminaText).fontSize = Plugin.StaminaFontSize.Value;
((TMP_Text)bonusText).fontSize = Plugin.StaminaFontSize.Value;
for (int i = 0; i < afflictionCount; i++)
{
((TMP_Text)afflictionTexts[i]).fontSize = Plugin.AfflictionFontSize.Value;
}
float num = (Plugin.HighContrastMode.Value ? Mathf.Max(0.16f, Plugin.TextOutlineThickness.Value) : Plugin.TextOutlineThickness.Value);
if ((Object)(object)sharedTextMaterial != (Object)null)
{
ShaderUtilities.GetShaderPropertyIDs();
if (sharedTextMaterial.HasProperty(ShaderUtilities.ID_OutlineWidth))
{
sharedTextMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, num);
}
if (sharedTextMaterial.HasProperty(ShaderUtilities.ID_OutlineColor))
{
sharedTextMaterial.SetColor(ShaderUtilities.ID_OutlineColor, Color.black);
}
if (sharedTextMaterial.HasProperty(ShaderUtilities.ID_FaceColor))
{
sharedTextMaterial.SetColor(ShaderUtilities.ID_FaceColor, Color.white);
}
}
UpdateMeshPadding();
UpdateStaminaLayout();
UpdateColors();
nextValueRefreshTime = 0f;
}
private void UpdateMeshPadding()
{
((TMP_Text)staminaText).UpdateMeshPadding();
((TMP_Text)bonusText).UpdateMeshPadding();
for (int i = 0; i < afflictionCount; i++)
{
((TMP_Text)afflictionTexts[i]).UpdateMeshPadding();
}
}
private void UpdateStaminaLayout()
{
float height = (float)Plugin.StaminaFontSize.Value + 8f;
SetRect(((TMP_Text)staminaText).rectTransform, 20f, Plugin.StaminaVerticalOffset.Value, 72f, height);
SetRect(((TMP_Text)bonusText).rectTransform, 26f, Plugin.StaminaVerticalOffset.Value, 72f, height);
}
private void UpdateValues(Character observed)
{
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
int value = Plugin.DecimalPlaces.Value;
int scale = NumericRounding.GetScale(value);
RoundingMode value2 = Plugin.RoundingMode.Value;
float value3 = Mathf.Max(0f, observed.data.currentStamina * 100f);
float num = Mathf.Max(0f, observed.data.extraStamina * 100f);
bool flag = observed.refs != null && (Object)(object)observed.refs.afflictions != (Object)null;
int count = 0;
if (Plugin.ShowStamina.Value)
{
AddRoundingValue(ref count, 0, value3, value);
}
else
{
ClearRoundingItem(0);
}
for (int i = 0; i < afflictionCount; i++)
{
BarAffliction val = afflictions[i];
bool num2 = Plugin.ShowAfflictions.Value && flag && (Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy;
float value4 = 0f;
if (num2)
{
value4 = (val.isPetrify ? Mathf.Max(0f, (float)observed.data.petrifyAmount) : Mathf.Max(0f, observed.refs.afflictions.GetCurrentStatus(val.afflictionType) * 100f));
}
if (num2)
{
AddRoundingValue(ref count, i + 1, value4, value);
continue;
}
roundedAfflictionValues[i] = 0;
ClearRoundingItem(i + 1);
}
if (count > 0)
{
if (value2 == RoundingMode.Balanced)
{
MinimaxRounding.RoundInto(roundingValues, count, roundingResults, roundingWorkspace, previousRoundingResults, previousExactRoundingValues, hasPreviousRoundingValues, 0.0001f * (float)scale, stable: true);
}
else
{
for (int j = 0; j < count; j++)
{
roundingResults[j] = ((value2 == RoundingMode.Truncate) ? ((int)Math.Floor(roundingValues[j])) : ((int)Math.Round(roundingValues[j], MidpointRounding.AwayFromZero)));
}
}
for (int k = 0; k < count; k++)
{
int num3 = roundingItemIndexes[k];
int num4 = roundingResults[k];
previousRoundedByItem[num3] = num4;
if (num3 > 0)
{
roundedAfflictionValues[num3 - 1] = num4;
}
}
}
HudValuePresentation presentation = HudValuePresentation.Create(Plugin.ShowStamina.Value ? previousRoundedByItem[0] : 0, Plugin.ShowStamina.Value, sourceVisible: true, Plugin.ShowZeroValues.Value);
ApplyPresentation(staminaText, presentation, bonus: false, value, ref staminaPresentationState);
RoundingMode mode = ((value2 == RoundingMode.Balanced) ? RoundingMode.Standard : value2);
HudValuePresentation presentation2 = HudValuePresentation.Create(NumericRounding.RoundIndependent(num, value, mode), Plugin.ShowBonusStamina.Value, sourceVisible: true, Plugin.ShowZeroValues.Value);
ApplyPresentation(bonusText, presentation2, bonus: true, value, ref bonusPresentationState);
for (int l = 0; l < afflictionCount; l++)
{
BarAffliction val2 = afflictions[l];
bool sourceVisible = flag && (Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeInHierarchy;
HudValuePresentation presentation3 = HudValuePresentation.Create(roundedAfflictionValues[l], Plugin.ShowAfflictions.Value, sourceVisible, Plugin.ShowZeroValues.Value);
ApplyPresentation(afflictionTexts[l], presentation3, bonus: false, value, ref afflictionPresentationStates[l]);
}
UpdateColors();
}
private void AddRoundingValue(ref int count, int itemIndex, float value, int decimalPlaces)
{
double num = NumericRounding.Scale(value, decimalPlaces);
roundingValues[count] = num;
roundingItemIndexes[count] = itemIndex;
previousRoundingResults[count] = previousRoundedByItem[itemIndex];
previousExactRoundingValues[count] = previousExactByItem[itemIndex];
hasPreviousRoundingValues[count] = hasPreviousExactByItem[itemIndex];
previousExactByItem[itemIndex] = num;
hasPreviousExactByItem[itemIndex] = true;
count++;
}
private void ClearRoundingItem(int itemIndex)
{
previousRoundedByItem[itemIndex] = 0;
previousExactByItem[itemIndex] = 0.0;
hasPreviousExactByItem[itemIndex] = false;
}
private void ResetRoundingHistory()
{
Array.Clear(previousRoundedByItem, 0, previousRoundedByItem.Length);
Array.Clear(previousExactByItem, 0, previousExactByItem.Length);
Array.Clear(hasPreviousExactByItem, 0, hasPreviousExactByItem.Length);
}
private static void ApplyPresentation(TextMeshProUGUI text, HudValuePresentation presentation, bool bonus, int decimalPlaces, ref PresentationState state)
{
bool isVisible = presentation.IsVisible;
if (((Component)text).gameObject.activeSelf != isVisible)
{
((Component)text).gameObject.SetActive(isVisible);
}
bool value = Plugin.ShowPercentageSign.Value;
if (!isVisible)
{
state.Set(presentation, value, decimalPlaces);
}
else if (!state.Matches(presentation, value, decimalPlaces))
{
float num = (float)presentation.Value / (float)NumericRounding.GetScale(decimalPlaces);
switch (decimalPlaces)
{
case 0:
((TMP_Text)text).SetText((!value) ? (bonus ? "+{0:0}" : "{0:0}") : (bonus ? "+{0:0}%" : "{0:0}%"), num);
break;
case 1:
((TMP_Text)text).SetText((!value) ? (bonus ? "+{0:0.0}" : "{0:0.0}") : (bonus ? "+{0:0.0}%" : "{0:0.0}%"), num);
break;
case 2:
((TMP_Text)text).SetText((!value) ? (bonus ? "+{0:0.00}" : "{0:0.00}") : (bonus ? "+{0:0.00}%" : "{0:0.00}%"), num);
break;
default:
throw new ArgumentOutOfRangeException("decimalPlaces");
}
state.Set(presentation, value, decimalPlaces);
}
}
private void UpdateColors()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: 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)
((Graphic)staminaText).color = ResolveTextColor(staminaImage, FallbackMainColor, 0);
((Graphic)bonusText).color = ResolveTextColor(bonusImage, FallbackBonusColor, 1);
for (int i = 0; i < afflictionCount; i++)
{
((Graphic)afflictionTexts[i]).color = ResolveTextColor(afflictionImages[i], CreateFallbackStatusColor(i), i + 2);
}
}
private static Color ResolveTextColor(Image image, Color fallback, int index)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: 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)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: 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)
Color val = (((Object)(object)image != (Object)null) ? ((Graphic)image).color : fallback);
if (!Plugin.FollowGameColorblindMode.Value)
{
float num2 = default(float);
float num3 = default(float);
float num = default(float);
Color.RGBToHSV(val, ref num, ref num2, ref num3);
num = Mathf.Repeat(num + (float)index * 0.011f, 1f);
val = Color.HSVToRGB(num, Mathf.Clamp01(num2 * 1.15f), Mathf.Max(0.8f, num3));
}
float whiteBlend = HudTextColor.GetWhiteBlend(val.r, val.g, val.b, Plugin.HighContrastMode.Value);
val = Color.Lerp(val, Color.white, whiteBlend);
val.a = Plugin.HudOpacity.Value;
return val;
}
private static Color CreateFallbackStatusColor(int index)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
return Color.HSVToRGB(Mathf.Repeat((float)index * 0.618034f, 1f), 0.68f, 1f);
}
private void LayoutAfflictionLabels()
{
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
int value = Plugin.MaxAfflictionLabelLanes.Value;
bool flag = value != previousLabelLaneCount;
for (int i = 0; i < afflictionCount; i++)
{
TextMeshProUGUI val = afflictionTexts[i];
RectTransform val2 = afflictionRects[i];
BarAffliction val3 = afflictions[i];
if ((Object)(object)val3 == (Object)null || !((Component)val3).gameObject.activeInHierarchy)
{
ResetLaneTransition(i);
if (((Component)val).gameObject.activeSelf)
{
((Component)val).gameObject.SetActive(false);
}
continue;
}
if (!((Component)val).gameObject.activeSelf || (Object)(object)val2 == (Object)null)
{
ResetLaneTransition(i);
continue;
}
Rect rect = val2.rect;
Vector3 val4 = ((Transform)val2).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center));
Vector3 val5 = ((Transform)overlayRoot).InverseTransformPoint(val4);
float num2 = Mathf.Max(1f, ((TMP_Text)val).preferredWidth);
flag |= activeAfflictionIndexes[num] != i || labelCenters[num] != val5.x || labelBaseY[num] != val5.y || labelWidths[num] != num2;
activeAfflictionIndexes[num] = i;
labelCenters[num] = val5.x;
labelBaseY[num] = val5.y;
labelWidths[num] = num2;
num++;
}
flag |= num != previousActiveLabelCount;
previousActiveLabelCount = num;
previousLabelLaneCount = value;
if (num == 0)
{
return;
}
if (flag)
{
HudLabelRowLayout.AssignLanes(labelCenters, labelWidths, labelBaseY, num, value, 1f, 1f, labelLanes, labelOrderWorkspace, laneRightWorkspace);
}
float height = (float)Plugin.AfflictionFontSize.Value + 8f;
float num3 = HudLabelLayout.CalculateLaneStep(Plugin.AfflictionFontSize.Value);
float num4 = ((Plugin.AfflictionVerticalOffset.Value <= 0f) ? (-1f) : 1f);
float value2 = Plugin.AfflictionLaneTransitionDuration.Value;
for (int j = 0; j < num; j++)
{
int num5 = activeAfflictionIndexes[j];
float num6 = num4 * (float)labelLanes[j] * num3;
if (!laneOffsetInitialized[num5] || value2 <= 0f)
{
currentLaneOffsets[num5] = num6;
laneOffsetVelocities[num5] = 0f;
laneOffsetInitialized[num5] = true;
}
else
{
currentLaneOffsets[num5] = Mathf.SmoothDamp(currentLaneOffsets[num5], num6, ref laneOffsetVelocities[num5], value2, float.PositiveInfinity, Time.unscaledDeltaTime);
if (Mathf.Abs(currentLaneOffsets[num5] - num6) <= 0.01f)
{
currentLaneOffsets[num5] = num6;
laneOffsetVelocities[num5] = 0f;
}
}
float y = labelBaseY[j] + Plugin.AfflictionVerticalOffset.Value + currentLaneOffsets[num5];
SetRect(((TMP_Text)afflictionTexts[num5]).rectTransform, labelCenters[j], y, Mathf.Clamp(labelWidths[j] + 8f, 32f, 88f), height);
}
}
private void ResetLaneTransition(int index)
{
currentLaneOffsets[index] = 0f;
laneOffsetVelocities[index] = 0f;
laneOffsetInitialized[index] = false;
}
private static void SetRect(RectTransform rect, float x, float y, float width, float height)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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_001b: 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_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
Vector2 anchoredPosition = rect.anchoredPosition;
if (Mathf.Abs(anchoredPosition.x - x) > 0.01f || Mathf.Abs(anchoredPosition.y - y) > 0.01f)
{
rect.anchoredPosition = new Vector2(x, y);
}
Vector2 sizeDelta = rect.sizeDelta;
if (Mathf.Abs(sizeDelta.x - width) > 0.01f || Mathf.Abs(sizeDelta.y - height) > 0.01f)
{
rect.sizeDelta = new Vector2(width, height);
}
}
private void SetOverlayVisible(bool visible)
{
if ((Object)(object)overlayRoot != (Object)null && ((Component)overlayRoot).gameObject.activeSelf != visible)
{
((Component)overlayRoot).gameObject.SetActive(visible);
}
}
}
}