Decompiled source of Carnometer v2.0.0

BepInEx/plugins/Carnometer.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 Pigeon.Movement;
using Sparroh.UI;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Carnometer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Carnometer")]
[assembly: AssemblyTitle("Carnometer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class CarnometerMod
{
	internal class DPSPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlayerData), "OnLocalPlayerDamageTarget")]
		private static bool PrefixDamage(in DamageCallbackData data)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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)
			if (Instance == null)
			{
				return true;
			}
			if (data.damageData.damage > 0f)
			{
				Instance.totalDamage += data.damageData.damage;
				TargetType type = ((IFollowable)data.target).Type;
				if ((type & 1) != 0 || (type & 2) != 0)
				{
					Instance.damageQueue.Enqueue((Time.time, data.damageData.damage));
				}
				if (((DamageCallbackData)(ref data)).KilledTarget)
				{
					Instance.totalKills++;
					if (typeof(EnemyCore).IsAssignableFrom(((object)data.target).GetType()))
					{
						Instance.totalCoresKilled++;
					}
				}
			}
			return true;
		}
	}

	internal class MissionPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(MissionManager), "SpawnHUD")]
		private static void MissionStart()
		{
			if (Instance != null)
			{
				Instance.totalDamage = 0f;
				Instance.totalKills = 0;
				Instance.totalCoresKilled = 0;
				Instance.damageQueue.Clear();
				Instance.missionStartTime = Time.time;
			}
		}
	}

	private ConfigEntry<bool> enableDamageMeterHUD;

	private ConfigEntry<float> dpsWindowSeconds;

	private ConfigEntry<float> carnometerAnchorX;

	private ConfigEntry<float> carnometerAnchorY;

	private ConfigColor valueColor;

	private HudHandle hud;

	public Queue<(float time, float damage)> damageQueue = new Queue<(float, float)>();

	public float totalDamage;

	public int totalKills;

	public int totalCoresKilled;

	public float missionStartTime;

	private readonly ConfigFile configFile;

	private readonly Harmony harmony;

	public static CarnometerMod Instance { get; private set; }

	public bool IsActive
	{
		get
		{
			if (hud != null)
			{
				return hud.IsActive;
			}
			return false;
		}
	}

	public Vector2 GetSize
	{
		get
		{
			//IL_0010: 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)
			HudHandle obj = hud;
			if (obj == null)
			{
				return Vector2.zero;
			}
			return obj.Size;
		}
	}

	public CarnometerMod(ConfigFile configFile, Harmony harmony)
	{
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		this.configFile = configFile;
		this.harmony = harmony;
		Instance = this;
		enableDamageMeterHUD = configFile.Bind<bool>("General", "EnableDamageMeterHUD", true, "Enable or disable the damage meter functionality.");
		enableDamageMeterHUD.SettingChanged += OnEnableDamageMeterHUDChanged;
		dpsWindowSeconds = configFile.Bind<float>("General", "DPSWindowSeconds", 5f, "Time window (in seconds) for calculating DPS. Higher values smooth out spikes.");
		carnometerAnchorX = configFile.Bind<float>("HUD Positioning", "CarnometerAnchorX", 0.294803f, "X anchor position for Carnometer (0-1).");
		carnometerAnchorY = configFile.Bind<float>("HUD Positioning", "CarnometerAnchorY", 0.285045f, "Y anchor position for Carnometer (0-1).");
		carnometerAnchorX.SettingChanged += OnAnchorChanged;
		carnometerAnchorY.SettingChanged += OnAnchorChanged;
		valueColor = ConfigColor.Bind(configFile, "Colors", "ValueColor", UIColors.Rose, "Rich-text value color for damage/kill meters (hex RRGGBB or #RRGGBB).");
		harmony.PatchAll(typeof(DPSPatches));
		harmony.PatchAll(typeof(MissionPatches));
		missionStartTime = Time.time;
	}

	public void UpdateHudVisibility()
	{
		if (hud != null)
		{
			hud.SetActive(enableDamageMeterHUD.Value);
		}
	}

	private void OnEnableDamageMeterHUDChanged(object sender, EventArgs e)
	{
		if (!enableDamageMeterHUD.Value && hud != null)
		{
			DestroyHud();
		}
		UpdateHudVisibility();
	}

	private void OnAnchorChanged(object sender, EventArgs e)
	{
		UpdateAnchors();
	}

	private void UpdateAnchors()
	{
		if (hud != null)
		{
			hud.SetAnchor(carnometerAnchorX.Value, carnometerAnchorY.Value);
		}
	}

	private void CreateDamageMeterHUD()
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		if (hud == null)
		{
			hud = HudBuilder.Create("DamageMeterHUD").ParentToReticle(true).Anchor(carnometerAnchorX.Value, carnometerAnchorY.Value)
				.Pivot(new Vector2(0f, 1f))
				.Size(320f, 100f, true)
				.AddLines(4, -1f, (TextAlignmentOptions)513)
				.Build();
			if (hud != null)
			{
				HudRepositionClient.Register("sparroh.carnometer", "Carnometer", hud.Rect, carnometerAnchorX, carnometerAnchorY);
				UpdateHudVisibility();
			}
		}
	}

	private void DestroyHud()
	{
		HudRepositionClient.Unregister("sparroh.carnometer");
		if (hud != null)
		{
			hud.Destroy();
			hud = null;
		}
	}

	public void Update()
	{
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: 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_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: 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)
		if (!enableDamageMeterHUD.Value || (Object)(object)Player.LocalPlayer == (Object)null)
		{
			return;
		}
		if (hud == null)
		{
			CreateDamageMeterHUD();
		}
		else
		{
			if (hud.Lines == null || hud.Lines.Length < 4)
			{
				return;
			}
			float time = Time.time;
			float value = dpsWindowSeconds.Value;
			while (damageQueue.Count > 0 && damageQueue.Peek().time < time - value)
			{
				damageQueue.Dequeue();
			}
			float num = 0f;
			foreach (var item in damageQueue)
			{
				num += item.damage;
			}
			float num2 = ((damageQueue.Count > 0) ? (num / value) : 0f);
			float num3 = Time.time - missionStartTime;
			float num4 = ((num3 > 0f) ? (totalDamage / num3) : 0f);
			float num5 = ((num3 > 0f) ? ((float)totalKills / num3) : 0f);
			float num6 = ((num3 > 0f) ? ((float)totalCoresKilled / num3) : 0f);
			Color value2 = valueColor.Value;
			hud.Lines[0].SetRichWithRate("Total Damage", totalDamage, num4, value2, "F0", "F1");
			hud.Lines[1].Text = RichText.LabeledWithRate($"Last {value:F0}sec Damage", num, num2, value2, "F0", "F1");
			hud.Lines[2].SetRichWithRate("Targets Killed", (float)totalKills, num5, value2, "F0", "F1");
			hud.Lines[3].SetRichWithRate("Cores Killed", (float)totalCoresKilled, num6, value2, "F0", "F1");
		}
	}

	public void OnDestroy()
	{
		DestroyHud();
	}
}
public static class HudRepositionClient
{
	private const string ApiTypeName = "HudRepositionAPI";

	private static Type _apiType;

	private static MethodInfo _register;

	private static MethodInfo _unregister;

	private static bool _available;

	public static bool IsAvailable
	{
		get
		{
			EnsureResolved();
			return _available;
		}
	}

	public static void Register(string id, string displayName, RectTransform rect, ConfigEntry<float> anchorX, ConfigEntry<float> anchorY)
	{
		if (!_available)
		{
			EnsureResolved(force: true);
		}
		if (!_available || (Object)(object)rect == (Object)null || anchorX == null || anchorY == null)
		{
			return;
		}
		try
		{
			_register.Invoke(null, new object[5] { id, displayName, rect, anchorX, anchorY });
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[HudRepositionClient] Register failed: " + (ex.InnerException?.Message ?? ex.Message)));
		}
	}

	public static void Unregister(string id)
	{
		if (!_available)
		{
			EnsureResolved(force: true);
		}
		if (!_available || string.IsNullOrEmpty(id))
		{
			return;
		}
		try
		{
			_unregister.Invoke(null, new object[1] { id });
		}
		catch (Exception)
		{
		}
	}

	private static void EnsureResolved(bool force = false)
	{
		if (_available && !force)
		{
			return;
		}
		_apiType = null;
		_register = null;
		_unregister = null;
		_available = false;
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly in assemblies)
		{
			try
			{
				Type type = assembly.GetType("HudRepositionAPI", throwOnError: false);
				if (type != null)
				{
					_apiType = type;
					break;
				}
			}
			catch
			{
			}
		}
		if (_apiType == null)
		{
			return;
		}
		MethodInfo[] methods = _apiType.GetMethods(BindingFlags.Static | BindingFlags.Public);
		foreach (MethodInfo methodInfo in methods)
		{
			ParameterInfo[] parameters = methodInfo.GetParameters();
			if (methodInfo.Name == "Register" && parameters.Length == 5 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string) && typeof(RectTransform).IsAssignableFrom(parameters[2].ParameterType))
			{
				_register = methodInfo;
			}
			else if (methodInfo.Name == "Unregister" && parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
			{
				_unregister = methodInfo;
			}
		}
		_available = _register != null && _unregister != null;
	}
}
[BepInPlugin("sparroh.carnometer", "Carnometer", "2.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class SparrohPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.carnometer";

	public const string PluginName = "Carnometer";

	public const string PluginVersion = "2.0.0";

	internal static ManualLogSource Logger;

	private Harmony harmony;

	private CarnometerMod carnometer;

	private void Awake()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		Logger = ((BaseUnityPlugin)this).Logger;
		try
		{
			harmony = new Harmony("sparroh.carnometer");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Failed to create Harmony instance: " + ex.Message));
			return;
		}
		ConfigFile configFile = ((BaseUnityPlugin)this).Config;
		try
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.carnometer.cfg");
			fileSystemWatcher.Changed += delegate
			{
				configFile.Reload();
			};
			fileSystemWatcher.EnableRaisingEvents = true;
		}
		catch (Exception ex2)
		{
			Logger.LogWarning((object)("Failed to set up config watcher: " + ex2.Message));
		}
		try
		{
			carnometer = new CarnometerMod(configFile, harmony);
		}
		catch (Exception ex3)
		{
			Logger.LogError((object)("Failed to initialize Carnometer: " + ex3.Message));
		}
		try
		{
			harmony.PatchAll();
		}
		catch (Exception ex4)
		{
			Logger.LogError((object)("Failed to apply Harmony patches: " + ex4.Message));
		}
		Logger.LogInfo((object)"Carnometer loaded successfully.");
	}

	private void Update()
	{
		try
		{
			if (carnometer != null)
			{
				carnometer.UpdateHudVisibility();
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error in Carnometer.UpdateHudVisibility(): " + ex.Message));
		}
		try
		{
			if (carnometer != null)
			{
				carnometer.Update();
			}
		}
		catch (Exception ex2)
		{
			Logger.LogError((object)("Error in Carnometer.Update(): " + ex2.Message));
		}
	}

	private void OnDestroy()
	{
		try
		{
			if (carnometer != null)
			{
				carnometer.OnDestroy();
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error in Carnometer.OnDestroy(): " + ex.Message));
		}
		try
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
		catch (Exception ex2)
		{
			Logger.LogError((object)("Error unpatching Harmony: " + ex2.Message));
		}
	}
}
namespace Carnometer
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Carnometer";

		public const string PLUGIN_NAME = "Carnometer";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}