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));
}
}