diff --git a/MechaDronesTweaks/MechaDronesTweaks.cs b/MechaDronesTweaks/MechaDronesTweaks.cs index ad01d3a..ae4e48c 100644 --- a/MechaDronesTweaks/MechaDronesTweaks.cs +++ b/MechaDronesTweaks/MechaDronesTweaks.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection.Emit; using BepInEx; using BepInEx.Configuration; @@ -36,9 +37,12 @@ public class MechaDronesTweaksPlugin : BaseUnityPlugin { MechaDronesTweaks.UseFixedSpeed = Config.Bind("MechaDrones", "UseFixedSpeed", MechaDronesTweaks.UseFixedSpeed, "Use fixed speed for mecha drones").Value; + MechaDronesTweaks.SkipStage1 = Config.Bind("MechaDrones", "SkipStage1", + MechaDronesTweaks.SkipStage1, + "Skip mecha drones' 1st stage (flying away from mecha in ~1/3 speed for several frames)").Value; MechaDronesTweaks.RemoveSpeedLimitForStage1 = Config.Bind("MechaDrones", "RemoveSpeedLimitForStage1", MechaDronesTweaks.RemoveSpeedLimitForStage1, - "Remove speed limit for 1st stage (flying away from mecha in ~1/3 speed for several frames)").Value; + "Remove speed limit for 1st stage (has a speed limit @ ~10m/s originally)").Value; MechaDronesTweaks.FixedSpeed = Config.Bind("MechaDrones", "FixedSpeed", MechaDronesTweaks.FixedSpeed, new ConfigDescription("Fixed speed for mecha drones, working only when UseFixedSpeed is enabled", new AcceptableValueRange(6f, 1000f))).Value; @@ -49,29 +53,94 @@ public class MechaDronesTweaksPlugin : BaseUnityPlugin MechaDronesTweaks.EnergyMultiplier = Config.Bind("MechaDrones", "EnergyMultiplier", MechaDronesTweaks.EnergyMultiplier, new ConfigDescription("Energy consumption multiplier for mecha drones", - new AcceptableValueRange(0.01f, 1f))).Value; + new AcceptableValueRange(0f, 1f))).Value; _harmony.PatchAll(typeof(MechaDronesTweaks)); } } -[HarmonyPatch] public static class MechaDronesTweaks { public static bool UseFixedSpeed = false; + public static bool SkipStage1 = false; public static bool RemoveSpeedLimitForStage1 = true; - public static float FixedSpeed = 500f; - public static float SpeedMultiplier = 5f; + public static float FixedSpeed = 300f; + public static float SpeedMultiplier = 4f; public static float EnergyMultiplier = 0.1f; + [HarmonyTranspiler, HarmonyPatch(typeof(UITechTree), "RefreshDataValueText")] + private static IEnumerable UITechTreeRefreshDataValueText_Transpiler(IEnumerable instructions) + { + foreach (var instr in instructions) + { + if (instr.opcode == OpCodes.Callvirt && instr.OperandIs(AccessTools.Method(typeof(Mecha), "get_droneSpeed"))) + { + if (UseFixedSpeed) + { + yield return new CodeInstruction(OpCodes.Pop); + yield return new CodeInstruction(OpCodes.Ldc_R4, FixedSpeed); + } + else + { + yield return instr; + yield return new CodeInstruction(OpCodes.Ldc_R4, SpeedMultiplier); + yield return new CodeInstruction(OpCodes.Mul); + } + } + else + { + yield return instr; + } + } + } + + [HarmonyTranspiler, HarmonyPatch(typeof(MechaDroneLogic), "UpdateTargets")] + private static IEnumerable MechaUpdateTargets_Transpiler(IEnumerable instructions) + { + if (SkipStage1) + { + var ilist = instructions.ToList(); + for (var i = 0; i < ilist.Count; i++) + { + var instr = ilist[i]; + if (instr.opcode == OpCodes.Ldc_I4_1) + { + var instrNext = ilist[i + 1]; + if (instrNext.opcode == OpCodes.Stfld && + instrNext.OperandIs(AccessTools.Field(typeof(MechaDrone), "stage"))) + { + instr.opcode = OpCodes.Ldc_I4_2; + } + } + yield return instr; + } + } + else + { + foreach (var instr in instructions) + { + yield return instr; + } + } + } + [HarmonyTranspiler, HarmonyPatch(typeof(MechaDroneLogic), "UpdateDrones")] private static IEnumerable MechaUpdateDrones_Transpiler(IEnumerable instructions) { - foreach (var instr in instructions) + if (EnergyMultiplier >= 1f) { - yield return instr; - if (instr.opcode == OpCodes.Ldfld && instr.OperandIs(AccessTools.Field(typeof(Mecha), "droneEnergyPerMeter"))) + foreach (var instr in instructions) { + yield return instr; + } + } + else + { + foreach (var instr in instructions) + { + yield return instr; + if (instr.opcode != OpCodes.Ldfld || + !instr.OperandIs(AccessTools.Field(typeof(Mecha), "droneEnergyPerMeter"))) continue; yield return new CodeInstruction(OpCodes.Ldc_R8, (double)EnergyMultiplier); yield return new CodeInstruction(OpCodes.Mul); } @@ -81,60 +150,75 @@ public static class MechaDronesTweaks [HarmonyTranspiler, HarmonyPatch(typeof(MechaDrone), "Update")] private static IEnumerable MechaDroneUpdate_Transpiler(IEnumerable instructions) { - var lastIsLdarg0 = false; - CodeInstruction lastInstr = null; - foreach (var instr in instructions) + var ilist = instructions.ToList(); + for (var i = 0; i < ilist.Count; i++) { + var instr = ilist[i]; if (instr.opcode == OpCodes.Ldarg_0) { - if (lastIsLdarg0) - { - yield return lastInstr; - continue; - } - - lastIsLdarg0 = true; - lastInstr = instr; - continue; - } - - if (lastIsLdarg0) - { - lastIsLdarg0 = false; - if (instr.opcode == OpCodes.Ldfld && - instr.OperandIs(AccessTools.Field(typeof(MechaDrone), "speed"))) + var instrNext = ilist[i + 1]; + if (instrNext.opcode == OpCodes.Ldfld && + instrNext.OperandIs(AccessTools.Field(typeof(MechaDrone), "speed"))) { if (UseFixedSpeed) { - lastInstr.opcode = OpCodes.Ldc_R4; - lastInstr.operand = FixedSpeed; - yield return lastInstr; + var newInstr = new CodeInstruction(instr) + { + opcode = OpCodes.Ldc_R4, + operand = FixedSpeed + }; + yield return newInstr; } else { - yield return lastInstr; yield return instr; + yield return instrNext; yield return new CodeInstruction(OpCodes.Ldc_R4, SpeedMultiplier); yield return new CodeInstruction(OpCodes.Mul); } - + i++; continue; } - - yield return lastInstr; - yield return instr; - continue; + if (instrNext.opcode == OpCodes.Ldc_R4) + { + if (instrNext.OperandIs(0f)) + { + var instrNext2 = ilist[i + 2]; + if (instrNext2.opcode == OpCodes.Stfld && + instrNext2.OperandIs(AccessTools.Field(typeof(MechaDrone), "progress"))) + { + ilist[i + 3].labels = instr.labels; + i += 2; + continue; + } + } + else if (instrNext.OperandIs(1f)) + { + var instrNext2 = ilist[i + 2]; + if (instrNext2.opcode == OpCodes.Stfld && + instrNext2.OperandIs(AccessTools.Field(typeof(MechaDrone), "progress"))) + { + instrNext.operand = 0f; + yield return instr; + yield return instrNext; + yield return instrNext2; + i += 2; + continue; + } + } + } } - - if (instr.opcode == OpCodes.Ldc_R4) + else if (instr.opcode == OpCodes.Ldc_R4) { if (instr.OperandIs(0.5f)) { - if (FixedSpeed > 59f) + if (UseFixedSpeed) { - instr.operand = 0.5f * FixedSpeed / 50f; - yield return instr; - continue; + if (FixedSpeed > 75f) { instr.operand = 0.5f * FixedSpeed / 75f; } + } + else + { + instr.operand = 0.5f * SpeedMultiplier; } } else if (instr.OperandIs(3f)) @@ -143,12 +227,8 @@ public static class MechaDronesTweaks { instr.operand = 10000f; } - - yield return instr; - continue; } } - yield return instr; } } diff --git a/MechaDronesTweaks/README.md b/MechaDronesTweaks/README.md index 47b4714..dcdefc5 100644 --- a/MechaDronesTweaks/README.md +++ b/MechaDronesTweaks/README.md @@ -4,5 +4,33 @@ #### 机甲建设机调整(FastDrones MOD的后继者) ## Usage +* Inspired by [FastDrones](https://dsp.thunderstore.io/package/dkoppstein/FastDrones/), but patching IL codes, consuming less CPU to reduce lags on massive builds especially blueprints' put. +* Does not affect current game-saves, which means: + * All values are patched in memory but written to game-saves so that you can play with normal mecha drone parameters while disabling this MOD. + * You can take benefit from this MOD on any game-saves after enabling this MOD. +* Config entries: + * `UseFixedSpeed` [Default Value: false]: + * If enabled: Use `FixedSpeed` for mecha drones, which makes related Upgrades not used any more. + * If disabled: Use `SpeedMultiplier` for mecha drones. + * `SkipStage1` [Default Value: false]: Skip mecha drones' 1st stage (flying away from mecha in ~1/3 speed for several frames). + * `RemoveSpeedLimitForStage1` [Default Value: true]: Remove speed limit for 1st stage (has a speed limit @ ~10m/s originally). + * `FixedSpeed` [Default Value: 300]: Fixed flying speed for mecha drones. + * `SpeedMultiplier` [Default Value: 4]: Speed multiplier for mecha drones. + * `EnergyMultiplier` [Default Value: 0.1]: Energy consumption multiplier for mecha drones. +* Note: This MOD will disable `FastDrones` if the MOD is installed, to avoid conflict in functions. ## 使用说明 +* 功能参考 [FastDrones](https://dsp.thunderstore.io/package/dkoppstein/FastDrones/),但主要对IL代码进行Patch因此消耗更少的CPU,尤其在大规模建造比如放置蓝图的时候可以大大减少卡顿。 +* 不影响当前游戏存档: + * 所有修改参数都在内存中Patch不会写入存档,禁用此MOD后可恢复正常建设机参数。 + * 启用本MOD后可以在已经游玩的游戏存档上享受参数的改动。 +* 设置选项: + * `UseFixedSpeed` [默认值: false]: + * 启用: 使用 `FixedSpeed`,固定速度,这将覆盖对应机甲建设机速度的升级数值。 + * 禁用: 使用 `SpeedMultiplier` + * `SkipStage1` [默认值: false]: 跳过建设机起飞的第一阶段(以大约1/3速度从机甲身上飞出,持续若干帧). + * `RemoveSpeedLimitForStage1` [默认值: true]: 移除第一阶段的速度限制 (原本大约有10m/s的限制). + * `FixedSpeed` [默认值: 300]: 固定速度。 + * `SpeedMultiplier` [默认值: 4]: 速度倍数。 + * `EnergyMultiplier` [默认值: 0.1]: 能量消耗倍数。 +* 说明: 如果安装了`FastDrones`本MOD会将其禁用避免功能冲突。 diff --git a/MechaDronesTweaks/package/icon.png b/MechaDronesTweaks/package/icon.png new file mode 100644 index 0000000..c1998c4 Binary files /dev/null and b/MechaDronesTweaks/package/icon.png differ diff --git a/README.md b/README.md index 0e70068..1f81b26 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,8 @@ Batch build Orbital Collectors Universe Generator Tweak 宇宙生成参数调节 + +# [MechaDronesTweaks](MechaDronesTweaks) + +Some tweaks for mecha drones(Successor to FastDrones MOD) +机甲建设机调整(FastDrones MOD的后继者)