1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2025-12-09 14:13:31 +08:00

fix various solar sail bugs

This commit is contained in:
2023-10-16 02:59:34 +08:00
parent 6ea66f787d
commit 3379745963

View File

@@ -16,24 +16,29 @@ public static class DysonSpherePatch
public static ConfigEntry<bool> OverclockSiloEnabled; public static ConfigEntry<bool> OverclockSiloEnabled;
private static bool _instantAbsorb; private static bool _instantAbsorb;
private static Harmony _dysonSpherePatch;
public static void Init() public static void Init()
{ {
SkipBulletEnabled.SettingChanged += (_, _) => SkipBulletPatch.Enable(SkipBulletEnabled.Value); SkipBulletEnabled.SettingChanged += (_, _) => SkipBulletPatch.Enable(SkipBulletEnabled.Value);
SkipAbsorbEnabled.SettingChanged += (_, _) => SkipAbsorbPatch.Enable(SkipBulletEnabled.Value); SkipAbsorbEnabled.SettingChanged += (_, _) => SkipAbsorbPatch.Enable(SkipAbsorbEnabled.Value);
QuickAbsorbEnabled.SettingChanged += (_, _) => QuickAbsorbPatch.Enable(QuickAbsorbEnabled.Value); QuickAbsorbEnabled.SettingChanged += (_, _) => QuickAbsorbPatch.Enable(QuickAbsorbEnabled.Value);
EjectAnywayEnabled.SettingChanged += (_, _) => EjectAnywayPatch.Enable(EjectAnywayEnabled.Value); EjectAnywayEnabled.SettingChanged += (_, _) => EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
OverclockEjectorEnabled.SettingChanged += (_, _) => OverclockEjector.Enable(OverclockEjectorEnabled.Value); OverclockEjectorEnabled.SettingChanged += (_, _) => OverclockEjector.Enable(OverclockEjectorEnabled.Value);
OverclockSiloEnabled.SettingChanged += (_, _) => OverclockSilo.Enable(OverclockSiloEnabled.Value); OverclockSiloEnabled.SettingChanged += (_, _) => OverclockSilo.Enable(OverclockSiloEnabled.Value);
SkipBulletPatch.Enable(SkipBulletEnabled.Value); SkipBulletPatch.Enable(SkipBulletEnabled.Value);
SkipAbsorbPatch.Enable(SkipBulletEnabled.Value); SkipAbsorbPatch.Enable(SkipAbsorbEnabled.Value);
QuickAbsorbPatch.Enable(QuickAbsorbEnabled.Value); QuickAbsorbPatch.Enable(QuickAbsorbEnabled.Value);
EjectAnywayPatch.Enable(EjectAnywayEnabled.Value); EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
OverclockEjector.Enable(OverclockEjectorEnabled.Value); OverclockEjector.Enable(OverclockEjectorEnabled.Value);
OverclockSilo.Enable(OverclockSiloEnabled.Value); OverclockSilo.Enable(OverclockSiloEnabled.Value);
_dysonSpherePatch ??= Harmony.CreateAndPatchAll(typeof(DysonSpherePatch));
} }
public static void Uninit() public static void Uninit()
{ {
_dysonSpherePatch?.UnpatchSelf();
_dysonSpherePatch = null;
SkipBulletPatch.Enable(false); SkipBulletPatch.Enable(false);
SkipAbsorbPatch.Enable(false); SkipAbsorbPatch.Enable(false);
QuickAbsorbPatch.Enable(false); QuickAbsorbPatch.Enable(false);
@@ -42,6 +47,40 @@ public static class DysonSpherePatch
OverclockSilo.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 static class SkipBulletPatch private static class SkipBulletPatch
{ {
private static long _sailLifeTime; private static long _sailLifeTime;
@@ -201,16 +240,16 @@ public static class DysonSpherePatch
var llen = sphere.layerCount; var llen = sphere.layerCount;
if (llen > 0) if (llen > 0)
{ {
var lidx = time / 16 % llen; var lidx = ((int)time >> 4) % llen;
for (var i = llen - 1; i >= 0; i--) for (var i = llen - 1; i >= 0; i--)
{ {
var layer = layers[(lidx + i) % llen]; var layer = layers[(lidx + i) % llen];
var nodes = layer.nodePool; var nodes = layer.nodePool;
var nlen = layer.nodeCursor; var nlen = layer.nodeCursor - 1;
var nidx = time % nlen; var nidx = (int)time % nlen;
for (var j = nlen - 1; j >= 0; j--) for (var j = nlen; j > 0; j--)
{ {
var nodeIdx = (nidx + j) % nlen; var nodeIdx = (nidx + j) % nlen + 1;
var node = nodes[nodeIdx]; var node = nodes[nodeIdx];
if (node == null || node.id != nodeIdx || node.sp < node.spMax) continue; if (node == null || node.id != nodeIdx || node.sp < node.spMax) continue;
while (node.cpReqOrder > 0) while (node.cpReqOrder > 0)
@@ -251,46 +290,21 @@ public static class DysonSpherePatch
if (on) if (on)
{ {
_patch ??= Harmony.CreateAndPatchAll(typeof(SkipAbsorbPatch)); _patch ??= Harmony.CreateAndPatchAll(typeof(SkipAbsorbPatch));
return;
} }
else
{
_patch?.UnpatchSelf(); _patch?.UnpatchSelf();
_patch = null; _patch = null;
} }
}
[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] [HarmonyTranspiler]
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.AbsorbSail))] [HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.AbsorbSail))]
private static IEnumerable<CodeInstruction> DysonSwarm_AbsorbSail_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) private static IEnumerable<CodeInstruction> DysonSwarm_AbsorbSail_Transpiler2(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{ {
var matcher = new CodeMatcher(instructions, generator); var matcher = new CodeMatcher(instructions, generator);
var label1 = generator.DefineLabel(); var label1 = generator.DefineLabel();
matcher.MatchForward(false, matcher.MatchForward(false,
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(ExpiryOrder), nameof(ExpiryOrder.index))) new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(ExpiryOrder), nameof(ExpiryOrder.index)))
).Advance(1).RemoveInstructions(matcher.Length - matcher.Pos).Insert( ).Advance(1).RemoveInstructions(matcher.Length - matcher.Pos).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))),
// if (node.ConstructCp() != null) // if (node.ConstructCp() != null)
// { // {
// this.dysonSphere.productRegister[11903]++; // this.dysonSphere.productRegister[11903]++;
@@ -360,25 +374,19 @@ public static class DysonSpherePatch
private static void DoAbsorb(DysonSphereLayer layer, long gameTick) 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 swarm = layer.dysonSphere.swarm;
for (var i = layer.nodeCursor - 1; i > 0; i--) 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--)
{ {
var node = layer.nodePool[i];
if (node == null || node.id != i || node.sp < node.spMax) continue;
var req = node._cpReq;
var ordered = node.cpOrdered;
if (req <= ordered) continue;
if (!swarm.AbsorbSail(node, gameTick)) return; // No more sails can be absorbed if (!swarm.AbsorbSail(node, gameTick)) return; // No more sails can be absorbed
ordered++;
while (req > ordered)
{
if (!swarm.AbsorbSail(node, gameTick))
{
// No more sails can be absorbed
node.cpOrdered = ordered;
return;
}
ordered++;
} }
} }
} }