mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-09 14:53:30 +08:00
UXAssist: Work in progress
This commit is contained in:
313
UXAssist/DysonSpherePatch.cs
Normal file
313
UXAssist/DysonSpherePatch.cs
Normal file
@@ -0,0 +1,313 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace UXAssist;
|
||||
|
||||
public static class DysonSpherePatch
|
||||
{
|
||||
public static ConfigEntry<bool> StopEjectOnNodeCompleteEnabled;
|
||||
public static ConfigEntry<bool> OnlyConstructNodesEnabled;
|
||||
private static Harmony _dysonSpherePatch;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_dysonSpherePatch ??= Harmony.CreateAndPatchAll(typeof(DysonSpherePatch));
|
||||
StopEjectOnNodeCompleteEnabled.SettingChanged += (_, _) => StopEjectOnNodeComplete.Enable(StopEjectOnNodeCompleteEnabled.Value);
|
||||
OnlyConstructNodesEnabled.SettingChanged += (_, _) => OnlyConstructNodes.Enable(OnlyConstructNodesEnabled.Value);
|
||||
StopEjectOnNodeComplete.Enable(StopEjectOnNodeCompleteEnabled.Value);
|
||||
OnlyConstructNodes.Enable(OnlyConstructNodesEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
StopEjectOnNodeComplete.Enable(false);
|
||||
OnlyConstructNodes.Enable(false);
|
||||
_dysonSpherePatch?.UnpatchSelf();
|
||||
_dysonSpherePatch = null;
|
||||
}
|
||||
|
||||
public static void InitCurrentDysonSphere(int index)
|
||||
{
|
||||
var star = GameMain.localStar;
|
||||
if (star == null) return;
|
||||
var dysonSpheres = GameMain.data?.dysonSpheres;
|
||||
if (dysonSpheres == null) return;
|
||||
if (index < 0)
|
||||
{
|
||||
if (dysonSpheres[star.index] == null) return;
|
||||
var dysonSphere = new DysonSphere();
|
||||
dysonSpheres[star.index] = dysonSphere;
|
||||
dysonSphere.Init(GameMain.data, star);
|
||||
dysonSphere.ResetNew();
|
||||
return;
|
||||
}
|
||||
|
||||
var ds = dysonSpheres[star.index];
|
||||
if (ds?.layersIdBased[index] == null) return;
|
||||
var pool = ds.rocketPool;
|
||||
for (var id = ds.rocketCursor - 1; id > 0; id--)
|
||||
{
|
||||
if (pool[id].id != id) continue;
|
||||
if (pool[id].nodeLayerId != index) continue;
|
||||
ds.RemoveDysonRocket(id);
|
||||
}
|
||||
ds.RemoveLayer(index);
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPriority(Priority.First)]
|
||||
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.ConstructCp))]
|
||||
private static IEnumerable<CodeInstruction> DysonSpherePatch_DysonNode_ConstructCp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchBack(false,
|
||||
new CodeMatch(OpCodes.Ldc_I4_0),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(DysonShell), nameof(DysonShell.Construct)))
|
||||
).Advance(3).InsertAndAdvance(
|
||||
// node._cpReq = node._cpReq - 1;
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode._cpReq))),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Sub),
|
||||
new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode._cpReq)))
|
||||
);
|
||||
// Remove use of RecalcCpReq()
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(DysonNode), nameof(DysonNode.RecalcCpReq)))
|
||||
);
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = new List<Label>();
|
||||
matcher.RemoveInstructions(2).Labels.AddRange(labels);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
private static class StopEjectOnNodeComplete
|
||||
{
|
||||
private static Harmony _patch;
|
||||
private static HashSet<int>[] _nodeForAbsorb;
|
||||
private static bool _initialized;
|
||||
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
InitNodeForAbsorb();
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(StopEjectOnNodeComplete));
|
||||
}
|
||||
else
|
||||
{
|
||||
_initialized = false;
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
_nodeForAbsorb = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitNodeForAbsorb()
|
||||
{
|
||||
_initialized = false;
|
||||
_nodeForAbsorb = null;
|
||||
var data = GameMain.data;
|
||||
var galaxy = data?.galaxy;
|
||||
if (galaxy == null) return;
|
||||
_nodeForAbsorb = new HashSet<int>[galaxy.starCount];
|
||||
var spheres = data.dysonSpheres;
|
||||
if (spheres == null) return;
|
||||
foreach (var sphere in spheres)
|
||||
{
|
||||
if (sphere?.layersSorted == null) continue;
|
||||
var starIndex = sphere.starData.index;
|
||||
foreach (var layer in sphere.layersSorted)
|
||||
{
|
||||
if (layer == null) continue;
|
||||
for (var i = layer.nodeCursor - 1; i > 0; i--)
|
||||
{
|
||||
var node = layer.nodePool[i];
|
||||
if (node == null || node.id != i || node.sp < node.spMax || node.cpReqOrder == 0) continue;
|
||||
SetNodeForAbsorb(starIndex, layer.id, node.id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
private static void SetNodeForAbsorb(int index, int layerId, int nodeId, bool canAbsorb)
|
||||
{
|
||||
ref var comp = ref _nodeForAbsorb[index];
|
||||
comp ??= new HashSet<int>();
|
||||
var idx = nodeId * 10 + layerId;
|
||||
if (canAbsorb)
|
||||
comp.Add(idx);
|
||||
else
|
||||
comp.Remove(idx);
|
||||
}
|
||||
|
||||
private static void UpdateNodeForAbsorbOnSpChange(DysonNode node)
|
||||
{
|
||||
if (!_initialized) return;
|
||||
if (node.sp < node.spMax || node.cpReqOrder <= 0) return;
|
||||
var shells = node.shells;
|
||||
if (shells.Count == 0) return;
|
||||
SetNodeForAbsorb(shells[0].dysonSphere.starData.index, node.layerId, node.id, true);
|
||||
}
|
||||
|
||||
private static void UpdateNodeForAbsorbOnCpChange(DysonNode node)
|
||||
{
|
||||
if (!_initialized) return;
|
||||
if (node.sp < node.spMax || node.cpReqOrder > 0) return;
|
||||
var shells = node.shells;
|
||||
if (shells.Count == 0) return;
|
||||
SetNodeForAbsorb(shells[0].dysonSphere.starData.index, node.layerId, node.id, false);
|
||||
}
|
||||
|
||||
private static bool AnyNodeForAbsorb(int starIndex)
|
||||
{
|
||||
var comp = _nodeForAbsorb[starIndex];
|
||||
return comp != null && comp.Count > 0;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
|
||||
private static void GameMain_Begin_Postfix()
|
||||
{
|
||||
InitNodeForAbsorb();
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.RecalcCpReq))]
|
||||
private static void DysonNode_RecalcCpReq_Postfix(DysonNode __instance)
|
||||
{
|
||||
UpdateNodeForAbsorbOnCpChange(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(DysonSphereLayer), nameof(DysonSphereLayer.RemoveDysonNode))]
|
||||
private static void DysonSphereLayer_RemoveDysonNode_Prefix(DysonSphereLayer __instance, int nodeId)
|
||||
{
|
||||
if (_initialized)
|
||||
SetNodeForAbsorb(__instance.starData.index, __instance.id, nodeId, false);
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.ResetNew))]
|
||||
private static void DysonSphere_ResetNew_Prefix(DysonSphere __instance)
|
||||
{
|
||||
var starIndex = __instance.starData.index;
|
||||
if (_nodeForAbsorb[starIndex] == null) return;
|
||||
_nodeForAbsorb[starIndex].Clear();
|
||||
_nodeForAbsorb[starIndex] = null;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
||||
private static IEnumerable<CodeInstruction> EjectorComponent_InternalUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
// if (this.orbitId == 0
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.orbitId))),
|
||||
new CodeMatch(OpCodes.Brtrue)
|
||||
).Advance(2).Insert(
|
||||
// || !StopEjectOnNodeComplete.AnyNodeForAbsorb(this.starData.index))
|
||||
new CodeInstruction(OpCodes.Ldarg_2),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSwarm), nameof(DysonSwarm.starData))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(StarData), nameof(StarData.index))),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(StopEjectOnNodeComplete), nameof(StopEjectOnNodeComplete.AnyNodeForAbsorb))),
|
||||
new CodeInstruction(OpCodes.And)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.ConstructSp))]
|
||||
private static IEnumerable<CodeInstruction> DysonNode_ConstructSp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode.sp)))
|
||||
).Advance(1);
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = new List<Label>();
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(StopEjectOnNodeComplete), nameof(StopEjectOnNodeComplete.UpdateNodeForAbsorbOnSpChange)))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.ConstructCp))]
|
||||
private static IEnumerable<CodeInstruction> DysonNode_ConstructCp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchBack(false,
|
||||
// Search for previous patch:
|
||||
// node._cpReq = node._cpReq - 1;
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode._cpReq))),
|
||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||
new CodeMatch(OpCodes.Sub),
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode._cpReq)))
|
||||
).Advance(6).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(StopEjectOnNodeComplete), nameof(StopEjectOnNodeComplete.UpdateNodeForAbsorbOnCpChange)))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private static class OnlyConstructNodes
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(OnlyConstructNodes));
|
||||
}
|
||||
else
|
||||
{
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
var spheres = GameMain.data?.dysonSpheres;
|
||||
if (spheres == null) return;
|
||||
foreach (var sphere in spheres)
|
||||
{
|
||||
if (sphere == null) continue;
|
||||
sphere.CheckAutoNodes();
|
||||
if (sphere.autoNodeCount > 0) continue;
|
||||
sphere.PickAutoNode();
|
||||
sphere.PickAutoNode();
|
||||
sphere.PickAutoNode();
|
||||
sphere.PickAutoNode();
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.spReqOrder), MethodType.Getter)]
|
||||
private static IEnumerable<CodeInstruction> DysonNode_spReqOrder_Getter_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode._spReq)))
|
||||
).Advance(1).SetInstructionAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode.spMax)))
|
||||
).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode.sp))),
|
||||
new CodeInstruction(OpCodes.Sub)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
511
UXAssist/FactoryPatch.cs
Normal file
511
UXAssist/FactoryPatch.cs
Normal file
@@ -0,0 +1,511 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UXAssist;
|
||||
|
||||
public static class FactoryPatch
|
||||
{
|
||||
public static ConfigEntry<bool> UnlimitInteractiveEnabled;
|
||||
public static ConfigEntry<bool> RemoveSomeConditionEnabled;
|
||||
public static ConfigEntry<bool> NightLightEnabled;
|
||||
public static ConfigEntry<bool> RemoveBuildRangeLimitEnabled;
|
||||
public static ConfigEntry<bool> LargerAreaForUpgradeAndDismantleEnabled;
|
||||
public static ConfigEntry<bool> LargerAreaForTerraformEnabled;
|
||||
|
||||
private static Harmony _factoryPatch;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
UnlimitInteractiveEnabled.SettingChanged += (_, _) => UnlimitInteractive.Enable(UnlimitInteractiveEnabled.Value);
|
||||
RemoveSomeConditionEnabled.SettingChanged += (_, _) => RemoveSomeConditionBuild.Enable(RemoveSomeConditionEnabled.Value);
|
||||
NightLightEnabled.SettingChanged += (_, _) => NightLight.Enable(NightLightEnabled.Value);
|
||||
RemoveBuildRangeLimitEnabled.SettingChanged += (_, _) => RemoveBuildRangeLimit.Enable(RemoveBuildRangeLimitEnabled.Value);
|
||||
LargerAreaForUpgradeAndDismantleEnabled.SettingChanged += (_, _) => LargerAreaForUpgradeAndDismantle.Enable(LargerAreaForUpgradeAndDismantleEnabled.Value);
|
||||
LargerAreaForTerraformEnabled.SettingChanged += (_, _) => LargerAreaForTerraform.Enable(LargerAreaForTerraformEnabled.Value);
|
||||
UnlimitInteractive.Enable(UnlimitInteractiveEnabled.Value);
|
||||
RemoveSomeConditionBuild.Enable(RemoveSomeConditionEnabled.Value);
|
||||
NightLight.Enable(NightLightEnabled.Value);
|
||||
RemoveBuildRangeLimit.Enable(RemoveBuildRangeLimitEnabled.Value);
|
||||
LargerAreaForUpgradeAndDismantle.Enable(LargerAreaForUpgradeAndDismantleEnabled.Value);
|
||||
LargerAreaForTerraform.Enable(LargerAreaForTerraformEnabled.Value);
|
||||
|
||||
_factoryPatch ??= Harmony.CreateAndPatchAll(typeof(FactoryPatch));
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
RemoveSomeConditionBuild.Enable(false);
|
||||
UnlimitInteractive.Enable(false);
|
||||
NightLight.Enable(false);
|
||||
RemoveBuildRangeLimit.Enable(false);
|
||||
LargerAreaForUpgradeAndDismantle.Enable(false);
|
||||
LargerAreaForTerraform.Enable(false);
|
||||
|
||||
_factoryPatch?.UnpatchSelf();
|
||||
_factoryPatch = null;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(ConnGizmoGraph), MethodType.Constructor)]
|
||||
[HarmonyPatch(typeof(ConnGizmoGraph), nameof(ConnGizmoGraph.SetPointCount))]
|
||||
private static IEnumerable<CodeInstruction> ConnGizmoGraph_Constructor_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(256))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 2048));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_Path), nameof(BuildTool_Path._OnInit))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_Path__OnInit_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(160))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 2048));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
public static class NightLight
|
||||
{
|
||||
private static Harmony _patch;
|
||||
private const float NightLightAngleX = -8;
|
||||
private const float NightLightAngleY = -2;
|
||||
public static bool Enabled;
|
||||
private static bool _nightlightInitialized;
|
||||
private static bool _mechaOnEarth;
|
||||
private static AnimationState _sail;
|
||||
private static Light _sunlight;
|
||||
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
Enabled = _mechaOnEarth;
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(NightLight));
|
||||
return;
|
||||
}
|
||||
|
||||
Enabled = false;
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
if (_sunlight == null) return;
|
||||
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
|
||||
}
|
||||
|
||||
public static void LateUpdate()
|
||||
{
|
||||
if (_patch == null) return;
|
||||
|
||||
switch (_nightlightInitialized)
|
||||
{
|
||||
case false:
|
||||
Ready();
|
||||
break;
|
||||
case true:
|
||||
Go();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Ready()
|
||||
{
|
||||
if (!GameMain.isRunning || !GameMain.mainPlayer.controller.model.gameObject.activeInHierarchy) return;
|
||||
if (_sail == null)
|
||||
{
|
||||
_sail = GameMain.mainPlayer.animator.sails[GameMain.mainPlayer.animator.sailAnimIndex];
|
||||
}
|
||||
|
||||
_nightlightInitialized = true;
|
||||
}
|
||||
|
||||
private static void Go()
|
||||
{
|
||||
if (!GameMain.isRunning)
|
||||
{
|
||||
End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_sail.enabled)
|
||||
{
|
||||
_mechaOnEarth = false;
|
||||
Enabled = false;
|
||||
if (_sunlight == null) return;
|
||||
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
|
||||
_sunlight = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_mechaOnEarth)
|
||||
{
|
||||
if (_sunlight == null)
|
||||
{
|
||||
var simu = GameMain.universeSimulator;
|
||||
if (simu)
|
||||
_sunlight = simu.LocalStarSimulator()?.sunLight;
|
||||
if (_sunlight == null) return;
|
||||
}
|
||||
|
||||
_mechaOnEarth = true;
|
||||
Enabled = NightLightEnabled.Value;
|
||||
}
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
_sunlight.transform.rotation =
|
||||
Quaternion.LookRotation(-GameMain.mainPlayer.transform.up + GameMain.mainPlayer.transform.forward * NightLightAngleX / 10f +
|
||||
GameMain.mainPlayer.transform.right * NightLightAngleY / 10f);
|
||||
}
|
||||
}
|
||||
|
||||
private static void End()
|
||||
{
|
||||
_mechaOnEarth = false;
|
||||
Enabled = false;
|
||||
if (_sunlight != null)
|
||||
{
|
||||
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
|
||||
_sunlight = null;
|
||||
}
|
||||
|
||||
_sail = null;
|
||||
_nightlightInitialized = false;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(StarSimulator), "LateUpdate")]
|
||||
private static IEnumerable<CodeInstruction> StarSimulator_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
// var vec = NightlightEnabled ? GameMain.mainPlayer.transform.up : __instance.transform.forward;
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
var label2 = generator.DefineLabel();
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(Component), nameof(Component.transform)))
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(NightLight), nameof(NightLight.Enabled))),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(GameMain), nameof(GameMain.mainPlayer))),
|
||||
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.transform))),
|
||||
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Transform), nameof(Transform.up))),
|
||||
new CodeInstruction(OpCodes.Stloc_0),
|
||||
new CodeInstruction(OpCodes.Br_S, label2)
|
||||
);
|
||||
matcher.Labels.Add(label1);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_0)
|
||||
).Advance(1).Labels.Add(label2);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlanetSimulator), "LateUpdate")]
|
||||
private static IEnumerable<CodeInstruction> PlanetSimulator_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
// var vec = (NightlightEnabled ? GameMain.mainPlayer.transform.up : (Quaternion.Inverse(localPlanet.runtimeRotation) * (__instance.planetData.star.uPosition - __instance.planetData.uPosition).normalized));
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
var label2 = generator.DefineLabel();
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Pop)
|
||||
).Advance(1).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(NightLight), nameof(NightLight.Enabled))),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(GameMain), nameof(GameMain.mainPlayer))),
|
||||
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.transform))),
|
||||
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Transform), nameof(Transform.up))),
|
||||
new CodeInstruction(OpCodes.Stloc_1),
|
||||
new CodeInstruction(OpCodes.Br_S, label2)
|
||||
);
|
||||
matcher.Labels.Add(label1);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(typeof(FactoryModel), nameof(FactoryModel.whiteMode0)))
|
||||
).Labels.Add(label2);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private static class UnlimitInteractive
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(UnlimitInteractive));
|
||||
return;
|
||||
}
|
||||
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlayerAction_Inspect), nameof(PlayerAction_Inspect.GetObjectSelectDistance))]
|
||||
private static IEnumerable<CodeInstruction> PlayerAction_Inspect_GetObjectSelectDistance_Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
yield return new CodeInstruction(OpCodes.Ldc_R4, 10000f);
|
||||
yield return new CodeInstruction(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RemoveSomeConditionBuild
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(RemoveSomeConditionBuild));
|
||||
return;
|
||||
}
|
||||
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler, HarmonyPriority(Priority.First)]
|
||||
[HarmonyPatch(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.CheckBuildConditions))]
|
||||
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.CheckBuildConditions))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_Click_CheckBuildConditions_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* search for:
|
||||
* ldloc.s V_8 (8)
|
||||
* ldfld class PrefabDesc BuildPreview::desc
|
||||
* ldfld bool PrefabDesc::isInserter
|
||||
* brtrue 2358 (1C12) ldloc.s V_8 (8)
|
||||
* ldloca.s V_10 (10)
|
||||
* call instance float32 [UnityEngine.CoreModule]UnityEngine.Vector3::get_magnitude()
|
||||
*/
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_S),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BuildPreview), nameof(BuildPreview.desc))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PrefabDesc), nameof(PrefabDesc.isInserter))),
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Brtrue || instr.opcode == OpCodes.Brtrue_S),
|
||||
new CodeMatch(OpCodes.Ldloca_S),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(Vector3), nameof(Vector3.magnitude)))
|
||||
);
|
||||
var jumpPos = matcher.InstructionAt(3).operand;
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = new List<Label>();
|
||||
/* Insert: br 2358 (1C12) ldloc.s V_8 (8)
|
||||
*/
|
||||
matcher.Insert(new CodeInstruction(OpCodes.Br, jumpPos).WithLabels(labels));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler, HarmonyPriority(Priority.First)]
|
||||
[HarmonyPatch(typeof(BuildTool_Path), nameof(BuildTool_Path.CheckBuildConditions))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_Path_CheckBuildConditions_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* search for:
|
||||
* ldloc.s V_88 (88)
|
||||
* ldloc.s V_120 (120)
|
||||
* brtrue.s 2054 (173A) ldc.i4.s 17
|
||||
* ldc.i4.s 18
|
||||
* br.s 2055 (173C) stfld valuetype EBuildCondition BuildPreview::condition
|
||||
* ldc.i4.s 17
|
||||
* stfld valuetype EBuildCondition BuildPreview::condition
|
||||
*/
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_S),
|
||||
new CodeMatch(OpCodes.Ldloc_S),
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Brtrue_S || instr.opcode == OpCodes.Brtrue),
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_I4_S && instr.OperandIs(18)),
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Br_S || instr.opcode == OpCodes.Br),
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_I4_S && instr.OperandIs(17)),
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(BuildPreview), nameof(BuildPreview.condition)))
|
||||
);
|
||||
if (matcher.IsValid)
|
||||
{
|
||||
// Remove 7 instructions, if the following instruction is br/br.s, remove it as well
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = new List<Label>();
|
||||
matcher.RemoveInstructions(7);
|
||||
var opcode = matcher.Opcode;
|
||||
if (opcode == OpCodes.Br || opcode == OpCodes.Br_S)
|
||||
matcher.RemoveInstruction();
|
||||
matcher.Labels.AddRange(labels);
|
||||
}
|
||||
|
||||
/* search for:
|
||||
* ldloc.s V_88 (88)
|
||||
* ldc.i4.s 15-19
|
||||
* stfld valuetype EBuildCondition BuildPreview::condition
|
||||
*/
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Ldloc_S || instr.opcode == OpCodes.Ldloc),
|
||||
new CodeMatch(instr => (instr.opcode == OpCodes.Ldc_I4_S || instr.opcode == OpCodes.Ldc_I4) && Convert.ToInt64(instr.operand) is >= 15 and <= 19),
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(BuildPreview), nameof(BuildPreview.condition)))
|
||||
);
|
||||
if (matcher.IsValid)
|
||||
{
|
||||
// Remove 3 instructions, if the following instruction is br/br.s, remove it as well
|
||||
matcher.Repeat(codeMatcher =>
|
||||
{
|
||||
var labels = codeMatcher.Labels;
|
||||
codeMatcher.Labels = new List<Label>();
|
||||
codeMatcher.RemoveInstructions(3);
|
||||
var opcode = codeMatcher.Opcode;
|
||||
if (opcode == OpCodes.Br || opcode == OpCodes.Br_S)
|
||||
codeMatcher.RemoveInstruction();
|
||||
codeMatcher.Labels.AddRange(labels);
|
||||
});
|
||||
}
|
||||
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private static class RemoveBuildRangeLimit
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(RemoveBuildRangeLimit));
|
||||
}
|
||||
else
|
||||
{
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
var controller = GameMain.mainPlayer?.controller;
|
||||
if (controller == null) return;
|
||||
controller.actionBuild?.clickTool?._OnInit();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click._OnInit))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_Click__OnInit_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(15))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 512));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_Addon), nameof(BuildTool_Addon.CheckBuildConditions))]
|
||||
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.CheckBuildConditions))]
|
||||
[HarmonyPatch(typeof(BuildTool_Dismantle), nameof(BuildTool_Dismantle.DetermineMoreChainTargets))]
|
||||
[HarmonyPatch(typeof(BuildTool_Dismantle), nameof(BuildTool_Dismantle.DeterminePreviews))]
|
||||
[HarmonyPatch(typeof(BuildTool_Inserter), nameof(BuildTool_Inserter.CheckBuildConditions))]
|
||||
[HarmonyPatch(typeof(BuildTool_Path), nameof(BuildTool_Path.CheckBuildConditions))]
|
||||
[HarmonyPatch(typeof(BuildTool_Reform), nameof(BuildTool_Reform.ReformAction))]
|
||||
[HarmonyPatch(typeof(BuildTool_Upgrade), nameof(BuildTool_Upgrade.DetermineMoreChainTargets))]
|
||||
[HarmonyPatch(typeof(BuildTool_Upgrade), nameof(BuildTool_Upgrade.DeterminePreviews))]
|
||||
private static IEnumerable<CodeInstruction> BuildAreaLimitRemoval_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* Patch (player.mecha.buildArea * player.mecha.buildArea) to 100000000 */
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(BuildTool), nameof(BuildTool.player))),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.mecha))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(Mecha), nameof(Mecha.buildArea))),
|
||||
new CodeMatch(),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(BuildTool), nameof(BuildTool.player))),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.mecha))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(Mecha), nameof(Mecha.buildArea))),
|
||||
new CodeMatch(OpCodes.Mul)
|
||||
);
|
||||
matcher.Repeat(m => m.RemoveInstructions(9).InsertAndAdvance(new CodeInstruction(OpCodes.Ldc_R4, 100000000.0f)));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private static class LargerAreaForUpgradeAndDismantle
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(LargerAreaForUpgradeAndDismantle));
|
||||
return;
|
||||
}
|
||||
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_Dismantle), nameof(BuildTool_Dismantle.DeterminePreviews))]
|
||||
[HarmonyPatch(typeof(BuildTool_Upgrade), nameof(BuildTool_Upgrade.DeterminePreviews))]
|
||||
private static IEnumerable<CodeInstruction> BuildTools_CursorSizePatch_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(11))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4_S, 31));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private static class LargerAreaForTerraform
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(LargerAreaForTerraform));
|
||||
return;
|
||||
}
|
||||
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler, HarmonyPatch(typeof(BuildTool_Reform), MethodType.Constructor)]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_Reform_Constructor_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(100))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 900));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler, HarmonyPatch(typeof(BuildTool_Reform), nameof(BuildTool_Reform.ReformAction))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_Reform_ReformAction_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BuildTool_Reform), nameof(BuildTool_Reform.brushSize))),
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(10))
|
||||
);
|
||||
matcher.Repeat(m => m.Advance(1).SetAndAdvance(OpCodes.Ldc_I4_S, 30));
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(10)),
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(BuildTool_Reform), nameof(BuildTool_Reform.brushSize)))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4_S, 30));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
145
UXAssist/PlanetFunctions.cs
Normal file
145
UXAssist/PlanetFunctions.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using System.Threading;
|
||||
|
||||
namespace UXAssist;
|
||||
|
||||
public static class PlanetFunctions
|
||||
{
|
||||
public static void DismantleAll(bool toBag)
|
||||
{
|
||||
var player = GameMain.mainPlayer;
|
||||
if (player == null) return;
|
||||
var planet = GameMain.localPlanet;
|
||||
var factory = planet?.factory;
|
||||
if (factory == null) return;
|
||||
foreach (var etd in factory.entityPool)
|
||||
{
|
||||
var stationId = etd.stationId;
|
||||
if (stationId > 0)
|
||||
{
|
||||
var sc = GameMain.localPlanet.factory.transport.stationPool[stationId];
|
||||
if (toBag)
|
||||
{
|
||||
for (var i = 0; i < sc.storage.Length; i++)
|
||||
{
|
||||
var package = player.TryAddItemToPackage(sc.storage[i].itemId, sc.storage[i].count, 0, true, etd.id);
|
||||
UIItemup.Up(sc.storage[i].itemId, package);
|
||||
}
|
||||
}
|
||||
sc.storage = new StationStore[sc.storage.Length];
|
||||
sc.needs = new int[sc.needs.Length];
|
||||
}
|
||||
if (toBag)
|
||||
{
|
||||
player.controller.actionBuild.DoDismantleObject(etd.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
factory.RemoveEntityWithComponents(etd.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RecreatePlanet(bool revertReform)
|
||||
{
|
||||
var player = GameMain.mainPlayer;
|
||||
if (player == null) return;
|
||||
var planet = GameMain.localPlanet;
|
||||
var factory = planet?.factory;
|
||||
if (factory == null) return;
|
||||
//planet.data = new PlanetRawData(planet.precision);
|
||||
//planet.data.CalcVerts();
|
||||
for (var id = factory.entityCursor - 1; id > 0; id--)
|
||||
{
|
||||
var ed = factory.entityPool[id];
|
||||
if (ed.id != id) continue;
|
||||
if (ed.colliderId != 0)
|
||||
{
|
||||
planet.physics.RemoveLinkedColliderData(ed.colliderId);
|
||||
planet.physics.NotifyObjectRemove(EObjectType.Entity, ed.id);
|
||||
}
|
||||
|
||||
if (ed.modelId != 0)
|
||||
{
|
||||
GameMain.gpuiManager.RemoveModel(ed.modelIndex, ed.modelId);
|
||||
}
|
||||
|
||||
if (ed.mmblockId != 0)
|
||||
{
|
||||
factory.blockContainer.RemoveMiniBlock(ed.mmblockId);
|
||||
}
|
||||
|
||||
if (ed.audioId == 0) continue;
|
||||
planet.audio?.RemoveAudioData(ed.audioId);
|
||||
}
|
||||
|
||||
var stationPool = factory.transport?.stationPool;
|
||||
if (stationPool != null)
|
||||
{
|
||||
foreach (var sc in stationPool)
|
||||
{
|
||||
if (sc == null || sc.id <= 0) continue;
|
||||
sc.storage = new StationStore[sc.storage.Length];
|
||||
sc.needs = new int[sc.needs.Length];
|
||||
int protoId = factory.entityPool[sc.entityId].protoId;
|
||||
factory.DismantleFinally(player, sc.entityId, ref protoId);
|
||||
}
|
||||
}
|
||||
|
||||
var gameScenario = GameMain.gameScenario;
|
||||
if (gameScenario != null)
|
||||
{
|
||||
var genPool = factory.powerSystem?.genPool;
|
||||
if (genPool != null)
|
||||
{
|
||||
foreach (var pgc in genPool)
|
||||
{
|
||||
if (pgc.id <= 0) continue;
|
||||
int protoId = factory.entityPool[pgc.entityId].protoId;
|
||||
gameScenario.achievementLogic.NotifyBeforeDismantleEntity(planet.id, protoId, pgc.entityId);
|
||||
gameScenario.NotifyOnDismantleEntity(planet.id, protoId, pgc.entityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (revertReform)
|
||||
{
|
||||
factory.PlanetReformRevert();
|
||||
}
|
||||
|
||||
planet.UnloadFactory();
|
||||
var index = factory.index;
|
||||
var warningSystem = GameMain.data.warningSystem;
|
||||
var warningPool = warningSystem.warningPool;
|
||||
for (var i = warningSystem.warningCursor - 1; i > 0; i--)
|
||||
{
|
||||
if (warningPool[i].id == i && warningPool[i].factoryId == index)
|
||||
warningSystem.RemoveWarningData(warningPool[i].id);
|
||||
}
|
||||
factory.entityCursor = 1;
|
||||
factory.entityRecycleCursor = 0;
|
||||
factory.entityCapacity = 0;
|
||||
factory.SetEntityCapacity(1024);
|
||||
factory.prebuildCursor = 1;
|
||||
factory.prebuildRecycleCursor = 0;
|
||||
factory.prebuildCapacity = 0;
|
||||
factory.SetPrebuildCapacity(256);
|
||||
factory.cargoContainer = new CargoContainer();
|
||||
factory.cargoTraffic = new CargoTraffic(planet);
|
||||
factory.blockContainer = new MiniBlockContainer();
|
||||
factory.factoryStorage = new FactoryStorage(planet);
|
||||
factory.powerSystem = new PowerSystem(planet);
|
||||
factory.factorySystem = new FactorySystem(planet);
|
||||
factory.transport = new PlanetTransport(GameMain.data, planet);
|
||||
factory.transport.Init();
|
||||
factory.digitalSystem = new DigitalSystem(planet);
|
||||
|
||||
//GameMain.data.statistics.production.CreateFactoryStat(index);
|
||||
planet.LoadFactory();
|
||||
while (!planet.factoryLoaded)
|
||||
{
|
||||
PlanetModelingManager.Update();
|
||||
Thread.Sleep(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
109
UXAssist/PlanetPatch.cs
Normal file
109
UXAssist/PlanetPatch.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using System.Threading;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace UXAssist;
|
||||
public static class PlanetPatch
|
||||
{
|
||||
public static ConfigEntry<bool> PlayerActionsInGlobeViewEnabled;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
PlayerActionsInGlobeViewEnabled.SettingChanged += (_, _) => PlayerActionsInGlobeView.Enable(PlayerActionsInGlobeViewEnabled.Value);
|
||||
PlayerActionsInGlobeView.Enable(PlayerActionsInGlobeViewEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
PlayerActionsInGlobeView.Enable(false);
|
||||
}
|
||||
|
||||
public static class PlayerActionsInGlobeView
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(PlayerActionsInGlobeView));
|
||||
return;
|
||||
}
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(VFInput), nameof(VFInput.UpdateGameStates))]
|
||||
private static IEnumerable<CodeInstruction> VFInput_UpdateGameStates_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* remove UIGame.viewMode != EViewMode.Globe in two places:
|
||||
* so search for:
|
||||
* ldsfld bool VFInput::viewMode
|
||||
* ldc.i4.3
|
||||
*/
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(typeof(UIGame), nameof(UIGame.viewMode))),
|
||||
new CodeMatch(OpCodes.Ldc_I4_3)
|
||||
);
|
||||
matcher.Repeat(codeMatcher =>
|
||||
{
|
||||
var labels = codeMatcher.Labels;
|
||||
codeMatcher.Labels = new List<Label>();
|
||||
codeMatcher.RemoveInstructions(3).Labels.AddRange(labels);
|
||||
});
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.GetInput))]
|
||||
private static IEnumerable<CodeInstruction> PlayerController_GetInput_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
// replace `UIGame.viewMode >= EViewMode.Globe` with `UIGame.viewMode >= EViewMode.Starmap`
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(typeof(UIGame), nameof(UIGame.viewMode))),
|
||||
new CodeMatch(OpCodes.Ldc_I4_3)
|
||||
).Advance(1).Opcode = OpCodes.Ldc_I4_4;
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlayerAction_Rts), nameof(PlayerAction_Rts.GameTick))]
|
||||
private static IEnumerable<CodeInstruction> PlayerAction_Rts_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var local1 = generator.DeclareLocal(typeof(bool));
|
||||
// var local1 = UIGame.viewMode == 3;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(VFInput), nameof(VFInput.rtsMoveCameraConflict))),
|
||||
new CodeMatch(OpCodes.Stloc_1)
|
||||
);
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = new List<Label>();
|
||||
matcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(UIGame), nameof(UIGame.viewMode))).WithLabels(labels),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_3),
|
||||
new CodeInstruction(OpCodes.Ceq),
|
||||
new CodeInstruction(OpCodes.Stloc, local1)
|
||||
);
|
||||
// Add extra condition:
|
||||
// VFInput.rtsMoveCameraConflict / VFInput.rtsMineCameraConflict `|| local1`
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Ldloc_1 || instr.opcode == OpCodes.Ldloc_2)
|
||||
);
|
||||
matcher.Repeat(codeMatcher =>
|
||||
{
|
||||
matcher.Advance(1);
|
||||
matcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldloc, local1),
|
||||
new CodeInstruction(OpCodes.Or)
|
||||
);
|
||||
});
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
88
UXAssist/PlayerPatch.cs
Normal file
88
UXAssist/PlayerPatch.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace UXAssist;
|
||||
|
||||
public static class PlayerPatch
|
||||
{
|
||||
public static ConfigEntry<bool> EnhancedMechaForgeCountControlEnabled;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
EnhancedMechaForgeCountControlEnabled.SettingChanged += (_, _) => EnhancedMechaForgeCountControl.Enable(EnhancedMechaForgeCountControlEnabled.Value);
|
||||
EnhancedMechaForgeCountControl.Enable(EnhancedMechaForgeCountControlEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
EnhancedMechaForgeCountControl.Enable(false);
|
||||
}
|
||||
|
||||
private static class EnhancedMechaForgeCountControl
|
||||
{
|
||||
private static Harmony _patch;
|
||||
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(EnhancedMechaForgeCountControl));
|
||||
}
|
||||
else
|
||||
{
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnOkButtonClick))]
|
||||
private static IEnumerable<CodeInstruction> UIReplicatorWindow_OnOkButtonClick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(10))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 1000));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnPlusButtonClick))]
|
||||
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnMinusButtonClick))]
|
||||
private static IEnumerable<CodeInstruction> UIReplicatorWindow_OnPlusButtonClick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var label1 = generator.DefineLabel();
|
||||
var label2 = generator.DefineLabel();
|
||||
var label3 = generator.DefineLabel();
|
||||
var label4 = generator.DefineLabel();
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||
new CodeMatch(o => o.opcode == OpCodes.Add || o.opcode == OpCodes.Sub)
|
||||
).Advance(1).RemoveInstruction().InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.control))),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label1),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_S, 10),
|
||||
new CodeInstruction(OpCodes.Br_S, label4),
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.shift))).WithLabels(label1),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label2),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_S, 100),
|
||||
new CodeInstruction(OpCodes.Br_S, label4),
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.alt))).WithLabels(label2),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label3),
|
||||
new CodeInstruction(OpCodes.Ldc_I4, 1000),
|
||||
new CodeInstruction(OpCodes.Br_S, label4),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1).WithLabels(label3)
|
||||
).Labels.Add(label4);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(10))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 1000));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +1,9 @@
|
||||
# CheatEnabler
|
||||
# UXAssist
|
||||
|
||||
#### Add various cheat functions while disabling abnormal determinants
|
||||
#### 添加一些作弊功能,同时屏蔽异常检测
|
||||
#### Some functions and patches for better user experience
|
||||
#### 一些提升用户体验的功能和补丁
|
||||
|
||||
## Changlog
|
||||
* 2.2.7
|
||||
+ New function: `Construct only nodes but frames`
|
||||
+ Opening config panel does not close inventory panel now
|
||||
+ Remove `Input direction conflict` check while using `Remove some build conditions`
|
||||
+ Fix a bug that prevents `Belt signal alt format` from switching number formats for current belt signals
|
||||
* 2.2.6
|
||||
+ New function: `Stop ejectors when available nodes are all filled up`
|
||||
+ Fix a bug that absorb solar sails on unfinised nodes
|
||||
* 2.2.5
|
||||
+ Skip all intermediate states and absorb solar sails instantly while enable `Quick absorb`, `Skip bullet period` and `Skip absorption period` at the same time.
|
||||
+ Fix a problem that `Quick absorb` does not absorb all solar sails instantly when most nodes are full.
|
||||
+ Fix crash while using with some mods
|
||||
* 2.2.4
|
||||
+ New function: `Enable player actions in globe view`
|
||||
+ Fix UI bug
|
||||
* 2.2.3
|
||||
+ New function: `Remove some build conditions`
|
||||
+ Fix compatibility with some mods
|
||||
* 2.2.2
|
||||
+ New function: `Assign game to currrnet account`
|
||||
+ New subfunction: `Belt signal alt format`
|
||||
+ Fix a crash on using `Initialize this Planet`
|
||||
+ Fix belt build in `Finish build immediately`
|
||||
* 2.2.1
|
||||
+ Check condition for miners even when `Build without condition` is enabled.
|
||||
+ Fix a patch issue that may cause `Build without condition` not working.
|
||||
* 2.2.0
|
||||
+ Add some power related functions
|
||||
+ Add a subfunction to belt signal item generation, which simulates production process of raws and intermediates on statistics
|
||||
+ Split some functions from Architect mode
|
||||
* 2.1.0
|
||||
+ Belt signal item generation
|
||||
+ Fix window display priority which may cause tips to be covered by main window
|
||||
* 2.0.0
|
||||
+ Refactorying codes
|
||||
+ UI implementation
|
||||
+ Add a lot of functions
|
||||
* 1.0.0
|
||||
+ Initial release
|
||||
|
||||
@@ -50,45 +13,16 @@
|
||||
* There are also buttons on title screen and planet minimap area to call up the config panel.
|
||||
* Features:
|
||||
+ Strict hotkey dectection for build menu, thus building hotkeys(0~9, F1~F10, X, U) are not triggered while holding Ctrl/Alt/Shift.
|
||||
+ General:
|
||||
+ Enable Dev Shortcuts (check config panel for usage)
|
||||
+ Disable Abnormal Checks
|
||||
+ Unlock techs with key-modifiers (Ctrl/Alt/Shift)
|
||||
+ Assign game to currrnet account
|
||||
+ Factory:
|
||||
+ Finish build immediately
|
||||
+ Architect mode (Infinite buildings)
|
||||
+ Unlimited interactive range
|
||||
+ Build without condition
|
||||
+ Remove some build conditions
|
||||
+ No collision
|
||||
+ Sunlight at night
|
||||
+ Belt signal item generation
|
||||
+ Count all raws and intermediates in statistics
|
||||
+ Belt signal alt format
|
||||
+ Remove space limit between wind turbines and solar panels
|
||||
+ Boost power generations for kinds of power generators
|
||||
+ Planet:
|
||||
+ Enable player actions in globe view
|
||||
+ Infinite Natural Resources
|
||||
+ Fast Mining
|
||||
+ Pump Anywhere
|
||||
+ Terraform without enought sands
|
||||
+ Re-intialize planet (without reseting veins)
|
||||
+ Quick dismantle all buildings (without drops)
|
||||
+ Dyson Sphere:
|
||||
+ Stop ejectors when available nodes are all filled up
|
||||
+ Construct only nodes but frames
|
||||
+ Skip bullet period
|
||||
+ Skip absorption period
|
||||
+ Quick absorb
|
||||
+ Eject anyway
|
||||
+ Re-initialize Dyson Spheres
|
||||
+ Quick dismantle Dyson Shells
|
||||
+ Birth star:
|
||||
+ Rare resources on birth planet
|
||||
+ Solid flat on birth planet
|
||||
+ High luminosity for birth star
|
||||
+ Unlimited interactive range
|
||||
+ Remove some build conditions
|
||||
+ Sunlight at night
|
||||
+ Enable player actions in globe view
|
||||
+ Re-intialize planet (without reseting veins)
|
||||
+ Quick dismantle all buildings (without drops)
|
||||
+ Stop ejectors when available nodes are all filled up
|
||||
+ Construct only nodes but frames
|
||||
+ Re-initialize Dyson Spheres
|
||||
+ Quick dismantle Dyson Shells
|
||||
|
||||
## Notes
|
||||
* Please upgrade `BepInEx` 5.4.21 or later if using with [BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/) to avoid possible conflicts.
|
||||
@@ -97,48 +31,10 @@
|
||||
|
||||
## CREDITS
|
||||
* [Dyson Sphere Program](https://store.steampowered.com/app/1366540): The great game
|
||||
* [BepInEx](https://bepinex.dev/): Base modding framework
|
||||
* [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): Some cheat functions
|
||||
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI implementations
|
||||
|
||||
## 更新日志
|
||||
* 2.2.7
|
||||
+ 新功能:`只建造节点不建造框架`
|
||||
+ 打开设置面板时不再关闭背包面板
|
||||
+ 在`移除部分不影响游戏逻辑的建造条件`启用时移除`输入方向冲突`的检查条件
|
||||
+ 修复导致`传送带信号替换格式`不切换传送带信号数字格式的问题
|
||||
* 2.2.6
|
||||
+ 新功能:`可用节点全部造完时停止弹射`
|
||||
+ 修复了在未完成的节点上吸收太阳帆的问题
|
||||
* 2.2.5
|
||||
+ 在同时启用`快速吸收`、`跳过子弹阶段`和`跳过吸收阶段`时,所有弹射的太阳帆会跳过所有中间环节立即吸收
|
||||
+ 修复了`快速吸收`在大部分节点已满时无法立即吸收所有太阳帆的问题
|
||||
+ 修复了与一些mod的兼容性问题
|
||||
* 2.2.4
|
||||
+ 新功能:`在行星视图中允许玩家操作`
|
||||
+ 修复了UI显示问题
|
||||
* 2.2.3
|
||||
+ 新功能:`移除部分不影响游戏逻辑的建造条件`
|
||||
+ 修复了与一些mod的兼容性问题
|
||||
* 2.2.2
|
||||
+ 新功能:`将游戏绑定给当前账号`
|
||||
+ 新子功能:`传送带信号替换格式`
|
||||
+ 修复了`初始化本行星`可能导致崩溃的问题
|
||||
+ 修复了`建造秒完成`中传送带建造的问题
|
||||
* 2.2.1
|
||||
+ 即使在启用`无条件建造`时依然检查矿机的建造条件
|
||||
+ 修复一个可能导致`无条件建造`不生效的问题
|
||||
* 2.2.0
|
||||
+ 添加了一些发电相关功能
|
||||
+ 为传送带信号物品生成添加了一个子功能,在统计面板模拟了原材料和中间产物的生产过程
|
||||
+ 从建筑师模式中分离了一些功能
|
||||
* 2.1.0
|
||||
+ 传送带信号物品生成
|
||||
+ 修复窗口显示优先级可能导致提示信息被主窗口遮挡的问题
|
||||
* 2.0.0
|
||||
+ 重构代码
|
||||
+ UI实现
|
||||
+ 添加了很多功能
|
||||
* 1.0.0
|
||||
+ 初始版本
|
||||
|
||||
@@ -148,45 +44,16 @@
|
||||
* 标题界面和行星小地图旁也有按钮呼出主面板。
|
||||
* 功能:
|
||||
+ 更严格的建造菜单热键检测,因此在按住Ctrl/Alt/Shift时不再会触发建造热键(0~9, F1~F10, X, U)
|
||||
+ 常规:
|
||||
+ 启用开发模式快捷键(使用说明见设置面板)
|
||||
+ 屏蔽异常检测
|
||||
+ 使用组合键解锁科技(Ctrl/Alt/Shift)
|
||||
+ 将游戏绑定给当前账号
|
||||
+ 工厂:
|
||||
+ 建造秒完成
|
||||
+ 建筑师模式(无限建筑)
|
||||
+ ** 无限交互距离
|
||||
+ 无条件建造
|
||||
+ ** 移除部分不影响游戏逻辑的建造条件
|
||||
+ 无碰撞
|
||||
+ ** 夜间日光灯
|
||||
+ 传送带信号物品生成
|
||||
+ 统计面板中计算所有原材料和中间产物
|
||||
+ 传送带信号替换格式
|
||||
+ 风力发电机和太阳能板无间距限制
|
||||
+ 提升各种发电设备发电量
|
||||
+ 行星:
|
||||
+ ** 在行星视图中允许玩家操作
|
||||
+ 自然资源采集不消耗
|
||||
+ 高速采集
|
||||
+ 平地抽水
|
||||
+ 沙土不够时依然可以整改地形
|
||||
+ ** 初始化本行星(不重置矿脉)
|
||||
+ ** 快速拆除所有建筑(不掉落)
|
||||
+ 戴森球:
|
||||
+ ** 可用节点全部造完时停止弹射
|
||||
+ ** 只建造节点不建造框架
|
||||
+ 跳过子弹阶段
|
||||
+ 跳过吸收阶段
|
||||
+ 快速吸收
|
||||
+ 全球弹射
|
||||
+ ** 初始化戴森球
|
||||
+ ** 快速拆除戴森壳
|
||||
+ 母星系:
|
||||
+ 母星有稀有资源
|
||||
+ 母星是纯平的
|
||||
+ 母星系恒星高亮
|
||||
+ 无限交互距离
|
||||
+ 移除部分不影响游戏逻辑的建造条件
|
||||
+ 夜间日光灯
|
||||
+ 在行星视图中允许玩家操作
|
||||
+ 初始化本行星(不重置矿脉)
|
||||
+ 快速拆除所有建筑(不掉落)
|
||||
+ 可用节点全部造完时停止弹射
|
||||
+ 只建造节点不建造框架
|
||||
+ 初始化戴森球
|
||||
+ 快速拆除戴森壳
|
||||
|
||||
## 注意事项
|
||||
* 如果和[BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/)一起使用,请升级`BepInEx`到5.4.21或更高版本,以避免可能的冲突。
|
||||
@@ -196,5 +63,4 @@
|
||||
## 鸣谢
|
||||
* [戴森球计划](https://store.steampowered.com/app/1366540): 伟大的游戏
|
||||
* [BepInEx](https://bepinex.dev/): 基础模组框架
|
||||
* [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): 一些作弊功能
|
||||
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI实现
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace UXAssist.UI;
|
||||
|
||||
@@ -20,7 +18,7 @@ public class MyConfigWindow : MyWindowWithTabs
|
||||
public override void _OnCreate()
|
||||
{
|
||||
_windowTrans = GetComponent<RectTransform>();
|
||||
_windowTrans.sizeDelta = new Vector2(680f, 420f);
|
||||
_windowTrans.sizeDelta = new Vector2(700f, 472f);
|
||||
|
||||
OnUICreated?.Invoke(this, _windowTrans);
|
||||
SetCurrentTab(0);
|
||||
|
||||
@@ -218,7 +218,7 @@ public class MyWindowWithTabs : MyWindow
|
||||
return true;
|
||||
}
|
||||
|
||||
public RectTransform AddTab(float x, int index, RectTransform parent, string label)
|
||||
private RectTransform AddTabInternal(float x, int index, RectTransform parent, string label)
|
||||
{
|
||||
var tab = new GameObject();
|
||||
var tabRect = tab.AddComponent<RectTransform>();
|
||||
@@ -229,7 +229,7 @@ public class MyWindowWithTabs : MyWindow
|
||||
var btn = Instantiate(src);
|
||||
var btnRect = Util.NormalizeRectWithTopLeft(btn, x, 54f, parent);
|
||||
btn.name = "tab-btn-" + index;
|
||||
btnRect.sizeDelta = new Vector2(100f, 24f);
|
||||
btnRect.sizeDelta = new Vector2(105f, 24f);
|
||||
btn.transform.Find("frame").gameObject.SetActive(false);
|
||||
if (btn.transitions.Length >= 3)
|
||||
{
|
||||
@@ -254,8 +254,8 @@ public class MyWindowWithTabs : MyWindow
|
||||
|
||||
public RectTransform AddTab(RectTransform parent, string label)
|
||||
{
|
||||
var result = AddTab(_tabX, _tabs.Count, parent, label);
|
||||
_tabX += 100f;
|
||||
var result = AddTabInternal(_tabX, _tabs.Count, parent, label);
|
||||
_tabX += 105f;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using UXAssist.UI;
|
||||
using UXAssist.Common;
|
||||
|
||||
@@ -8,19 +7,122 @@ namespace UXAssist;
|
||||
public static class UIConfigWindow
|
||||
{
|
||||
private static RectTransform _windowTrans;
|
||||
private static MyConfigWindow _configWindow;
|
||||
private static RectTransform _tab;
|
||||
private static readonly UIButton[] _dysonLayerBtn = new UIButton[10];
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
I18N.Add("UXAssist", "UXAssist", "UX助手");
|
||||
I18N.Add("Unlimited interactive range", "Unlimited interactive range", "无限交互距离");
|
||||
I18N.Add("Night Light", "Sunlight at night", "夜间日光灯");
|
||||
I18N.Add("Remove some build conditions", "Remove some build conditions", "移除部分不影响游戏逻辑的建造条件");
|
||||
I18N.Add("Remove build range limit", "Remove build range limit", "移除建造距离限制");
|
||||
I18N.Add("Larger area for upgrade and dismantle", "Larger area for upgrade and dismantle", "提升范围升级和拆除的最大区域");
|
||||
I18N.Add("Larger area for terraform", "Larger area for terraform", "提升范围铺设地基的最大区域");
|
||||
I18N.Add("Enable player actions in globe view", "Enable player actions in globe view", "在行星视图中允许玩家操作");
|
||||
I18N.Add("Enhanced count control for hand-make", "Enhanced count control for hand-make", "手动制造物品的数量控制改进");
|
||||
I18N.Add("Enhanced count control for hand-make tips", "Maximum count is increased to 1000.\nHold Ctrl/Shift/Alt to change the count rapidly.", "最大数量提升至1000\n按住Ctrl/Shift/Alt可快速改变数量");
|
||||
I18N.Add("Initialize This Planet", "Initialize this planet", "初始化本行星");
|
||||
I18N.Add("Dismantle All Buildings", "Dismantle all buildings", "拆除所有建筑");
|
||||
I18N.Add("Stop ejectors when available nodes are all filled up", "Stop ejectors when available nodes are all filled up", "可用节点全部造完时停止弹射");
|
||||
I18N.Add("Construct only nodes but frames", "Construct only nodes but frames", "只造节点不造框架");
|
||||
I18N.Add("Initialize Dyson Sphere", "Initialize Dyson Sphere", "初始化戴森球");
|
||||
I18N.Add("Click to dismantle selected layer", "Click to dismantle selected layer", "点击拆除对应的戴森壳");
|
||||
I18N.Apply();
|
||||
MyConfigWindow.OnUICreated += CreateUI;
|
||||
}
|
||||
|
||||
private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
|
||||
{
|
||||
_configWindow = wnd;
|
||||
_windowTrans = trans;
|
||||
var tab1 = wnd.AddTab(_windowTrans, "UXAssist");
|
||||
var x = 0f;
|
||||
var y = 10f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, FactoryPatch.UnlimitInteractiveEnabled, "Unlimited interactive range");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, FactoryPatch.NightLightEnabled, "Night Light");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, FactoryPatch.RemoveSomeConditionEnabled, "Remove some build conditions");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, FactoryPatch.RemoveBuildRangeLimitEnabled, "Remove build range limit");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, FactoryPatch.LargerAreaForUpgradeAndDismantleEnabled, "Larger area for upgrade and dismantle");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, FactoryPatch.LargerAreaForTerraformEnabled, "Larger area for terraform");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, PlanetPatch.PlayerActionsInGlobeViewEnabled, "Enable player actions in globe view");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, PlayerPatch.EnhancedMechaForgeCountControlEnabled, "Enhanced count control for hand-make");
|
||||
x = 240f;
|
||||
y += 6f;
|
||||
MyWindow.AddTipsButton(x, y, tab1, "Enhanced count control for hand-make", "Enhanced count control for hand-make tips", "enhanced-count-control-tips");
|
||||
x = 0f;
|
||||
y += 30f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, DysonSpherePatch.StopEjectOnNodeCompleteEnabled, "Stop ejectors when available nodes are all filled up");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab1, DysonSpherePatch.OnlyConstructNodesEnabled, "Construct only nodes but frames");
|
||||
x = 400f;
|
||||
y = 10f;
|
||||
wnd.AddButton(x, y, tab1, "Initialize This Planet", 16, "button-init-planet", () => { PlanetFunctions.RecreatePlanet(true); });
|
||||
y += 36f;
|
||||
wnd.AddButton(x, y, tab1, "Dismantle All Buildings", 16, "button-dismantle-all", () => { PlanetFunctions.DismantleAll(false); });
|
||||
y += 36f;
|
||||
y += 36f;
|
||||
wnd.AddButton(x, y, tab1, "Initialize Dyson Sphere", 16, "init-dyson-sphere", () => { DysonSpherePatch.InitCurrentDysonSphere(-1); });
|
||||
y += 36f;
|
||||
MyWindow.AddText(x, y, tab1, "Click to dismantle selected layer", 16, "text-dismantle-layer");
|
||||
y += 26f;
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var id = i + 1;
|
||||
var btn = wnd.AddFlatButton(x, y, tab1, id.ToString(), 12, "dismantle-layer-" + id, () => { DysonSpherePatch.InitCurrentDysonSphere(id); });
|
||||
((RectTransform)btn.transform).sizeDelta = new Vector2(40f, 20f);
|
||||
_dysonLayerBtn[i] = btn;
|
||||
if (i == 4)
|
||||
{
|
||||
x -= 160f;
|
||||
y += 20f;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += 40f;
|
||||
}
|
||||
}
|
||||
x = 400f;
|
||||
y += 72f;
|
||||
MyKeyBinder.CreateKeyBinder(x, y, tab1, UXAssist.Hotkey, "Hotkey");
|
||||
|
||||
_tab = tab1;
|
||||
}
|
||||
|
||||
private static void UpdateUI()
|
||||
{
|
||||
UpdateDysonShells();
|
||||
}
|
||||
|
||||
private static void UpdateDysonShells()
|
||||
{
|
||||
if (!_tab.gameObject.activeSelf) return;
|
||||
var star = GameMain.localStar;
|
||||
if (star != null)
|
||||
{
|
||||
var dysonSpheres = GameMain.data?.dysonSpheres;
|
||||
if (dysonSpheres?[star.index] != null)
|
||||
{
|
||||
var ds = dysonSpheres[star.index];
|
||||
for (var i = 1; i <= 10; i++)
|
||||
{
|
||||
var layer = ds.layersIdBased[i];
|
||||
_dysonLayerBtn[i - 1].button.interactable = layer != null && layer.id == i;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
_dysonLayerBtn[i].button.interactable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,89 +28,27 @@ public class UXAssist : BaseUnityPlugin
|
||||
private void Awake()
|
||||
{
|
||||
Hotkey = Config.Bind("General", "Shortcut", KeyboardShortcut.Deserialize("BackQuote + LeftAlt"), "Shortcut to open config window");
|
||||
/*
|
||||
DevShortcuts.Enabled = Config.Bind("General", "DevShortcuts", false, "Enable DevMode shortcuts");
|
||||
AbnormalDisabler.Enabled = Config.Bind("General", "DisableAbnormalChecks", false,
|
||||
"disable all abnormal checks");
|
||||
TechPatch.Enabled = Config.Bind("General", "UnlockTech", false,
|
||||
"Unlock clicked tech by holding key-modifilers(Shift/Alt/Ctrl)");
|
||||
FactoryPatch.ImmediateEnabled = Config.Bind("Build", "ImmediateBuild", false,
|
||||
"Build immediately");
|
||||
FactoryPatch.ArchitectModeEnabled = Config.Bind("Build", "Architect", false,
|
||||
"Architect Mode");
|
||||
FactoryPatch.UnlimitInteractiveEnabled = Config.Bind("Build", "UnlimitInteractive", false,
|
||||
FactoryPatch.UnlimitInteractiveEnabled = Config.Bind("Factory", "UnlimitInteractive", false,
|
||||
"Unlimit interactive range");
|
||||
FactoryPatch.RemoveSomeConditionEnabled = Config.Bind("Build", "RemoveSomeBuildConditionCheck", false,
|
||||
FactoryPatch.RemoveSomeConditionEnabled = Config.Bind("Factory", "RemoveSomeBuildConditionCheck", false,
|
||||
"Remove part of build condition checks that does not affect game logic");
|
||||
FactoryPatch.NoConditionEnabled = Config.Bind("Build", "BuildWithoutCondition", false,
|
||||
"Build without condition");
|
||||
FactoryPatch.NoCollisionEnabled = Config.Bind("Build", "NoCollision", false,
|
||||
"No collision");
|
||||
FactoryPatch.BeltSignalGeneratorEnabled = Config.Bind("Build", "BeltSignalGenerator", false,
|
||||
"Belt signal generator");
|
||||
FactoryPatch.BeltSignalNumberAltFormat = Config.Bind("Build", "BeltSignalNumberFormat", false,
|
||||
"Belt signal number format alternative format (AAAA=generation speed in minutes, B=proliferate points, C=stack count):\n AAAABC by default\n BCAAAA as alternative");
|
||||
FactoryPatch.BeltSignalCountRecipeEnabled = Config.Bind("Build", "BeltSignalCountRecipe", false,
|
||||
"Belt signal count all raws and intermediates in statistics");
|
||||
FactoryPatch.NightLightEnabled = Config.Bind("Build", "NightLight", false,
|
||||
FactoryPatch.NightLightEnabled = Config.Bind("Factory", "NightLight", false,
|
||||
"Night light");
|
||||
FactoryPatch.RemovePowerSpaceLimitEnabled = Config.Bind("Build", "RemovePowerDistanceLimit", false,
|
||||
"Remove distance limit for wind turbines and geothermals");
|
||||
FactoryPatch.BoostWindPowerEnabled = Config.Bind("Build", "BoostWindPower", false,
|
||||
"Boost wind power");
|
||||
FactoryPatch.BoostSolarPowerEnabled = Config.Bind("Build", "BoostSolarPower", false,
|
||||
"Boost solar power");
|
||||
FactoryPatch.BoostFuelPowerEnabled = Config.Bind("Build", "BoostFuelPower", false,
|
||||
"Boost fuel power");
|
||||
FactoryPatch.BoostGeothermalPowerEnabled = Config.Bind("Build", "BoostGeothermalPower", false,
|
||||
"Boost geothermal power");
|
||||
PlanetFunctions.PlayerActionsInGlobeViewEnabled = Config.Bind("Planet", "PlayerActionsInGlobeView", false,
|
||||
PlanetPatch.PlayerActionsInGlobeViewEnabled = Config.Bind("Planet", "PlayerActionsInGlobeView", false,
|
||||
"Enable player actions in globe view");
|
||||
ResourcePatch.InfiniteResourceEnabled = Config.Bind("Planet", "AlwaysInfiniteResource", false,
|
||||
"always infinite natural resource");
|
||||
ResourcePatch.FastMiningEnabled = Config.Bind("Planet", "FastMining", false,
|
||||
"super-fast mining speed");
|
||||
WaterPumperPatch.Enabled = Config.Bind("Planet", "WaterPumpAnywhere", false,
|
||||
"Can pump water anywhere (while water type is not None)");
|
||||
TerraformPatch.Enabled = Config.Bind("Planet", "TerraformAnyway", false,
|
||||
"Can do terraform without enough sands");
|
||||
FactoryPatch.RemoveBuildRangeLimitEnabled = Config.Bind("Factory", "RemoveBuildRangeLimit", false,
|
||||
"Remove limit for build range and maximum count of drag building belts/buildings\nNote: this does not affect range limit for mecha drones' action");
|
||||
FactoryPatch.LargerAreaForUpgradeAndDismantleEnabled = Config.Bind("Factory", "LargerAreaForUpgradeAndDismantle", false,
|
||||
"Increase maximum area size for upgrade and dismantle to 31x31 (from 11x11)");
|
||||
FactoryPatch.LargerAreaForTerraformEnabled = Config.Bind("Factory", "LargerAreaForTerraform", false,
|
||||
"Increase maximum area size for terraform to 30x30 (from 10x10)\nNote: this may impact game performance while using large area");
|
||||
PlayerPatch.EnhancedMechaForgeCountControlEnabled = Config.Bind("Player", "EnhancedMechaForgeCountControl", false,
|
||||
"Enhanced count control for hand-make, increases maximum of count to 1000, and you can hold Ctrl/Shift/Alt to change the count rapidly");
|
||||
DysonSpherePatch.StopEjectOnNodeCompleteEnabled = Config.Bind("DysonSphere", "StopEjectOnNodeComplete", false,
|
||||
"Stop ejectors when available nodes are all filled up");
|
||||
DysonSpherePatch.OnlyConstructNodesEnabled = Config.Bind("DysonSphere", "OnlyConstructNodes", false,
|
||||
"Construct only nodes but frames");
|
||||
DysonSpherePatch.SkipBulletEnabled = Config.Bind("DysonSphere", "SkipBullet", false,
|
||||
"Skip bullet");
|
||||
DysonSpherePatch.SkipAbsorbEnabled = Config.Bind("DysonSphere", "SkipAbsorb", false,
|
||||
"Skip absorption");
|
||||
DysonSpherePatch.QuickAbsorbEnabled = Config.Bind("DysonSphere", "QuickAbsorb", false,
|
||||
"Quick absorb");
|
||||
DysonSpherePatch.EjectAnywayEnabled = Config.Bind("DysonSphere", "EjectAnyway", false,
|
||||
"Eject anyway");
|
||||
DysonSpherePatch.OverclockEjectorEnabled = Config.Bind("DysonSphere", "OverclockEjector", false,
|
||||
"Overclock ejector");
|
||||
DysonSpherePatch.OverclockSiloEnabled = Config.Bind("DysonSphere", "OverclockSilo", false,
|
||||
"Overclock silo");
|
||||
BirthPlanetPatch.SitiVeinsOnBirthPlanet = Config.Bind("Birth", "SiTiVeinsOnBirthPlanet", false,
|
||||
"Silicon/Titanium on birth planet");
|
||||
BirthPlanetPatch.FireIceOnBirthPlanet = Config.Bind("Birth", "FireIceOnBirthPlanet", false,
|
||||
"Fire ice on birth planet");
|
||||
BirthPlanetPatch.KimberliteOnBirthPlanet = Config.Bind("Birth", "KimberliteOnBirthPlanet", false,
|
||||
"Kimberlite on birth planet");
|
||||
BirthPlanetPatch.FractalOnBirthPlanet = Config.Bind("Birth", "FractalOnBirthPlanet", false,
|
||||
"Fractal silicon on birth planet");
|
||||
BirthPlanetPatch.OrganicOnBirthPlanet = Config.Bind("Birth", "OrganicOnBirthPlanet", false,
|
||||
"Organic crystal on birth planet");
|
||||
BirthPlanetPatch.OpticalOnBirthPlanet = Config.Bind("Birth", "OpticalOnBirthPlanet", false,
|
||||
"Optical grating crystal on birth planet");
|
||||
BirthPlanetPatch.SpiniformOnBirthPlanet = Config.Bind("Birth", "SpiniformOnBirthPlanet", false,
|
||||
"Spiniform stalagmite crystal on birth planet");
|
||||
BirthPlanetPatch.UnipolarOnBirthPlanet = Config.Bind("Birth", "UnipolarOnBirthPlanet", false,
|
||||
"Unipolar magnet on birth planet");
|
||||
BirthPlanetPatch.FlatBirthPlanet = Config.Bind("Birth", "FlatBirthPlanet", false,
|
||||
"Birth planet is solid flat (no water at all)");
|
||||
BirthPlanetPatch.HighLuminosityBirthStar = Config.Bind("Birth", "HighLuminosityBirthStar", false,
|
||||
"Birth star has high luminosity");
|
||||
*/
|
||||
|
||||
I18N.Init();
|
||||
I18N.Add("UXAssist Config", "UXAssist Config", "UX助手设置");
|
||||
I18N.Apply();
|
||||
@@ -120,34 +58,19 @@ public class UXAssist : BaseUnityPlugin
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(UXAssist));
|
||||
|
||||
UIConfigWindow.Init();
|
||||
/*
|
||||
DevShortcuts.Init();
|
||||
AbnormalDisabler.Init();
|
||||
TechPatch.Init();
|
||||
FactoryPatch.Init();
|
||||
PlanetFunctions.Init();
|
||||
ResourcePatch.Init();
|
||||
WaterPumperPatch.Init();
|
||||
TerraformPatch.Init();
|
||||
PlanetPatch.Init();
|
||||
PlayerPatch.Init();
|
||||
DysonSpherePatch.Init();
|
||||
BirthPlanetPatch.Init();
|
||||
*/
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
/*
|
||||
BirthPlanetPatch.Uninit();
|
||||
DysonSpherePatch.Uninit();
|
||||
TerraformPatch.Uninit();
|
||||
WaterPumperPatch.Uninit();
|
||||
ResourcePatch.Uninit();
|
||||
PlanetFunctions.Uninit();
|
||||
PlayerPatch.Uninit();
|
||||
PlanetPatch.Uninit();
|
||||
FactoryPatch.Uninit();
|
||||
TechPatch.Uninit();
|
||||
AbnormalDisabler.Uninit();
|
||||
DevShortcuts.Uninit();
|
||||
*/
|
||||
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
_windowPatch?.UnpatchSelf();
|
||||
@@ -159,12 +82,12 @@ public class UXAssist : BaseUnityPlugin
|
||||
if (VFInput.inputing) return;
|
||||
if (Hotkey.Value.IsDown()) ToggleConfigWindow();
|
||||
}
|
||||
/*
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
FactoryPatch.NightLight.LateUpdate();
|
||||
}
|
||||
*/
|
||||
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(UIRoot), nameof(UIRoot.OpenMainMenuUI))]
|
||||
public static void UIRoot_OpenMainMenuUI_Postfix()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user