using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
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 Unity.Netcode;
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("TowerStatsMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.10.0")]
[assembly: AssemblyInformationalVersion("1.0.10+ded0321878575e1e2dd3053142a71cc979c4a6c1")]
[assembly: AssemblyProduct("TowerStatsMod")]
[assembly: AssemblyTitle("TowerStatsMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.10.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 TowerStatsMod
{
internal static class Patches
{
public static bool IsTower(Unit? unit)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Invalid comparison between Unknown and I4
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Invalid comparison between Unknown and I4
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Invalid comparison between Unknown and I4
if ((Object)(object)unit == (Object)null || !unit.isBuilding)
{
return false;
}
if ((Object)(object)unit.playerBuilding != (Object)null)
{
HouseType houseType = unit.playerBuilding.HouseType;
if ((int)houseType == 3 || (int)houseType == 9 || (int)houseType == 10 || (int)houseType == 17)
{
return true;
}
return false;
}
try
{
if ((Object)(object)((Component)unit).GetComponent<AutoTower>() != (Object)null)
{
return true;
}
}
catch
{
}
return false;
}
public static TowerStatsComponent? GetOrCreateTowerStats(Unit unit, bool resetStats = false)
{
if ((Object)(object)unit == (Object)null || !IsTower(unit))
{
return null;
}
TowerStatsComponent component = ((Component)unit).GetComponent<TowerStatsComponent>();
if ((Object)(object)component != (Object)null)
{
if (resetStats)
{
component.ResetStats();
}
return component;
}
try
{
TowerStatsComponent towerStatsComponent = ((Component)unit).gameObject.AddComponent<TowerStatsComponent>();
towerStatsComponent.Init(unit);
if (resetStats)
{
towerStatsComponent.ResetStats();
}
return towerStatsComponent;
}
catch
{
return null;
}
}
public static void EnsureComponentAttachedToBuilding(PlayerBuilding? building, bool resetStats = false)
{
if (!((Object)(object)building == (Object)null))
{
Unit val = building.Owner;
if ((Object)(object)val == (Object)null)
{
val = ((Component)building).GetComponent<Unit>();
}
if ((Object)(object)val == (Object)null)
{
val = ((Component)building).GetComponentInParent<Unit>();
}
if ((Object)(object)val != (Object)null && IsTower(val))
{
GetOrCreateTowerStats(val, resetStats);
}
}
}
public static void EnsureComponentAttachedToSpot(BuildingSpot? spot, bool resetStats = false)
{
if (!((Object)(object)spot == (Object)null) && (Object)(object)spot.PlayerBuilding != (Object)null)
{
EnsureComponentAttachedToBuilding(spot.PlayerBuilding, resetStats);
}
}
[HarmonyPatch(typeof(SimpleDamageable), "TakeDamage")]
[HarmonyPostfix]
private static void SimpleDamageable_TakeDamage_Postfix(SimpleDamageable __instance, float amount, IDamageSource source)
{
if (amount <= 0f || source == null)
{
return;
}
try
{
Unit sourceUnit = source.SourceUnit;
if ((Object)(object)sourceUnit != (Object)null && IsTower(sourceUnit))
{
TowerStatsComponent orCreateTowerStats = GetOrCreateTowerStats(sourceUnit);
if ((Object)(object)orCreateTowerStats != (Object)null)
{
orCreateTowerStats.RecordDamage(amount);
}
}
}
catch
{
}
}
[HarmonyPatch(typeof(BuildingDamageable), "TakeDamage")]
[HarmonyPostfix]
private static void BuildingDamageable_TakeDamage_Postfix(BuildingDamageable __instance, float amount, IDamageSource source)
{
if (amount <= 0f || source == null)
{
return;
}
try
{
Unit sourceUnit = source.SourceUnit;
if ((Object)(object)sourceUnit != (Object)null && IsTower(sourceUnit))
{
TowerStatsComponent orCreateTowerStats = GetOrCreateTowerStats(sourceUnit);
if ((Object)(object)orCreateTowerStats != (Object)null)
{
orCreateTowerStats.RecordDamage(amount);
}
}
}
catch
{
}
}
[HarmonyPatch(typeof(DamageBatchManager), "ApplyHitLocally")]
[HarmonyPostfix]
private static void DamageBatchManager_ApplyHitLocally_Postfix(ulong targetNetId, float damage, HitResultType type, bool isBuilding)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
if (damage <= 0f)
{
return;
}
try
{
if (!((Object)(object)NetworkManager.Singleton != (Object)null) || NetworkManager.Singleton.SpawnManager == null || !NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(targetNetId, out var value) || !((Object)(object)value != (Object)null))
{
return;
}
Unit val = FindNearestTower(((Component)value).transform.position);
if ((Object)(object)val != (Object)null)
{
TowerStatsComponent orCreateTowerStats = GetOrCreateTowerStats(val);
if ((Object)(object)orCreateTowerStats != (Object)null)
{
orCreateTowerStats.RecordDamage(damage);
}
Unit component = ((Component)value).GetComponent<Unit>();
if ((Object)(object)component != (Object)null && (component.IsDead || (component.Damageable != null && component.Damageable.CurrentHealth <= 0f)))
{
orCreateTowerStats?.RecordKill();
}
}
}
catch
{
}
}
private static Unit? FindNearestTower(Vector3 targetPos)
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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)
float num = 1600f;
Unit result = null;
IReadOnlyList<TowerStatsComponent> activeTowers = TowerStatsManager.ActiveTowers;
for (int i = 0; i < activeTowers.Count; i++)
{
TowerStatsComponent towerStatsComponent = activeTowers[i];
if ((Object)(object)towerStatsComponent == (Object)null)
{
continue;
}
Unit component = ((Component)towerStatsComponent).GetComponent<Unit>();
if ((Object)(object)component != (Object)null && ((Component)component).gameObject.activeInHierarchy)
{
Vector3 val = ((Component)component).transform.position - targetPos;
float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
if (sqrMagnitude < num)
{
num = sqrMagnitude;
result = component;
}
}
}
return result;
}
[HarmonyPatch(typeof(PlayerStatisticsManager), "OnUnitKilled")]
[HarmonyPostfix]
private static void PlayerStatisticsManager_OnUnitKilled_Postfix(Unit victim, Unit killer)
{
if ((Object)(object)killer == (Object)null)
{
return;
}
try
{
if (IsTower(killer))
{
TowerStatsComponent orCreateTowerStats = GetOrCreateTowerStats(killer);
if ((Object)(object)orCreateTowerStats != (Object)null)
{
orCreateTowerStats.RecordKill();
}
}
}
catch
{
}
}
[HarmonyPatch(typeof(PlayerBuilding), "OnNetworkSpawn")]
[HarmonyPostfix]
private static void PlayerBuilding_OnNetworkSpawn_Postfix(PlayerBuilding __instance)
{
EnsureComponentAttachedToBuilding(__instance, resetStats: true);
}
[HarmonyPatch(typeof(BuildingSpot), "OnEnable")]
[HarmonyPostfix]
private static void BuildingSpot_OnEnable_Postfix(BuildingSpot __instance)
{
EnsureComponentAttachedToSpot(__instance, resetStats: true);
}
[HarmonyPatch(typeof(BuildingDamageable), "Initialize")]
[HarmonyPostfix]
private static void BuildingDamageable_Initialize_Postfix(BuildingDamageable __instance, Unit owner)
{
if ((Object)(object)owner != (Object)null && IsTower(owner))
{
GetOrCreateTowerStats(owner, resetStats: true);
}
}
}
[BepInPlugin("com.antigravity.towerstatsmod", "Tower Stats Mod", "1.0.10")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.antigravity.towerstatsmod";
public const string PluginName = "Tower Stats Mod";
public const string PluginVersion = "1.0.10";
private Harmony _harmony;
public static Plugin Instance { get; private set; } = null;
internal static ManualLogSource Log { get; private set; } = null;
public static bool IsModEnabled { get; private set; } = true;
public static ConfigEntry<KeyboardShortcut> ToggleKey { get; private set; } = null;
public static ConfigEntry<float> DpsWindowSeconds { get; private set; } = null;
public static ConfigEntry<float> ShowRadius { get; private set; } = null;
public static ConfigEntry<float> HeightOffset { get; private set; } = null;
public static ConfigEntry<float> UiScale { get; private set; } = null;
public static ConfigEntry<int> FontSize { get; private set; } = null;
public static ConfigEntry<bool> RenderThrough { get; private set; } = null;
private void Awake()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
BindConfig();
_harmony = new Harmony("com.antigravity.towerstatsmod");
_harmony.PatchAll(typeof(Patches));
Log.LogInfo((object)"\ud83c\udff0 Tower Stats Mod v1.0.10 initialized! Press F6 to toggle stats display.");
}
private void Update()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
KeyboardShortcut value = ToggleKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
IsModEnabled = !IsModEnabled;
Log.LogInfo((object)("[TowerStatsMod] Tower stats display toggled " + (IsModEnabled ? "ON" : "OFF")));
}
}
private void BindConfig()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "ToggleKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Key to toggle tower stats display (F6).");
DpsWindowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "DpsWindowSeconds", 5f, "Time window in seconds to calculate rolling current DPS.");
ShowRadius = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "ShowRadius", 32f, "Maximum distance (in units) from player to show tower stats.");
HeightOffset = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Appearance", "HeightOffset", 4f, "Height position offset above tower base.");
UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Appearance", "UiScale", 0.019f, "Overall scale of the overhead badge.");
FontSize = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Appearance", "FontSize", 16, "Font size of the kills and DPS text.");
RenderThrough = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Appearance", "RenderThrough", true, "Render text through/on top of tower geometry (ZTest Always).");
}
private void OnDestroy()
{
_harmony.UnpatchSelf();
}
}
public sealed class TowerStatsComponent : MonoBehaviour
{
private struct DamageSample
{
public float Time;
public float Amount;
}
private Unit? _unit;
private readonly Queue<DamageSample> _rollingSamples = new Queue<DamageSample>(128);
private Canvas? _canvas;
private RectTransform? _canvasRT;
private Text? _killsText;
private Text? _dpsText;
private Image? _bgImage;
private Camera? _cam;
private static Material? _alwaysOnTopTextMaterial;
private static Material? _alwaysOnTopImageMaterial;
private static PlayerInteract? _staticLocalPlayer;
private static float _staticLastPlayerCheckTime;
private bool _uiInitialized;
private float _nextUIUpdate;
private float _lastRenderedDPS = -1f;
private int _lastRenderedKills = -1;
public float TotalDamage { get; private set; }
public int Kills { get; private set; }
public float CurrentDPS { get; private set; }
public static Material AlwaysOnTopTextMaterial
{
get
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
if ((Object)(object)_alwaysOnTopTextMaterial == (Object)null)
{
try
{
Shader val = Shader.Find("GUI/Text Shader") ?? Shader.Find("UI/Default");
if ((Object)(object)val != (Object)null)
{
_alwaysOnTopTextMaterial = new Material(val);
((Object)_alwaysOnTopTextMaterial).name = "TowerStatsTextOverlayMaterial";
_alwaysOnTopTextMaterial.SetInt("unity_GUIZTestMode", 8);
_alwaysOnTopTextMaterial.SetInt("_ZTest", 8);
_alwaysOnTopTextMaterial.renderQueue = 3000;
}
}
catch
{
}
}
return _alwaysOnTopTextMaterial;
}
}
public static Material AlwaysOnTopImageMaterial
{
get
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
if ((Object)(object)_alwaysOnTopImageMaterial == (Object)null)
{
try
{
Shader val = Shader.Find("UI/Default") ?? Shader.Find("Sprites/Default");
if ((Object)(object)val != (Object)null)
{
_alwaysOnTopImageMaterial = new Material(val);
((Object)_alwaysOnTopImageMaterial).name = "TowerStatsImageOverlayMaterial";
_alwaysOnTopImageMaterial.SetInt("unity_GUIZTestMode", 8);
_alwaysOnTopImageMaterial.SetInt("_ZTest", 8);
_alwaysOnTopImageMaterial.renderQueue = 3000;
}
}
catch
{
}
}
return _alwaysOnTopImageMaterial;
}
}
public void Init(Unit unit)
{
_unit = unit;
}
public void ResetStats()
{
TotalDamage = 0f;
Kills = 0;
CurrentDPS = 0f;
_rollingSamples.Clear();
_lastRenderedDPS = -1f;
_lastRenderedKills = -1;
UpdateUIContent();
}
private void Start()
{
BuildUI();
_uiInitialized = true;
}
private void OnEnable()
{
if (_uiInitialized && ((Object)(object)_canvas == (Object)null || (Object)(object)_killsText == (Object)null))
{
BuildUI();
}
}
private void OnDestroy()
{
if ((Object)(object)_canvas != (Object)null && (Object)(object)((Component)_canvas).gameObject != (Object)null)
{
Object.Destroy((Object)(object)((Component)_canvas).gameObject);
}
}
public void RecordDamage(float amount)
{
if (!(amount <= 0f))
{
TotalDamage += amount;
_rollingSamples.Enqueue(new DamageSample
{
Time = Time.time,
Amount = amount
});
}
}
public void RecordKill(int count = 1)
{
if (count > 0)
{
Kills += count;
}
}
private void Update()
{
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: 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)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: 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_0179: 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)
if (!Plugin.IsModEnabled)
{
return;
}
if ((Object)(object)_canvas == (Object)null || (Object)(object)_canvasRT == (Object)null || (Object)(object)_killsText == (Object)null || (Object)(object)_dpsText == (Object)null)
{
BuildUI();
if ((Object)(object)_canvas == (Object)null || (Object)(object)_canvasRT == (Object)null)
{
return;
}
}
PlayerInteract localPlayer = GetLocalPlayer();
float value = Plugin.ShowRadius.Value;
if ((Object)(object)localPlayer != (Object)null && (Object)(object)((Component)localPlayer).gameObject != (Object)null && ((Component)localPlayer).gameObject.activeInHierarchy && value > 0f && Vector3.Distance(((Component)this).transform.position, ((Component)localPlayer).transform.position) > value)
{
if (((Component)_canvas).gameObject.activeSelf)
{
((Component)_canvas).gameObject.SetActive(false);
}
return;
}
if (!((Component)_canvas).gameObject.activeSelf)
{
((Component)_canvas).gameObject.SetActive(true);
}
if ((Object)(object)_cam == (Object)null || !((Behaviour)_cam).isActiveAndEnabled)
{
_cam = Camera.main;
}
if ((Object)(object)_cam != (Object)null)
{
Vector3 val = ((Component)_canvas).transform.position - ((Component)_cam).transform.position;
if (val != Vector3.zero)
{
((Component)_canvas).transform.rotation = Quaternion.LookRotation(val);
}
}
float value2 = Plugin.DpsWindowSeconds.Value;
float num = Time.time - value2;
while (_rollingSamples.Count > 0 && _rollingSamples.Peek().Time < num)
{
_rollingSamples.Dequeue();
}
float num2 = 0f;
foreach (DamageSample rollingSample in _rollingSamples)
{
num2 += rollingSample.Amount;
}
CurrentDPS = ((value2 > 0.1f) ? (num2 / value2) : 0f);
if (Time.time >= _nextUIUpdate)
{
_nextUIUpdate = Time.time + 0.1f;
UpdateUIContent();
}
}
private void BuildUI()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Expected O, but got Unknown
//IL_019b: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0204: Unknown result type (might be due to invalid IL or missing references)
//IL_020b: Expected O, but got Unknown
//IL_0275: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
Transform val = ((Component)this).transform.Find("TowerStatsCanvas");
if ((Object)(object)val != (Object)null)
{
Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
}
GameObject val2 = new GameObject("TowerStatsCanvas");
val2.transform.SetParent(((Component)this).transform, false);
_canvas = val2.AddComponent<Canvas>();
_canvas.renderMode = (RenderMode)2;
_canvas.overrideSorting = true;
_canvas.sortingOrder = 30000;
_canvasRT = val2.GetComponent<RectTransform>();
_canvasRT.sizeDelta = new Vector2(100f, 52f);
((Transform)_canvasRT).localScale = Vector3.one * Plugin.UiScale.Value;
((Transform)_canvasRT).localPosition = new Vector3(0f, Plugin.HeightOffset.Value, 0f);
_bgImage = val2.AddComponent<Image>();
((Graphic)_bgImage).color = new Color(0.04f, 0.06f, 0.1f, 0.9f);
Font builtinResource = Resources.GetBuiltinResource<Font>("Arial.ttf");
int value = Plugin.FontSize.Value;
GameObject val3 = new GameObject("KillsLabel");
val3.transform.SetParent(val2.transform, false);
_killsText = val3.AddComponent<Text>();
_killsText.font = builtinResource;
_killsText.fontSize = value;
_killsText.fontStyle = (FontStyle)1;
_killsText.alignment = (TextAnchor)4;
((Graphic)_killsText).color = new Color(0.95f, 0.95f, 0.95f, 1f);
RectTransform component = val3.GetComponent<RectTransform>();
component.anchorMin = new Vector2(0f, 0.5f);
component.anchorMax = new Vector2(1f, 1f);
component.offsetMin = new Vector2(2f, 0f);
component.offsetMax = new Vector2(-2f, 0f);
GameObject val4 = new GameObject("DPSLabel");
val4.transform.SetParent(val2.transform, false);
_dpsText = val4.AddComponent<Text>();
_dpsText.font = builtinResource;
_dpsText.fontSize = value;
_dpsText.fontStyle = (FontStyle)1;
_dpsText.alignment = (TextAnchor)4;
((Graphic)_dpsText).color = new Color(0.35f, 0.85f, 1f, 1f);
RectTransform component2 = val4.GetComponent<RectTransform>();
component2.anchorMin = new Vector2(0f, 0f);
component2.anchorMax = new Vector2(1f, 0.5f);
component2.offsetMin = new Vector2(2f, 0f);
component2.offsetMax = new Vector2(-2f, 0f);
ApplyOverlayMaterials();
UpdateUIContent();
}
private void ApplyOverlayMaterials()
{
if (!Plugin.RenderThrough.Value)
{
return;
}
Material alwaysOnTopImageMaterial = AlwaysOnTopImageMaterial;
if ((Object)(object)alwaysOnTopImageMaterial != (Object)null && (Object)(object)_bgImage != (Object)null)
{
((Graphic)_bgImage).material = alwaysOnTopImageMaterial;
}
Material alwaysOnTopTextMaterial = AlwaysOnTopTextMaterial;
if ((Object)(object)alwaysOnTopTextMaterial != (Object)null)
{
if ((Object)(object)_killsText != (Object)null)
{
((Graphic)_killsText).material = alwaysOnTopTextMaterial;
}
if ((Object)(object)_dpsText != (Object)null)
{
((Graphic)_dpsText).material = alwaysOnTopTextMaterial;
}
}
}
private void UpdateUIContent()
{
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_killsText == (Object)null) && !((Object)(object)_dpsText == (Object)null) && !((Object)(object)_canvasRT == (Object)null) && (!(Mathf.Abs(CurrentDPS - _lastRenderedDPS) < 0.1f) || Kills != _lastRenderedKills))
{
_lastRenderedDPS = CurrentDPS;
_lastRenderedKills = Kills;
int value = Plugin.FontSize.Value;
if (_killsText.fontSize != value)
{
_killsText.fontSize = value;
}
if (_dpsText.fontSize != value)
{
_dpsText.fontSize = value;
}
ApplyOverlayMaterials();
string text = FormatNumber(CurrentDPS);
string text2 = Kills.ToString(CultureInfo.InvariantCulture);
_killsText.text = "⚔ Kills: " + text2;
_dpsText.text = "⚡ DPS: " + text;
float num = Mathf.Clamp(Mathf.Max(_killsText.preferredWidth, _dpsText.preferredWidth) + 20f, 75f, 320f);
if (Mathf.Abs(_canvasRT.sizeDelta.x - num) > 1f)
{
_canvasRT.sizeDelta = new Vector2(num, 52f);
}
}
}
public static string FormatNumber(float val)
{
if (val < 0.1f)
{
return "0";
}
if (val < 1000f)
{
return val.ToString("F0", CultureInfo.InvariantCulture);
}
if (val < 1000000f)
{
return (val / 1000f).ToString("F1", CultureInfo.InvariantCulture) + "k";
}
return (val / 1000000f).ToString("F2", CultureInfo.InvariantCulture) + "M";
}
private static PlayerInteract? GetLocalPlayer()
{
if ((Object)(object)_staticLocalPlayer != (Object)null && (Object)(object)((Component)_staticLocalPlayer).gameObject != (Object)null && ((Component)_staticLocalPlayer).gameObject.activeInHierarchy)
{
return _staticLocalPlayer;
}
if (Time.time - _staticLastPlayerCheckTime < 0.5f)
{
return _staticLocalPlayer;
}
_staticLastPlayerCheckTime = Time.time;
try
{
PlayerInteract[] array = Object.FindObjectsOfType<PlayerInteract>();
if (array != null)
{
PlayerInteract[] array2 = array;
foreach (PlayerInteract val in array2)
{
if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy && ((NetworkBehaviour)val).IsOwner)
{
_staticLocalPlayer = val;
return _staticLocalPlayer;
}
}
}
}
catch
{
}
return _staticLocalPlayer;
}
}
public static class TowerStatsManager
{
private static readonly List<TowerStatsComponent> _activeTowers = new List<TowerStatsComponent>();
public static IReadOnlyList<TowerStatsComponent> ActiveTowers => _activeTowers;
public static void RegisterTower(TowerStatsComponent tower)
{
if ((Object)(object)tower != (Object)null && !_activeTowers.Contains(tower))
{
_activeTowers.Add(tower);
}
}
public static void UnregisterTower(TowerStatsComponent tower)
{
if ((Object)(object)tower != (Object)null)
{
_activeTowers.Remove(tower);
}
}
public static void Clear()
{
_activeTowers.Clear();
}
}
}