Decompiled source of CruiserScrapCounter v1.0.1

CruiserScrapCounter.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using UnityEngine;

[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("CruiserScrapCounter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("CruiserScrapCounter")]
[assembly: AssemblyTitle("CruiserScrapCounter")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace CruiserScrapCounter;

[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
internal static class CruiserScanPatch
{
	private const string ValueCounterPath = "/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/ValueCounter";

	private static readonly float[] LineHeights = new float[2] { -70f, -90f };

	private static readonly GameObject[] _counters = (GameObject[])(object)new GameObject[2];

	private static readonly TMP_Text[] _texts = (TMP_Text[])(object)new TMP_Text[2];

	private static float _displayTimeLeft;

	public static void Postfix()
	{
		try
		{
			GameNetworkManager instance = GameNetworkManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			PlayerControllerB localPlayerController = instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null || localPlayerController.isInsideFactory)
			{
				return;
			}
			StartOfRound instance2 = StartOfRound.Instance;
			if (!((Object)(object)instance2 == (Object)null) && !instance2.inShipPhase && LootTracker.ShipHasLanded() && !LootTracker.IsDisabledMoon())
			{
				Component val = (Component)(object)Object.FindObjectOfType<VehicleController>();
				if (!((Object)(object)val == (Object)null))
				{
					LootTracker.Count(val, out var cruiserValue, out var cruiserCount, out var moonValue, out var moonCount);
					Show(FormatText(cruiserValue, moonValue, cruiserCount, moonCount), instance);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Scan handler failed: " + ex));
		}
	}

	private static string FormatText(int cruiserValue, int moonValue, int cruiserCount, int moonCount)
	{
		try
		{
			return string.Format(Plugin.Format.Value.Replace("\\n", "\n"), cruiserValue, moonValue, cruiserCount, moonCount);
		}
		catch (FormatException)
		{
			return "Cruiser: " + cruiserValue + "/" + moonValue + "\nCount:   " + cruiserCount + "/" + moonCount;
		}
	}

	private static void Show(string message, GameNetworkManager gnm)
	{
		string[] array = message.Split(new char[1] { '\n' }, 2);
		for (int i = 0; i < 2; i++)
		{
			if ((Object)(object)_counters[i] == (Object)null && !CopyValueCounter(i))
			{
				return;
			}
			_texts[i].text = ((i < array.Length) ? array[i] : "");
		}
		bool activeSelf = _counters[0].activeSelf;
		_displayTimeLeft = ((Plugin.DisplayTime.Value > 0f) ? Plugin.DisplayTime.Value : 5f);
		if (!activeSelf)
		{
			((MonoBehaviour)gnm).StartCoroutine(DisplayCoroutine(array.Length > 1));
		}
	}

	private static IEnumerator DisplayCoroutine(bool twoLines)
	{
		_counters[0].SetActive(true);
		_counters[1].SetActive(twoLines);
		while (_displayTimeLeft > 0f)
		{
			float displayTimeLeft = _displayTimeLeft;
			_displayTimeLeft = 0f;
			yield return (object)new WaitForSeconds(displayTimeLeft);
		}
		for (int i = 0; i < 2; i++)
		{
			if ((Object)(object)_counters[i] != (Object)null)
			{
				_counters[i].SetActive(false);
			}
		}
	}

	private static bool CopyValueCounter(int index)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/ValueCounter");
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogError((object)"Failed to find ValueCounter object to copy!");
			return false;
		}
		GameObject val2 = Object.Instantiate<GameObject>(val, val.transform.parent, false);
		val2.transform.Translate(0f, 1f, 0f);
		Vector3 localPosition = val2.transform.localPosition;
		val2.transform.localPosition = new Vector3(localPosition.x + 50f + Plugin.OffsetX.Value, LineHeights[index] + Plugin.OffsetY.Value, localPosition.z);
		TMP_Text componentInChildren = val2.GetComponentInChildren<TMP_Text>();
		if ((Object)(object)componentInChildren == (Object)null)
		{
			Plugin.Log.LogError((object)"ValueCounter copy has no text component.");
			return false;
		}
		RectTransform rectTransform = componentInChildren.rectTransform;
		rectTransform.anchoredPosition += new Vector2(200f, 0f);
		rectTransform.sizeDelta = new Vector2(600f, rectTransform.sizeDelta.y);
		_counters[index] = val2;
		_texts[index] = componentInChildren;
		return true;
	}
}
[HarmonyPatch(typeof(StartOfRound), "openingDoorsSequence")]
internal static class LandingPatch
{
	private static void Postfix()
	{
		try
		{
			if (!LootTracker.IsDisabledMoon())
			{
				LootTracker.RecordOldLoot();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Recording old loot failed: " + ex));
		}
	}
}
internal static class LootTracker
{
	private static readonly HashSet<GrabbableObject> OldLoot = new HashSet<GrabbableObject>();

	private static readonly FieldInfo DeactivatedField = AccessTools.Field(typeof(GrabbableObject), "deactivated");

	private static int _seed;

	private static object GetField(object obj, string name)
	{
		if (obj == null)
		{
			return null;
		}
		FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), name);
		if (!(fieldInfo != null))
		{
			return null;
		}
		return fieldInfo.GetValue(obj);
	}

	internal static bool IsDisabledMoon()
	{
		StartOfRound instance = StartOfRound.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			return false;
		}
		object field = GetField(instance, "currentLevel");
		if (field == null)
		{
			return false;
		}
		object field2 = GetField(field, "levelID");
		if (field2 is int && (int)field2 == 3)
		{
			return true;
		}
		string text = string.Concat(GetField(field, "PlanetName"), " ", GetField(field, "sceneName"));
		if (text.IndexOf("Gordion", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		string[] array = Plugin.DisabledMoons.Value.Split(',');
		for (int i = 0; i < array.Length; i++)
		{
			string text2 = array[i].Trim();
			if (text2.Length > 0 && text.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	internal static bool ShipHasLanded()
	{
		object field = GetField(StartOfRound.Instance, "shipHasLanded");
		if (field is bool)
		{
			return (bool)field;
		}
		return true;
	}

	private static bool IsActiveScrap(GrabbableObject g)
	{
		if ((Object)(object)g == (Object)null || (Object)(object)g.itemProperties == (Object)null || !g.itemProperties.isScrap)
		{
			return false;
		}
		if (g.itemUsedUp)
		{
			return false;
		}
		if (DeactivatedField != null)
		{
			object value = DeactivatedField.GetValue(g);
			if (value is bool && (bool)value)
			{
				return false;
			}
		}
		return true;
	}

	private static bool IsInCruiser(GrabbableObject g, Component cruiser)
	{
		if ((Object)(object)cruiser != (Object)null)
		{
			return ((Component)g).transform.IsChildOf(cruiser.transform);
		}
		return false;
	}

	private static bool IsAboardShip(GrabbableObject g, Component cruiser)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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)
		if (g.isInShipRoom || IsInCruiser(g, cruiser))
		{
			return true;
		}
		StartOfRound instance = StartOfRound.Instance;
		if ((Object)(object)instance != (Object)null && (Object)(object)instance.shipInnerRoomBounds != (Object)null)
		{
			Bounds bounds = instance.shipInnerRoomBounds.bounds;
			return ((Bounds)(ref bounds)).Contains(((Component)g).transform.position);
		}
		return false;
	}

	internal static void RecordOldLoot()
	{
		OldLoot.Clear();
		_seed = StartOfRound.Instance.randomMapSeed;
		Component cruiser = (Component)(object)Object.FindObjectOfType<VehicleController>();
		GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
		foreach (GrabbableObject val in array)
		{
			if (IsActiveScrap(val) && IsAboardShip(val, cruiser))
			{
				OldLoot.Add(val);
			}
		}
		Plugin.Log.LogInfo((object)("Ignoring " + OldLoot.Count + " items that were already aboard when landing."));
	}

	internal static void Count(Component cruiser, out int cruiserValue, out int cruiserCount, out int moonValue, out int moonCount)
	{
		cruiserValue = 0;
		cruiserCount = 0;
		moonValue = 0;
		moonCount = 0;
		int randomMapSeed = StartOfRound.Instance.randomMapSeed;
		if (randomMapSeed != _seed)
		{
			OldLoot.Clear();
			_seed = randomMapSeed;
		}
		GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
		foreach (GrabbableObject val in array)
		{
			if (IsActiveScrap(val) && !val.scrapPersistedThroughRounds && !OldLoot.Contains(val))
			{
				moonValue += val.scrapValue;
				moonCount++;
				if (IsInCruiser(val, cruiser))
				{
					cruiserValue += val.scrapValue;
					cruiserCount++;
				}
			}
		}
	}
}
public static class MyPluginInfo
{
	public const string PLUGIN_GUID = "CruiserScrapCounter";

	public const string PLUGIN_NAME = "CruiserScrapCounter";

	public const string PLUGIN_VERSION = "1.0.1";
}
[BepInPlugin("CruiserScrapCounter", "CruiserScrapCounter", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	internal static ConfigEntry<float> DisplayTime;

	internal static ConfigEntry<string> Format;

	internal static ConfigEntry<float> OffsetX;

	internal static ConfigEntry<float> OffsetY;

	internal static ConfigEntry<string> DisabledMoons;

	private const string DefaultFormat = "Cruiser: {0}/{1}\nCount:   {2}/{3}";

	private void Awake()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Expected O, but got Unknown
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Expected O, but got Unknown
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Expected O, but got Unknown
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Expected O, but got Unknown
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		DisplayTime = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DisplayTime", 5f, new ConfigDescription("How long the counter stays on screen after a scan, in seconds.", (AcceptableValueBase)null, Array.Empty<object>()));
		Format = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Format", "Cruiser: {0}/{1}\nCount:   {2}/{3}", new ConfigDescription("Counter text. {0} = Cruiser value, {1} = value of all of today's loot on the moon, {2} = Cruiser item count, {3} = item count of all of today's loot on the moon. Use \\n for a new line. One-line example: Cruiser: {0}/{1} {2}/{3}", (AcceptableValueBase)null, Array.Empty<object>()));
		OffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "OffsetX", 0f, new ConfigDescription("Moves the counter horizontally from its default spot (the QUOTA/OVERTIME rows). Negative = left, positive = right.", (AcceptableValueBase)null, Array.Empty<object>()));
		OffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "OffsetY", 0f, new ConfigDescription("Moves the counter vertically. Negative = down, positive = up.", (AcceptableValueBase)null, Array.Empty<object>()));
		DisabledMoons = ((BaseUnityPlugin)this).Config.Bind<string>("General", "DisabledMoons", "Galetry", new ConfigDescription("Comma-separated moon names where the counter stays hidden (matched anywhere in the moon name). The Company building is always disabled.", (AcceptableValueBase)null, Array.Empty<object>()));
		ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "ConfigVersion", 0, new ConfigDescription("Used to apply new defaults once after an update. Don't change.", (AcceptableValueBase)null, Array.Empty<object>()));
		if (val.Value < 2)
		{
			Format.Value = "Cruiser: {0}/{1}\nCount:   {2}/{3}";
		}
		if (val.Value < 5)
		{
			OffsetX.Value = 0f;
			OffsetY.Value = 0f;
			val.Value = 5;
			((BaseUnityPlugin)this).Config.Save();
		}
		new Harmony("CruiserScrapCounter").PatchAll();
		Log.LogInfo((object)"CruiserScrapCounter v1.0.1 has loaded!");
	}
}