mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-02-05 04:22:21 +08:00
refactoring UXAssist and CheatEnabler
This commit is contained in:
84
CheatEnabler/Patches/CombatPatch.cs
Normal file
84
CheatEnabler/Patches/CombatPatch.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace CheatEnabler.Patches;
|
||||
|
||||
public static class CombatPatch
|
||||
{
|
||||
public static ConfigEntry<bool> MechaInvincibleEnabled;
|
||||
public static ConfigEntry<bool> BuildingsInvincibleEnabled;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
MechaInvincibleEnabled.SettingChanged += (_, _) => MechaInvincible.Enable(MechaInvincibleEnabled.Value);
|
||||
BuildingsInvincibleEnabled.SettingChanged += (_, _) => BuildingsInvincible.Enable(BuildingsInvincibleEnabled.Value);
|
||||
MechaInvincible.Enable(MechaInvincibleEnabled.Value);
|
||||
BuildingsInvincible.Enable(BuildingsInvincibleEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
BuildingsInvincible.Enable(false);
|
||||
MechaInvincible.Enable(false);
|
||||
}
|
||||
|
||||
private class MechaInvincible: PatchImpl<MechaInvincible>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(Player), nameof(Player.invincible), MethodType.Getter)]
|
||||
private static IEnumerable<CodeInstruction> Player_get_invincible_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.Start().RemoveInstructions(matcher.Length).Insert(
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageGroundObjectByLocalCaster))]
|
||||
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageGroundObjectByRemoteCaster))]
|
||||
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageObject))]
|
||||
private static IEnumerable<CodeInstruction> SkillSystem_DamageObject_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase __originalMethod)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.IsLdarg()),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(SkillTargetLocal), nameof(SkillTargetLocal.type))),
|
||||
new CodeMatch(OpCodes.Ldc_I4_6),
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Bne_Un || ci.opcode == OpCodes.Bne_Un_S)
|
||||
);
|
||||
matcher.Repeat(m => m.Advance(4).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Starg_S, __originalMethod.Name == "DamageObject" ? 1 : 2)
|
||||
));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class BuildingsInvincible: PatchImpl<BuildingsInvincible>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageGroundObjectByLocalCaster))]
|
||||
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageGroundObjectByRemoteCaster))]
|
||||
private static IEnumerable<CodeInstruction> SkillSystem_DamageObject_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.IsLdarg()),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(SkillTargetLocal), nameof(SkillTargetLocal.type))),
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Brtrue || ci.opcode == OpCodes.Brtrue_S),
|
||||
new CodeMatch(OpCodes.Ldarg_1)
|
||||
).Advance(3).Insert(
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Starg_S, 2)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
522
CheatEnabler/Patches/DysonSpherePatch.cs
Normal file
522
CheatEnabler/Patches/DysonSpherePatch.cs
Normal file
@@ -0,0 +1,522 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace CheatEnabler.Patches;
|
||||
|
||||
public static class DysonSpherePatch
|
||||
{
|
||||
public static ConfigEntry<bool> SkipBulletEnabled;
|
||||
public static ConfigEntry<bool> SkipAbsorbEnabled;
|
||||
public static ConfigEntry<bool> QuickAbsorbEnabled;
|
||||
public static ConfigEntry<bool> EjectAnywayEnabled;
|
||||
public static ConfigEntry<bool> OverclockEjectorEnabled;
|
||||
public static ConfigEntry<bool> OverclockSiloEnabled;
|
||||
private static bool _instantAbsorb;
|
||||
|
||||
private static Harmony _dysonSpherePatch;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
SkipBulletEnabled.SettingChanged += (_, _) => SkipBulletPatch.Enable(SkipBulletEnabled.Value);
|
||||
SkipAbsorbEnabled.SettingChanged += (_, _) => SkipAbsorbPatch.Enable(SkipAbsorbEnabled.Value);
|
||||
QuickAbsorbEnabled.SettingChanged += (_, _) => QuickAbsorbPatch.Enable(QuickAbsorbEnabled.Value);
|
||||
EjectAnywayEnabled.SettingChanged += (_, _) => EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
|
||||
OverclockEjectorEnabled.SettingChanged += (_, _) => OverclockEjector.Enable(OverclockEjectorEnabled.Value);
|
||||
OverclockSiloEnabled.SettingChanged += (_, _) => OverclockSilo.Enable(OverclockSiloEnabled.Value);
|
||||
SkipBulletPatch.Enable(SkipBulletEnabled.Value);
|
||||
SkipAbsorbPatch.Enable(SkipAbsorbEnabled.Value);
|
||||
QuickAbsorbPatch.Enable(QuickAbsorbEnabled.Value);
|
||||
EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
|
||||
OverclockEjector.Enable(OverclockEjectorEnabled.Value);
|
||||
OverclockSilo.Enable(OverclockSiloEnabled.Value);
|
||||
_dysonSpherePatch ??= Harmony.CreateAndPatchAll(typeof(DysonSpherePatch));
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
_dysonSpherePatch?.UnpatchSelf();
|
||||
_dysonSpherePatch = null;
|
||||
SkipBulletPatch.Enable(false);
|
||||
SkipAbsorbPatch.Enable(false);
|
||||
QuickAbsorbPatch.Enable(false);
|
||||
EjectAnywayPatch.Enable(false);
|
||||
OverclockEjector.Enable(false);
|
||||
OverclockSilo.Enable(false);
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.OrderConstructCp))]
|
||||
private static IEnumerable<CodeInstruction> DysonNode_OrderConstructCp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(DysonSwarm), nameof(DysonSwarm.AbsorbSail)))
|
||||
).Advance(1).SetInstructionAndAdvance(
|
||||
new CodeInstruction(OpCodes.Pop)
|
||||
).Insert(
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.AbsorbSail))]
|
||||
private static IEnumerable<CodeInstruction> DysonSwarm_AbsorbSail_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(ExpiryOrder), nameof(ExpiryOrder.time)))
|
||||
).Advance(1).Insert(
|
||||
// node.cpOrdered = node.cpOrdered + 1;
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode.cpOrdered))),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Add),
|
||||
new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(DysonNode), nameof(DysonNode.cpOrdered)))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
private class SkipBulletPatch: PatchImpl<SkipBulletPatch>
|
||||
{
|
||||
private static long _sailLifeTime;
|
||||
private static DysonSailCache[][] _sailsCache;
|
||||
private static int[] _sailsCacheLen, _sailsCacheCapacity;
|
||||
|
||||
private struct DysonSailCache
|
||||
{
|
||||
public DysonSail Sail;
|
||||
public int OrbitId;
|
||||
|
||||
public void FromData(in VectorLF3 delta1, in VectorLF3 delta2, int orbitId)
|
||||
{
|
||||
Sail.px = (float)delta1.x;
|
||||
Sail.py = (float)delta1.y;
|
||||
Sail.pz = (float)delta1.z;
|
||||
Sail.vx = (float)delta2.x;
|
||||
Sail.vy = (float)delta2.y;
|
||||
Sail.vz = (float)delta2.z;
|
||||
Sail.gs = 1f;
|
||||
OrbitId = orbitId;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
UpdateSailLifeTime();
|
||||
UpdateSailsCacheForThisGame();
|
||||
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
|
||||
}
|
||||
|
||||
private static void UpdateSailLifeTime()
|
||||
{
|
||||
if (GameMain.history == null) return;
|
||||
_sailLifeTime = (long)(GameMain.history.solarSailLife * 60f + 0.1f);
|
||||
}
|
||||
|
||||
private static void UpdateSailsCacheForThisGame()
|
||||
{
|
||||
var galaxy = GameMain.data?.galaxy;
|
||||
if (galaxy == null) return;
|
||||
var starCount = GameMain.data.galaxy.starCount;
|
||||
_sailsCache = new DysonSailCache[starCount][];
|
||||
_sailsCacheLen = new int[starCount];
|
||||
_sailsCacheCapacity = new int[starCount];
|
||||
Array.Clear(_sailsCacheLen, 0, starCount);
|
||||
Array.Clear(_sailsCacheCapacity, 0, starCount);
|
||||
}
|
||||
|
||||
private static void SetSailsCacheCapacity(int index, int capacity)
|
||||
{
|
||||
var newCache = new DysonSailCache[capacity];
|
||||
var len = _sailsCacheLen[index];
|
||||
if (len > 0)
|
||||
{
|
||||
Array.Copy(_sailsCache[index], newCache, len);
|
||||
}
|
||||
_sailsCache[index] = newCache;
|
||||
_sailsCacheCapacity[index] = capacity;
|
||||
}
|
||||
|
||||
private static void GameMain_Begin_Postfix()
|
||||
{
|
||||
UpdateSailsCacheForThisGame();
|
||||
UpdateSailLifeTime();
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(GameHistoryData), nameof(GameHistoryData.UnlockTechFunction))]
|
||||
private static void GameHistoryData_SetForNewGame_Postfix(int func)
|
||||
{
|
||||
if (func == 12)
|
||||
{
|
||||
UpdateSailLifeTime();
|
||||
}
|
||||
}
|
||||
|
||||
[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,
|
||||
new CodeMatch(OpCodes.Ldc_R4, 10f)
|
||||
).Advance(2);
|
||||
var start = matcher.Pos;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Pop)
|
||||
).Advance(1);
|
||||
var end = matcher.Pos;
|
||||
matcher.Start().Advance(start).RemoveInstructions(end - start).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_2),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.orbitId))),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 8),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 10),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(SkipBulletPatch), nameof(SkipBulletPatch.AddDysonSail)))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
private static void AddDysonSail(DysonSwarm swarm, int orbitId, VectorLF3 uPos, VectorLF3 endVec)
|
||||
{
|
||||
var index = swarm.starData.index;
|
||||
var delta1 = endVec - swarm.starData.uPosition;
|
||||
var delta2 = VectorLF3.Cross(endVec - uPos, swarm.orbits[orbitId].up).normalized * Math.Sqrt(swarm.dysonSphere.gravity / swarm.orbits[orbitId].radius);
|
||||
lock (swarm)
|
||||
{
|
||||
var cache = _sailsCache[index];
|
||||
var len = _sailsCacheLen[index];
|
||||
if (cache == null)
|
||||
{
|
||||
SetSailsCacheCapacity(index, 256);
|
||||
cache = _sailsCache[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
var capacity = _sailsCacheCapacity[index];
|
||||
if (len >= capacity)
|
||||
{
|
||||
SetSailsCacheCapacity(index, capacity * 2);
|
||||
cache = _sailsCache[index];
|
||||
}
|
||||
}
|
||||
_sailsCacheLen[index] = len + 1;
|
||||
cache[len].FromData(delta1, delta2 + RandomTable.SphericNormal(ref swarm.randSeed, 0.5), orbitId);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(DysonSwarm), "GameTick")]
|
||||
public static void DysonSwarm_GameTick_Prefix(DysonSwarm __instance, long time)
|
||||
{
|
||||
var index = __instance.starData.index;
|
||||
var len = _sailsCacheLen[index];
|
||||
if (len == 0) return;
|
||||
_sailsCacheLen[index] = 0;
|
||||
var cache = _sailsCache[index];
|
||||
var deadline = time + _sailLifeTime;
|
||||
var idx = len - 1;
|
||||
if (_instantAbsorb)
|
||||
{
|
||||
var sphere = __instance.dysonSphere;
|
||||
var layers = sphere.layersSorted;
|
||||
var llen = sphere.layerCount;
|
||||
var sphereProductRegister = sphere.productRegister;
|
||||
var sphereConsumeRegister = sphere.consumeRegister;
|
||||
if (llen > 0)
|
||||
{
|
||||
var lidx = ((int)time >> 4) % llen;
|
||||
for (var i = llen - 1; i >= 0; i--)
|
||||
{
|
||||
var layer = layers[(lidx + i) % llen];
|
||||
var nodes = layer.nodePool;
|
||||
var nlen = layer.nodeCursor - 1;
|
||||
if (nlen <= 0) continue;
|
||||
var nidx = (int)time % nlen;
|
||||
for (var j = nlen; j > 0; j--)
|
||||
{
|
||||
var nodeIdx = (nidx + j) % nlen + 1;
|
||||
var node = nodes[nodeIdx];
|
||||
if (node == null || node.id != nodeIdx || node.sp < node.spMax) continue;
|
||||
while (node.cpReqOrder > 0)
|
||||
{
|
||||
node.cpOrdered++;
|
||||
if (node.ConstructCp() == null) break;
|
||||
if (idx == 0)
|
||||
{
|
||||
sphereProductRegister[11901] += len;
|
||||
sphereConsumeRegister[11901] += len;
|
||||
sphereProductRegister[11903] += len;
|
||||
return;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var absorbCnt = len - 1 - idx;
|
||||
if (absorbCnt > 0)
|
||||
{
|
||||
sphereProductRegister[11901] += absorbCnt;
|
||||
sphereConsumeRegister[11901] += absorbCnt;
|
||||
sphereProductRegister[11903] += absorbCnt;
|
||||
}
|
||||
}
|
||||
for (; idx >= 0; idx--)
|
||||
{
|
||||
__instance.AddSolarSail(cache[idx].Sail, cache[idx].OrbitId, deadline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SkipAbsorbPatch: PatchImpl<SkipAbsorbPatch>
|
||||
{
|
||||
protected override void OnEnable()
|
||||
{
|
||||
_instantAbsorb = QuickAbsorbEnabled.Value;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
_instantAbsorb = false;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.AbsorbSail))]
|
||||
private static IEnumerable<CodeInstruction> DysonSwarm_AbsorbSail_Transpiler2(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(ExpiryOrder), nameof(ExpiryOrder.index)))
|
||||
).Advance(1).RemoveInstructions(matcher.Length - matcher.Pos).Insert(
|
||||
// if (node.ConstructCp() != null)
|
||||
// {
|
||||
// this.dysonSphere.productRegister[11903]++;
|
||||
// }
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(DysonNode), nameof(DysonNode.ConstructCp))),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label1),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSwarm), nameof(DysonSwarm.dysonSphere))),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(DysonSphere), nameof(DysonSphere.productRegister))),
|
||||
new CodeInstruction(OpCodes.Ldc_I4, 11903),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(int)),
|
||||
new CodeInstruction(OpCodes.Dup),
|
||||
new CodeInstruction(OpCodes.Ldind_I4),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Add),
|
||||
new CodeInstruction(OpCodes.Stind_I4),
|
||||
|
||||
// this.RemoveSolarSail(index);
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(label1),
|
||||
new CodeInstruction(OpCodes.Ldloc_1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(DysonSwarm), nameof(DysonSwarm.RemoveSolarSail))),
|
||||
|
||||
// return false;
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class QuickAbsorbPatch: PatchImpl<QuickAbsorbPatch>
|
||||
{
|
||||
protected override void OnEnable()
|
||||
{
|
||||
_instantAbsorb = SkipAbsorbEnabled.Value;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
_instantAbsorb = false;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DysonSphereLayer), nameof(DysonSphereLayer.GameTick))]
|
||||
private static IEnumerable<CodeInstruction> DysonSphereLayer_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* Insert absorption functions on beginning */
|
||||
matcher.Start().InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(QuickAbsorbPatch), nameof(QuickAbsorbPatch.DoAbsorb)))
|
||||
).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSphereLayer), nameof(DysonSphereLayer.dysonSphere))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSphere), nameof(DysonSphere.swarm)))
|
||||
).Insert(new CodeInstruction(OpCodes.Ret));
|
||||
/* Insert a RETURN before old absorption functions */
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
private static void DoAbsorb(DysonSphereLayer layer, long gameTick)
|
||||
{
|
||||
var nodeCount = layer.nodeCursor - 1;
|
||||
if (nodeCount <= 0) return;
|
||||
var nodes = layer.nodePool;
|
||||
var swarm = layer.dysonSphere.swarm;
|
||||
var delta = ((int)gameTick >> 6) % nodeCount;
|
||||
for (var i = nodeCount - ((int)gameTick & 0x3F); i > 0; i -= 0x40)
|
||||
{
|
||||
var idx = (delta + i) % nodeCount + 1;
|
||||
var node = nodes[idx];
|
||||
if (node == null || node.id != idx || node.sp < node.spMax) continue;
|
||||
for (var j = node.cpReqOrder; j > 0; j--)
|
||||
{
|
||||
if (!swarm.AbsorbSail(node, gameTick)) return; // No more sails can be absorbed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class EjectAnywayPatch: PatchImpl<EjectAnywayPatch>
|
||||
{
|
||||
[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,
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R8 && Math.Abs((double)instr.operand - 0.08715574) < 0.00000001)
|
||||
);
|
||||
var start = matcher.Pos - 3;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.And)
|
||||
).Advance(1).MatchForward(false,
|
||||
new CodeMatch(OpCodes.And)
|
||||
);
|
||||
var end = matcher.Pos - 2;
|
||||
/* Remove angle checking codes, then add:
|
||||
* V_13 = this.bulletCount > 0;
|
||||
*/
|
||||
matcher.Start().Advance(start).RemoveInstructions(end - start).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.bulletCount))),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Cgt),
|
||||
new CodeInstruction(OpCodes.Stloc_S, 13)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class OverclockEjector: PatchImpl<OverclockEjector>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
||||
private static IEnumerable<CodeInstruction> EjectAndSiloComponent_InternalUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* Add a multiply to ejector speed */
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_1)
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_I4_S, 10),
|
||||
new CodeInstruction(OpCodes.Mul)
|
||||
).Advance(1);
|
||||
|
||||
/* remove boost part of Sandbox Mode for better performance */
|
||||
var pos = matcher.Pos;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_1)
|
||||
).Advance(1);
|
||||
var end = matcher.Pos;
|
||||
matcher.Start().Advance(pos).RemoveInstructions(end - pos);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIEjectorWindow), nameof(UIEjectorWindow._OnUpdate))]
|
||||
private static IEnumerable<CodeInstruction> UIEjectAndSiloWindow__OnUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* Add a multiply to ejector speed */
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(typeof(Cargo), nameof(Cargo.accTableMilli)))
|
||||
).Advance(-1);
|
||||
var operand = matcher.Operand;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_S, operand)
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_R4, 10f),
|
||||
new CodeInstruction(OpCodes.Mul)
|
||||
).Advance(1);
|
||||
|
||||
/* remove boost part of Sandbox Mode for better performance */
|
||||
var pos = matcher.Pos;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_S, operand)
|
||||
).Advance(1);
|
||||
var end = matcher.Pos;
|
||||
matcher.Start().Advance(pos).RemoveInstructions(end - pos);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class OverclockSilo: PatchImpl<OverclockSilo>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(SiloComponent), nameof(SiloComponent.InternalUpdate))]
|
||||
private static IEnumerable<CodeInstruction> EjectAndSiloComponent_InternalUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* Add a multiply to ejector speed */
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_1)
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_I4_S, 10),
|
||||
new CodeInstruction(OpCodes.Mul)
|
||||
).Advance(1);
|
||||
|
||||
/* remove boost part of Sandbox Mode for better performance */
|
||||
var pos = matcher.Pos;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_1)
|
||||
).Advance(1);
|
||||
var end = matcher.Pos;
|
||||
matcher.Start().Advance(pos).RemoveInstructions(end - pos);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UISiloWindow), nameof(UISiloWindow._OnUpdate))]
|
||||
private static IEnumerable<CodeInstruction> UIEjectAndSiloWindow__OnUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
/* Add a multiply to ejector speed */
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(typeof(Cargo), nameof(Cargo.accTableMilli)))
|
||||
).Advance(-1);
|
||||
var operand = matcher.Operand;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_S, operand)
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_R4, 10f),
|
||||
new CodeInstruction(OpCodes.Mul)
|
||||
).Advance(1);
|
||||
|
||||
/* remove boost part of Sandbox Mode for better performance */
|
||||
var pos = matcher.Pos;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_S, operand)
|
||||
).Advance(1);
|
||||
var end = matcher.Pos;
|
||||
matcher.Start().Advance(pos).RemoveInstructions(end - pos);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
1603
CheatEnabler/Patches/FactoryPatch.cs
Normal file
1603
CheatEnabler/Patches/FactoryPatch.cs
Normal file
File diff suppressed because it is too large
Load Diff
306
CheatEnabler/Patches/GamePatch.cs
Normal file
306
CheatEnabler/Patches/GamePatch.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
using UnityEngine.Bindings;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace CheatEnabler.Patches;
|
||||
|
||||
public static class GamePatch
|
||||
{
|
||||
public static ConfigEntry<bool> DevShortcutsEnabled;
|
||||
public static ConfigEntry<bool> AbnormalDisablerEnabled;
|
||||
public static ConfigEntry<bool> UnlockTechEnabled;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
DevShortcutsEnabled.SettingChanged += (_, _) => DevShortcuts.Enable(DevShortcutsEnabled.Value);
|
||||
AbnormalDisablerEnabled.SettingChanged += (_, _) => AbnormalDisabler.Enable(AbnormalDisablerEnabled.Value);
|
||||
UnlockTechEnabled.SettingChanged += (_, _) => UnlockTech.Enable(UnlockTechEnabled.Value);
|
||||
DevShortcuts.Enable(DevShortcutsEnabled.Value);
|
||||
AbnormalDisabler.Enable(AbnormalDisablerEnabled.Value);
|
||||
UnlockTech.Enable(UnlockTechEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
UnlockTech.Enable(false);
|
||||
AbnormalDisabler.Enable(false);
|
||||
DevShortcuts.Enable(false);
|
||||
}
|
||||
|
||||
public class AbnormalDisabler : PatchImpl<AbnormalDisabler>
|
||||
{
|
||||
private static Dictionary<int, AbnormalityDeterminator> _savedDeterminators;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
if (_savedDeterminators == null) return;
|
||||
var abnormalLogic = GameMain.gameScenario.abnormalityLogic;
|
||||
foreach (var p in _savedDeterminators)
|
||||
{
|
||||
p.Value.OnUnregEvent();
|
||||
}
|
||||
|
||||
abnormalLogic.determinators = new Dictionary<int, AbnormalityDeterminator>();
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
if (_savedDeterminators == null) return;
|
||||
var abnormalLogic = GameMain.gameScenario.abnormalityLogic;
|
||||
abnormalLogic.determinators = _savedDeterminators;
|
||||
foreach (var p in _savedDeterminators)
|
||||
{
|
||||
p.Value.OnRegEvent();
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyBeforeGameSave")]
|
||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnAssemblerRecipePick")]
|
||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnGameBegin")]
|
||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnMechaForgeTaskComplete")]
|
||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnUnlockTech")]
|
||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnUseConsole")]
|
||||
private static bool DisableAbnormalLogic()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(AbnormalityLogic), "InitDeterminators")]
|
||||
private static void DisableAbnormalDeterminators(AbnormalityLogic __instance)
|
||||
{
|
||||
_savedDeterminators = __instance.determinators;
|
||||
if (!AbnormalDisablerEnabled.Value) return;
|
||||
__instance.determinators = new Dictionary<int, AbnormalityDeterminator>();
|
||||
foreach (var p in _savedDeterminators)
|
||||
{
|
||||
p.Value.OnUnregEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DevShortcuts : PatchImpl<DevShortcuts>
|
||||
{
|
||||
private static PlayerAction_Test _test;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
if (_test != null) _test.active = true;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
if (_test != null) _test.active = false;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.Init))]
|
||||
private static void PlayerController_Init_Postfix(PlayerController __instance)
|
||||
{
|
||||
var cnt = __instance.actions.Length;
|
||||
var newActions = new PlayerAction[cnt + 1];
|
||||
for (var i = 0; i < cnt; i++)
|
||||
{
|
||||
newActions[i] = __instance.actions[i];
|
||||
}
|
||||
|
||||
_test = new PlayerAction_Test();
|
||||
_test.Init(__instance.player);
|
||||
_test.active = DevShortcutsEnabled.Value;
|
||||
newActions[cnt] = _test;
|
||||
__instance.actions = newActions;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(PlayerAction_Test), nameof(PlayerAction_Test.GameTick))]
|
||||
private static void PlayerAction_Test_GameTick_Postfix(PlayerAction_Test __instance)
|
||||
{
|
||||
__instance.Update();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlayerAction_Test), nameof(PlayerAction_Test.Update))]
|
||||
private static IEnumerable<CodeInstruction> PlayerAction_Test_Update_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.End().MatchBack(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerAction_Test), nameof(PlayerAction_Test.active)))
|
||||
);
|
||||
var pos = matcher.Pos;
|
||||
/* Remove Shift+F4 part of the method */
|
||||
matcher.Start().RemoveInstructions(pos).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(GameMain), "get_sandboxToolsEnabled")),
|
||||
new CodeMatch(OpCodes.Ldc_I4_0),
|
||||
new CodeMatch(OpCodes.Ceq)
|
||||
);
|
||||
var labels = matcher.Labels;
|
||||
matcher.SetInstructionAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1).WithLabels(labels)
|
||||
).RemoveInstructions(2);
|
||||
/* Remove Ctrl+A */
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(instr => (instr.opcode == OpCodes.Ldc_I4_S || instr.opcode == OpCodes.Ldc_I4) && instr.OperandIs(0x61)),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(UnityEngine.Input), nameof(UnityEngine.Input.GetKeyDown), [typeof(UnityEngine.KeyCode)]))
|
||||
);
|
||||
labels = matcher.Labels;
|
||||
matcher.Labels = null;
|
||||
matcher.RemoveInstructions(2);
|
||||
matcher.Opcode = OpCodes.Br;
|
||||
matcher.Labels = labels;
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(GameCamera), nameof(GameCamera.FrameLogic))]
|
||||
private static IEnumerable<CodeInstruction> GameCamera_Logic_Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameCamera), nameof(GameCamera.finalPoser))),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(CameraPoser), nameof(CameraPoser.cameraPose)))
|
||||
);
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = null;
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||
Transpilers.EmitDelegate((GameCamera camera) =>
|
||||
{
|
||||
if (PlayerAction_Test.lockCam)
|
||||
{
|
||||
camera.finalPoser.cameraPose = PlayerAction_Test.camPose;
|
||||
}
|
||||
})
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
public class UnlockTech: PatchImpl<UnlockTech>
|
||||
{
|
||||
private static void UnlockTechRecursive(GameHistoryData history, [NotNull] TechProto techProto, int maxLevel = 10000)
|
||||
{
|
||||
var techStates = history.techStates;
|
||||
var techID = techProto.ID;
|
||||
if (techStates == null || !techStates.TryGetValue(techID, out var value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.unlocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var maxLvl = Math.Min(maxLevel < 0 ? value.curLevel - maxLevel - 1 : maxLevel, value.maxLevel);
|
||||
|
||||
foreach (var preid in techProto.PreTechs)
|
||||
{
|
||||
var preProto = LDB.techs.Select(preid);
|
||||
if (preProto != null)
|
||||
UnlockTechRecursive(history, preProto, techProto.PreTechsMax ? 10000 : -1);
|
||||
}
|
||||
|
||||
foreach (var preid in techProto.PreTechsImplicit)
|
||||
{
|
||||
var preProto = LDB.techs.Select(preid);
|
||||
if (preProto != null)
|
||||
UnlockTechRecursive(history, preProto, techProto.PreTechsMax ? 10000 : -1);
|
||||
}
|
||||
|
||||
if (value.curLevel < techProto.Level) value.curLevel = techProto.Level;
|
||||
while (value.curLevel <= maxLvl)
|
||||
{
|
||||
if (value.curLevel == 0)
|
||||
{
|
||||
foreach (var recipe in techProto.UnlockRecipes)
|
||||
{
|
||||
history.UnlockRecipe(recipe);
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < techProto.UnlockFunctions.Length; j++)
|
||||
{
|
||||
history.UnlockTechFunction(techProto.UnlockFunctions[j], techProto.UnlockValues[j], value.curLevel);
|
||||
}
|
||||
|
||||
for (var k = 0; k < techProto.AddItems.Length; k++)
|
||||
{
|
||||
history.GainTechAwards(techProto.AddItems[k], techProto.AddItemCounts[k]);
|
||||
}
|
||||
|
||||
value.curLevel++;
|
||||
}
|
||||
|
||||
value.unlocked = maxLvl >= value.maxLevel;
|
||||
value.curLevel = value.unlocked ? maxLvl : maxLvl + 1;
|
||||
value.hashNeeded = techProto.GetHashNeeded(value.curLevel);
|
||||
value.hashUploaded = value.unlocked ? value.hashNeeded : 0;
|
||||
techStates[techID] = value;
|
||||
history.RegFeatureKey(1000100);
|
||||
history.NotifyTechUnlock(techID, maxLvl, true);
|
||||
}
|
||||
|
||||
private static void OnClickTech(UITechNode node)
|
||||
{
|
||||
var history = GameMain.history;
|
||||
if (VFInput.shift)
|
||||
{
|
||||
if (VFInput.alt) return;
|
||||
if (VFInput.control)
|
||||
UnlockTechRecursive(history, node.techProto, -100);
|
||||
else
|
||||
UnlockTechRecursive(history, node.techProto, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VFInput.control)
|
||||
{
|
||||
if (!VFInput.alt)
|
||||
UnlockTechRecursive(history, node.techProto, -10);
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if (VFInput.alt)
|
||||
{
|
||||
UnlockTechRecursive(history, node.techProto);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
history.VarifyTechQueue();
|
||||
if (history.currentTech != history.techQueue[0])
|
||||
{
|
||||
history.currentTech = history.techQueue[0];
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UITechNode), nameof(UITechNode.OnPointerDown))]
|
||||
private static IEnumerable<CodeInstruction> UITechNode_OnPointerDown_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(UITechNode), nameof(UITechNode.tree))),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(UITechTree), "get_selected"))
|
||||
);
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = null;
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UnlockTech), nameof(UnlockTech.OnClickTech)))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
75
CheatEnabler/Patches/PlanetPatch.cs
Normal file
75
CheatEnabler/Patches/PlanetPatch.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace CheatEnabler.Patches;
|
||||
public static class PlanetPatch
|
||||
{
|
||||
public static ConfigEntry<bool> WaterPumpAnywhereEnabled;
|
||||
public static ConfigEntry<bool> TerraformAnywayEnabled;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
WaterPumpAnywhereEnabled.SettingChanged += (_, _) => WaterPumperPatch.Enable(WaterPumpAnywhereEnabled.Value);
|
||||
TerraformAnywayEnabled.SettingChanged += (_, _) => TerraformAnyway.Enable(TerraformAnywayEnabled.Value);
|
||||
WaterPumperPatch.Enable(WaterPumpAnywhereEnabled.Value);
|
||||
TerraformAnyway.Enable(TerraformAnywayEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
WaterPumperPatch.Enable(false);
|
||||
TerraformAnyway.Enable(false);
|
||||
}
|
||||
|
||||
private class WaterPumperPatch: PatchImpl<WaterPumperPatch>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.CheckBuildConditions))]
|
||||
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.CheckBuildConditions))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_CheckBuildConditions_Transpiler(
|
||||
IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_I4_S && instr.OperandIs((int)EBuildCondition.NeedWater))
|
||||
).Advance(1).MatchForward(false,
|
||||
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_I4_S && instr.OperandIs((int)EBuildCondition.NeedWater))
|
||||
);
|
||||
matcher.Repeat(codeMatcher =>
|
||||
{
|
||||
codeMatcher.SetAndAdvance(OpCodes.Ldc_I4_S, 0);
|
||||
});
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class TerraformAnyway: PatchImpl<TerraformAnyway>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_Reform), nameof(BuildTool_Reform.ReformAction))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_Reform_ReformAction_Patch(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(BuildTool_Reform), nameof(BuildTool_Reform.cursorPointCount))),
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Blt || ci.opcode == OpCodes.Blt_S)
|
||||
).RemoveInstructions(2).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0)
|
||||
).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Player), "get_sandCount"))
|
||||
).Advance(1).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Conv_I8),
|
||||
new CodeMatch(OpCodes.Sub)
|
||||
).Advance(2).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldc_I8, 0L),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Math), "Max", [typeof(long), typeof(long)]))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
68
CheatEnabler/Patches/PlayerPatch.cs
Normal file
68
CheatEnabler/Patches/PlayerPatch.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace CheatEnabler.Patches;
|
||||
|
||||
public static class PlayerPatch
|
||||
{
|
||||
public static ConfigEntry<bool> InstantTeleportEnabled;
|
||||
public static ConfigEntry<bool> WarpWithoutSpaceWarpersEnabled;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
InstantTeleportEnabled.SettingChanged += (_, _) => InstantTeleport.Enable(InstantTeleportEnabled.Value);
|
||||
WarpWithoutSpaceWarpersEnabled.SettingChanged += (_, _) => WarpWithoutSpaceWarpers.Enable(WarpWithoutSpaceWarpersEnabled.Value);
|
||||
InstantTeleport.Enable(InstantTeleportEnabled.Value);
|
||||
WarpWithoutSpaceWarpers.Enable(WarpWithoutSpaceWarpersEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
InstantTeleport.Enable(false);
|
||||
WarpWithoutSpaceWarpers.Enable(false);
|
||||
}
|
||||
|
||||
private class InstantTeleport: PatchImpl<InstantTeleport>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIGlobemap), nameof(UIGlobemap._OnUpdate))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap.DoRightClickFastTravel))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap.OnFastTravelButtonClick))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap.OnScreenClick))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap.SandboxRightClickFastTravelLogic))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap.StartFastTravelToPlanet))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap.StartFastTravelToUPosition))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap.UpdateCursorView))]
|
||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap._OnUpdate))]
|
||||
private static IEnumerable<CodeInstruction> UIGlobemap__OnUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(GameMain), nameof(GameMain.sandboxToolsEnabled)))
|
||||
);
|
||||
matcher.Repeat(cm => cm.SetAndAdvance(OpCodes.Ldc_I4_1, null));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class WarpWithoutSpaceWarpers: PatchImpl<WarpWithoutSpaceWarpers>
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(Mecha), nameof(Mecha.HasWarper))]
|
||||
private static bool Mecha_HasWarper_Prefix(ref bool __result)
|
||||
{
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(Mecha), nameof(Mecha.UseWarper))]
|
||||
private static void Mecha_UseWarper_Postfix(ref bool __result)
|
||||
{
|
||||
__result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
87
CheatEnabler/Patches/ResourcePatch.cs
Normal file
87
CheatEnabler/Patches/ResourcePatch.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using HarmonyLib;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace CheatEnabler.Patches;
|
||||
|
||||
public static class ResourcePatch
|
||||
{
|
||||
public static ConfigEntry<bool> InfiniteResourceEnabled;
|
||||
public static ConfigEntry<bool> FastMiningEnabled;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
InfiniteResourceEnabled.SettingChanged += (_, _) => InfiniteResource.Enable(InfiniteResourceEnabled.Value);
|
||||
FastMiningEnabled.SettingChanged += (_, _) => FastMining.Enable(FastMiningEnabled.Value);
|
||||
InfiniteResource.Enable(InfiniteResourceEnabled.Value);
|
||||
FastMining.Enable(FastMiningEnabled.Value);
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
InfiniteResource.Enable(false);
|
||||
FastMining.Enable(false);
|
||||
}
|
||||
|
||||
private class InfiniteResource: PatchImpl<InfiniteResource>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool))]
|
||||
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))]
|
||||
[HarmonyPatch(typeof(ItemProto), "GetPropValue")]
|
||||
[HarmonyPatch(typeof(PlanetTransport), "GameTick")]
|
||||
[HarmonyPatch(typeof(UIMinerWindow), "_OnUpdate")]
|
||||
[HarmonyPatch(typeof(UIMiningUpgradeLabel), "Update")]
|
||||
[HarmonyPatch(typeof(UIPlanetDetail), "OnPlanetDataSet")]
|
||||
[HarmonyPatch(typeof(UIPlanetDetail), "RefreshDynamicProperties")]
|
||||
[HarmonyPatch(typeof(UIStarDetail), "OnStarDataSet")]
|
||||
[HarmonyPatch(typeof(UIStarDetail), "RefreshDynamicProperties")]
|
||||
[HarmonyPatch(typeof(UIStationStorage), "RefreshValues")]
|
||||
[HarmonyPatch(typeof(UIVeinCollectorPanel), "_OnUpdate")]
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningCostRate)))
|
||||
).Repeat(codeMatcher =>
|
||||
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Pop),
|
||||
new CodeInstruction(OpCodes.Ldc_R4, 0f)
|
||||
)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class FastMining: PatchImpl<FastMining>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool))]
|
||||
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))]
|
||||
[HarmonyPatch(typeof(ItemProto), "GetPropValue")]
|
||||
[HarmonyPatch(typeof(PlanetTransport), "GameTick")]
|
||||
[HarmonyPatch(typeof(UIMinerWindow), "_OnUpdate")]
|
||||
[HarmonyPatch(typeof(UIMiningUpgradeLabel), "Update")]
|
||||
[HarmonyPatch(typeof(UIPlanetDetail), "OnPlanetDataSet")]
|
||||
[HarmonyPatch(typeof(UIPlanetDetail), "RefreshDynamicProperties")]
|
||||
[HarmonyPatch(typeof(UIStarDetail), "OnStarDataSet")]
|
||||
[HarmonyPatch(typeof(UIStarDetail), "RefreshDynamicProperties")]
|
||||
[HarmonyPatch(typeof(UIStationStorage), "RefreshValues")]
|
||||
[HarmonyPatch(typeof(UIVeinCollectorPanel), "_OnUpdate")]
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningSpeedScale)))
|
||||
).Repeat(codeMatcher =>
|
||||
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Pop),
|
||||
new CodeInstruction(OpCodes.Ldc_R4, 2400f)
|
||||
)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user