Decompiled source of LaserClearing v1.0.6

LaserClearing.dll

Decompiled 2 months ago
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("LaserClearing")]
[assembly: AssemblyProduct("starfi5h.plugin.LaserClearing")]
[assembly: AssemblyFileVersion("1.0.6")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.6.0")]
[module: UnverifiableCode]
namespace LaserClearing;

public class LocalLaser_Patch
{
	public static bool Enable = true;

	public static bool EnableLoot = true;

	public static int RequiredSpace = 5;

	public static int MaxLaserCount = 3;

	public static float Range = 40f;

	public static int MiningTick = 60;

	public static double MiningPower = 6000.0;

	public static bool DropOnly = true;

	public static bool SpaceCapsule = false;

	public static bool EnableDestructionSFX = false;

	public static float ScaleWithDroneCount = 0f;

	public static float ScaleWithMiningSpeed = 0f;

	private static readonly Dictionary<int, bool> checkVeges = new Dictionary<int, bool>();

	private static readonly List<int> laserIds = new List<int>();

	private static int factoryIndex = -1;

	private static int maxLaserCount = 3;

	private static int tickToClear = 60;

	private static int checkIntervalTick = 10;

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameMain), "Begin")]
	[HarmonyPatch(typeof(GameHistoryData), "NotifyTechUnlock")]
	private static void SetParameters()
	{
		maxLaserCount = MaxLaserCount;
		if (ScaleWithDroneCount > 0f)
		{
			maxLaserCount = (int)((float)(maxLaserCount * GameMain.mainPlayer.mecha.constructionModule.droneCount) * ScaleWithDroneCount);
		}
		maxLaserCount = ((maxLaserCount <= 0) ? 1 : maxLaserCount);
		tickToClear = MiningTick;
		if (ScaleWithMiningSpeed > 0f)
		{
			tickToClear = (int)((float)tickToClear / (1f + (GameMain.history.miningSpeedScale - 1f) * ScaleWithMiningSpeed));
		}
		tickToClear = ((tickToClear <= 0) ? 1 : tickToClear);
		checkIntervalTick = tickToClear / (maxLaserCount * 2);
		checkIntervalTick = ((checkIntervalTick <= 0) ? 1 : checkIntervalTick);
		Plugin.Log.LogDebug((object)$"maxLaserCount={maxLaserCount} tickToClear={tickToClear}");
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(PlayerAction_Mine), "GameTick")]
	private static void GameTick(PlayerAction_Mine __instance)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		if (!Enable)
		{
			return;
		}
		PlanetFactory factory = ((PlayerAction)__instance).player.factory;
		if (factory == null)
		{
			return;
		}
		if (factoryIndex != factory.index)
		{
			ClearAll();
		}
		factoryIndex = factory.index;
		Mecha mecha = ((PlayerAction)__instance).player.mecha;
		Vector3 skillCastRightL = mecha.skillCastRightL;
		if (laserIds.Count < maxLaserCount && GameMain.gameTick % checkIntervalTick == 0L)
		{
			if (CheckPlayerInventorySpace())
			{
				UI_Patch.UpdateButtonStatus(UI_Patch.ButtonStatus.Normal);
				int closestVegeId = GetClosestVegeId(factory, skillCastRightL, Range);
				if (closestVegeId != 0)
				{
					laserIds.Add(StartLaser(factory, closestVegeId, skillCastRightL));
					checkVeges[closestVegeId] = false;
				}
			}
			else
			{
				UI_Patch.UpdateButtonStatus(UI_Patch.ButtonStatus.NotEnoughSpace);
			}
		}
		double num2 = default(double);
		float num3 = default(float);
		for (int num = laserIds.Count - 1; num >= 0; num--)
		{
			if (ContinueLaser(factory, laserIds[num], skillCastRightL, out var vegeId))
			{
				_ = ref factory.vegePool[vegeId];
				mecha.QueryEnergy(MiningPower, ref num2, ref num3);
				mecha.coreEnergy -= num2;
				mecha.MarkEnergyChange(5, 0.0 - num2);
			}
			else
			{
				checkVeges.Remove(vegeId);
				laserIds.RemoveAt(num);
			}
		}
	}

	private static bool CheckPlayerInventorySpace()
	{
		if (!EnableLoot)
		{
			return true;
		}
		GRID[] grids = GameMain.mainPlayer.package.grids;
		int num = 0;
		for (int num2 = GameMain.mainPlayer.package.size - 1; num2 >= 0; num2--)
		{
			if (grids[num2].count == 0 && grids[num2].filter == 0)
			{
				num++;
			}
			if (num >= RequiredSpace)
			{
				return true;
			}
		}
		return false;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameMain), "Begin")]
	[HarmonyPatch(typeof(GameMain), "End")]
	public static void ClearAll()
	{
		checkVeges.Clear();
		laserIds.Clear();
		StopAll();
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(PlanetFactory), "KillVegeFinally")]
	public static bool KillVegeFinally_Prefix(PlanetFactory __instance, int id)
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		if (!Enable || __instance.index != factoryIndex)
		{
			return true;
		}
		ref VegeData reference = ref __instance.vegePool[id];
		VegeProto val = ((ProtoSet<VegeProto>)(object)LDB.veges).Select((int)reference.protoId);
		if (val != null)
		{
			VFEffectEmitter.Emit(val.MiningEffect, __instance.vegePool[id].pos, __instance.vegePool[id].rot);
			if (EnableDestructionSFX)
			{
				VFAudio.Create(val.MiningAudio, (Transform)null, __instance.vegePool[id].pos, true, 1, -1, -1L);
			}
			if (EnableLoot)
			{
				GetVegLoot(__instance, in reference, val);
			}
		}
		__instance.RemoveVegeWithComponents(id);
		return false;
	}

	private static void GetVegLoot(PlanetFactory factory, in VegeData vegeData, VegeProto vegeProto)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		DotNet35Random val = new DotNet35Random(vegeData.id + ((factory.planet.seed & 0x3FFF) << 14));
		int num = 0;
		for (int i = 0; i < vegeProto.MiningItem.Length; i++)
		{
			if (!((float)val.NextDouble() < vegeProto.MiningChance[i]))
			{
				continue;
			}
			int num2 = vegeProto.MiningItem[i];
			int num3 = (int)((float)vegeProto.MiningCount[i] * (vegeData.scl.y * vegeData.scl.y) + 0.5f);
			if (num3 > 0 && ((ProtoSet<ItemProto>)(object)LDB.items).Select(num2) != null)
			{
				int num4 = GameMain.mainPlayer.TryAddItemToPackage(num2, num3, 0, true, 0, false);
				GameMain.statistics.production.factoryStatPool[factory.index].AddProductionToTotalArray(num2, num3);
				GameMain.data.history.AddFeatureValue(2150000 + num2, num3);
				if (num4 > 0)
				{
					UIItemup.Up(num2, num4);
					Vector3 pos = vegeData.pos;
					Vector3 pos2 = vegeData.pos;
					UIRealtimeTip.PopupItemGet(num2, num4, pos + ((Vector3)(ref pos2)).normalized, num++);
				}
			}
		}
	}

	private static int StartLaser(PlanetFactory factory, int vegeId, Vector3 beginPos)
	{
		//IL_0042: 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_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		ref LocalLaserContinuous reference = ref GameMain.data.spaceSector.skillSystem.localLaserContinuous.Add();
		ref VegeData reference2 = ref factory.vegePool[vegeId];
		((LocalLaserContinuous)(ref reference)).Start();
		reference.astroId = factory.planetId;
		reference.hitIndex = 4;
		reference.beginPos = reference2.pos + ((Vector3)(ref reference2.pos)).normalized * SkillSystem.RoughHeightByModelIndex[reference2.modelIndex] * 0.5f;
		reference.endPos = beginPos;
		reference.target.type = (ETargetType)1;
		reference.target.id = vegeId;
		int num = SkillSystem.HpMaxByModelIndex[reference2.modelIndex];
		int num2 = SkillSystem.HpRecoverByModelIndex[reference2.modelIndex];
		reference.damage = (int)((float)(num / tickToClear + num2) / 1f + 1f);
		reference.damageScale = 1f;
		reference.mask = (ETargetTypeMask)127;
		reference.sfxId = GameMain.data.spaceSector.skillSystem.audio.AddPlanetAudio(123, 0f, reference.astroId, reference.beginPos).id;
		return reference.id;
	}

	private static bool ContinueLaser(PlanetFactory factory, int laserId, Vector3 beginPos, out int vegeId)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_002d: 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_0065: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		ref LocalLaserContinuous reference = ref GameMain.data.spaceSector.skillSystem.localLaserContinuous.buffer[laserId];
		reference.endPos = beginPos;
		SkillTargetLocal target = reference.target;
		vegeId = target.id;
		ref VegeData reference2 = ref factory.vegePool[vegeId];
		if (reference2.id == 0)
		{
			((LocalLaserContinuous)(ref reference)).Stop(GameMain.data.spaceSector.skillSystem);
			return false;
		}
		reference.beginPos = reference2.pos + ((Vector3)(ref reference2.pos)).normalized * SkillSystem.RoughHeightByModelIndex[reference2.modelIndex] * 0.5f;
		if (Vector3.SqrMagnitude(reference.endPos - beginPos) > Range * Range)
		{
			((LocalLaserContinuous)(ref reference)).Stop(GameMain.data.spaceSector.skillSystem);
			return false;
		}
		return true;
	}

	private static void StopAll()
	{
		ref DataPoolRenderer<LocalLaserContinuous> localLaserContinuous = ref GameMain.data.spaceSector.skillSystem.localLaserContinuous;
		for (int i = 1; i < localLaserContinuous.cursor; i++)
		{
			if (localLaserContinuous.buffer[i].id > 0)
			{
				((LocalLaserContinuous)(ref localLaserContinuous.buffer[i])).Stop(GameMain.data.spaceSector.skillSystem);
			}
		}
	}

	private static int GetClosestVegeId(PlanetFactory factory, Vector3 centerPos, float range)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: 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_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: 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)
		int result = 0;
		VegeData[] vegePool = factory.vegePool;
		float num = range * range;
		HashSystem hashSystemStatic = factory.hashSystemStatic;
		hashSystemStatic.ClearActiveBuckets();
		int[] hashPool = hashSystemStatic.hashPool;
		int[] bucketOffsets = hashSystemStatic.bucketOffsets;
		int[] bucketCursors = hashSystemStatic.bucketCursors;
		hashSystemStatic.GetBucketIdxesInArea(centerPos, range);
		int[] activeBuckets = hashSystemStatic.activeBuckets;
		int activeBucketsCount = hashSystemStatic.activeBucketsCount;
		for (int i = 0; i < activeBucketsCount; i++)
		{
			int num2 = activeBuckets[i];
			int num3 = bucketOffsets[num2];
			int num4 = num3 + bucketCursors[num2];
			for (int j = num3; j < num4; j++)
			{
				int num5 = hashPool[j];
				if (num5 == 0 || num5 >> 28 != 1)
				{
					continue;
				}
				int num6 = num5 & 0xFFFFFFF;
				if (num6 == 0)
				{
					continue;
				}
				if (checkVeges.TryGetValue(num6, out var value))
				{
					if (value)
					{
						float num7 = Vector3.SqrMagnitude(vegePool[num6].pos - centerPos);
						if (num7 < num)
						{
							result = num6;
							num = num7;
						}
					}
					continue;
				}
				ref VegeData reference = ref vegePool[num6];
				VegeProto val = ((ProtoSet<VegeProto>)(object)LDB.veges).Select((int)reference.protoId);
				if (reference.id == num6 && val != null)
				{
					if (DropOnly && val.MiningItem.Length == 0)
					{
						checkVeges[num6] = false;
						continue;
					}
					if (reference.protoId == 9999 && !SpaceCapsule)
					{
						checkVeges[num6] = false;
						continue;
					}
					float num8 = Vector3.SqrMagnitude(reference.pos - centerPos);
					if (num8 < num)
					{
						result = num6;
						num = num8;
					}
					checkVeges[num6] = true;
				}
				else
				{
					checkVeges[num6] = false;
				}
			}
		}
		hashSystemStatic.ClearActiveBuckets();
		return result;
	}
}
[BepInPlugin("starfi5h.plugin.LaserClearing", "LaserClearing", "1.0.6")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "starfi5h.plugin.LaserClearing";

	public const string NAME = "LaserClearing";

	public const string VERSION = "1.0.6";

	public static Plugin Instance;

	public static ManualLogSource Log;

	private static Harmony harmony;

	public void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		harmony = new Harmony("starfi5h.plugin.LaserClearing");
		LoadConfigs();
		harmony.PatchAll(typeof(LocalLaser_Patch));
		harmony.PatchAll(typeof(UI_Patch));
	}

	public static void LoadConfigs()
	{
		LocalLaser_Patch.Enable = ((BaseUnityPlugin)Instance).Config.Bind<bool>("General", "Enable", false, "Enable LaserClearing when starting the game\n进入游戏时启用激光").Value;
		LocalLaser_Patch.EnableLoot = ((BaseUnityPlugin)Instance).Config.Bind<bool>("General", "EnableLoot", true, "Get drops from destroying trees and stones when enable laser\n启用激光时,破坏树木/石头时会获取掉落物").Value;
		LocalLaser_Patch.RequiredSpace = ((BaseUnityPlugin)Instance).Config.Bind<int>("General", "RequiredSpace", 5, "Stop laser when there is not enough space in inventory\n物品栏保留空位,当空间不足时停止激光").Value;
		LocalLaser_Patch.MaxLaserCount = ((BaseUnityPlugin)Instance).Config.Bind<int>("Laser", "MaxCount", 3, "Maximum count of laser\n激光最大数量").Value;
		LocalLaser_Patch.Range = ((BaseUnityPlugin)Instance).Config.Bind<float>("Laser", "Range", 40f, "Maximum range of laser\n激光最远距离").Value;
		LocalLaser_Patch.MiningTick = ((BaseUnityPlugin)Instance).Config.Bind<int>("Laser", "MiningTick", 90, "Time to mine an object (tick)\n开采所需时间").Value;
		LocalLaser_Patch.MiningPower = ((BaseUnityPlugin)Instance).Config.Bind<float>("Laser", "MiningPower", 480f, "Power consumption per laser (kW)\n激光耗能").Value / 60f * 1000f;
		LocalLaser_Patch.DropOnly = ((BaseUnityPlugin)Instance).Config.Bind<bool>("Target", "DropOnly", true, "Targets only objects with available drop\n只清除有掉落物的植被").Value;
		LocalLaser_Patch.SpaceCapsule = ((BaseUnityPlugin)Instance).Config.Bind<bool>("Target", "SpaceCapsule", false, "Targets space capsule\n清除飞行仓").Value;
		LocalLaser_Patch.EnableDestructionSFX = ((BaseUnityPlugin)Instance).Config.Bind<bool>("Other", "EnableDestructionSFX", false, "Play sounds when trees and stones get clear by laser\n激光清除树木/石头时播放音效").Value;
		LocalLaser_Patch.ScaleWithDroneCount = ((BaseUnityPlugin)Instance).Config.Bind<float>("Other", "ScaleWithDroneCount", 0f, "Scale laser count with (this ratio * consturction drone count)\n>0时, 使激光数量随(科技无人机数量*此值)增长").Value;
		LocalLaser_Patch.ScaleWithMiningSpeed = ((BaseUnityPlugin)Instance).Config.Bind<float>("Other", "ScaleWithMiningSpeed", 0f, "Scale mining tick with (this ratio * mining speed boost)\n>0时, 使激光效率随(科技矿物采集速度*此值)增长").Value;
		((BaseUnityPlugin)Instance).Logger.LogDebug((object)$"LoadConfigs drop:{LocalLaser_Patch.DropOnly}");
	}
}
public class UI_Patch
{
	public enum ButtonStatus
	{
		None,
		Normal,
		NotEnoughSpace
	}

	private static UIButton enableButton;

	private static ButtonStatus buttonStatus;

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIMechaEnergy), "_OnCreate")]
	public static void OnEnableChanged()
	{
		//IL_004d: 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)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)enableButton == (Object)null)
		{
			UIButton infiniteEnergyButton = UIRoot.instance.uiGame.energyBar.infiniteEnergyButton;
			GameObject obj = Object.Instantiate<GameObject>(((Component)infiniteEnergyButton).gameObject, ((Component)infiniteEnergyButton).transform.parent);
			((Object)obj).name = "[LaserClearing] Toggle";
			Transform transform = obj.transform;
			transform.localPosition += new Vector3(30f, 0f, 0f);
			obj.SetActive(true);
			Image component = ((Component)obj.transform.Find("icon")).GetComponent<Image>();
			Image val = UIRoot.instance.uiGame.sandboxMenu.categoryIcons[3];
			component.sprite = val.sprite;
			enableButton = obj.GetComponent<UIButton>();
			enableButton.onClick += EnableButton_onClick;
			enableButton.tips.corner = 8;
			enableButton.tips.tipTitle = "LaserClearing";
			enableButton.transitions[0].highlightColorOverride = new Color(0.6f, 0.6f, 0.6f, 0.1f);
			UpdateButtonStatus(ButtonStatus.Normal);
		}
		enableButton.highlighted = LocalLaser_Patch.Enable;
	}

	public static void UpdateButtonStatus(ButtonStatus status)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		if (buttonStatus != status)
		{
			switch (status)
			{
			case ButtonStatus.Normal:
				enableButton.tips.tipText = "Enable/Disable mecha laser to clear trees and stones";
				enableButton.transitions[1].highlightColorOverride = new Color(0.6f, 0.6f, 1f, 1f);
				break;
			case ButtonStatus.NotEnoughSpace:
				enableButton.tips.tipText = "Not enoguh space in inventory! Requrie: " + LocalLaser_Patch.RequiredSpace;
				enableButton.transitions[1].highlightColorOverride = new Color(1f, 0.4f, 0.4f, 1f);
				break;
			}
			enableButton.OnEnable();
			buttonStatus = status;
		}
	}

	private static void EnableButton_onClick(int obj)
	{
		LocalLaser_Patch.Enable = !LocalLaser_Patch.Enable;
		enableButton.highlighted = LocalLaser_Patch.Enable;
		if (!LocalLaser_Patch.Enable)
		{
			LocalLaser_Patch.ClearAll();
		}
	}

	public static void OnDestory()
	{
		UIButton obj = enableButton;
		Object.Destroy((Object)(object)((obj != null) ? ((Component)obj).gameObject : null));
	}
}