diff --git a/CheatEnabler/CheatEnabler.cs b/CheatEnabler/CheatEnabler.cs index d55c706..6672f5c 100644 --- a/CheatEnabler/CheatEnabler.cs +++ b/CheatEnabler/CheatEnabler.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using System.Reflection.Emit; using BepInEx; using HarmonyLib; @@ -14,6 +16,11 @@ public class CheatEnabler : BaseUnityPlugin private bool _devShortcuts = true; private bool _disableAbnormalChecks = true; private bool _alwaysInfiniteResource = true; + private bool _waterPumpAnywhere = true; + private static bool _rareVeinsOnBirthPlanet = true; + private static bool _flatBirthPlanet = true; + private static string _unlockTechToMaximumLevel = ""; + private static readonly List TechToUnlock = new(); private void Awake() { @@ -22,6 +29,14 @@ public class CheatEnabler : BaseUnityPlugin "disable all abnormal checks").Value; _alwaysInfiniteResource = Config.Bind("General", "AlwaysInfiniteResource", _alwaysInfiniteResource, "always infinite resource").Value; + _unlockTechToMaximumLevel = Config.Bind("General", "UnlockTechToMaxLevel", _unlockTechToMaximumLevel, + "Unlock listed tech to MaxLevel").Value; + _waterPumpAnywhere = Config.Bind("General", "WaterPumpAnywhere", _waterPumpAnywhere, + "Can pump water anywhere (while water type is not None)").Value; + _rareVeinsOnBirthPlanet = Config.Bind("General", "RareVeinsOnBirthPlanet", _rareVeinsOnBirthPlanet, + "Has rare veins on birth planet (except unipolar magnet)").Value; + _flatBirthPlanet = Config.Bind("General", "FlatBirthPlanet", _flatBirthPlanet, + "Birth planet is solid flat (no water)").Value; if (_devShortcuts) { Harmony.CreateAndPatchAll(typeof(DevShortcuts)); @@ -34,6 +49,26 @@ public class CheatEnabler : BaseUnityPlugin { Harmony.CreateAndPatchAll(typeof(AlwaysInfiniteResource)); } + + foreach (var idstr in _unlockTechToMaximumLevel.Split(',')) + { + if (int.TryParse(idstr, out var id)) + { + TechToUnlock.Add(id); + } + } + if (TechToUnlock.Count > 0) + { + Harmony.CreateAndPatchAll(typeof(UnlockTechOnGameStart)); + } + if (_waterPumpAnywhere) + { + Harmony.CreateAndPatchAll(typeof(WaterPumperCheat)); + } + if (_rareVeinsOnBirthPlanet || _flatBirthPlanet) + { + Harmony.CreateAndPatchAll(typeof(BirthPlanetCheat)); + } } private class DevShortcuts @@ -111,7 +146,7 @@ public class CheatEnabler : BaseUnityPlugin { foreach (var instruction in instructions) { - if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand.Equals(99.5f)) + if (instruction.opcode == OpCodes.Ldc_R4 && instruction.OperandIs(99.5f)) { yield return new CodeInstruction(OpCodes.Ldc_R4, 0f); } @@ -122,4 +157,142 @@ public class CheatEnabler : BaseUnityPlugin } } } -} \ No newline at end of file + + private class UnlockTechOnGameStart + { + [HarmonyPostfix] + [HarmonyPatch(typeof(GameScenarioLogic), "NotifyOnGameBegin")] + private static void UnlockTechPatch() + { + var history = GameMain.history; + if (GameMain.mainPlayer == null || GameMain.mainPlayer.mecha == null) + { + return; + } + foreach (var currentTech in TechToUnlock) + { + UnlockTechRecursive(history, currentTech, 5000); + } + var techQueue = history.techQueue; + if (techQueue == null || techQueue.Length == 0) + { + return; + } + history.VarifyTechQueue(); + if (history.currentTech > 0 && history.currentTech != techQueue[0]) + { + history.AlterCurrentTech(techQueue[0]); + } + } + + private static void UnlockTechRecursive(GameHistoryData history, int currentTech, int maxLevel = 10000) + { + var techStates = history.techStates; + if (techStates == null || !techStates.ContainsKey(currentTech)) + { + return; + } + var techProto = LDB.techs.Select(currentTech); + if (techProto == null) + { + return; + } + var value = techStates[currentTech]; + var maxLvl = Math.Min(maxLevel, value.maxLevel); + if (value.unlocked && value.curLevel >= maxLvl && value.hashUploaded >= value.hashNeeded) + { + return; + } + foreach (var preid in techProto.PreTechs) + { + UnlockTechRecursive(history, preid, maxLevel); + } + + var techQueue = history.techQueue; + if (techQueue != null) + { + for (var i = 0; i < techQueue.Length; i++) + { + if (techQueue[i] == currentTech) + { + techQueue[i] = 0; + } + } + } + + while (value.curLevel <= maxLvl) + { + for (var j = 0; j < techProto.UnlockFunctions.Length; j++) + { + history.UnlockTechFunction(techProto.UnlockFunctions[j], techProto.UnlockValues[j], value.curLevel); + } + value.curLevel++; + } + value.curLevel = maxLvl; + value.unlocked = maxLvl >= value.maxLevel; + value.hashNeeded = techProto.GetHashNeeded(value.curLevel); + value.hashUploaded = maxLvl >= value.maxLevel ? value.hashNeeded : 0; + techStates[currentTech] = value; + } + } + + private class BirthPlanetCheat + { + [HarmonyPostfix, HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")] + private static void VFPreload_InvokeOnLoadWorkEnded_Postfix() + { + var theme = LDB.themes.Select(1); + if (_flatBirthPlanet) + { + theme.Algos[0] = 2; + } + + if (_rareVeinsOnBirthPlanet) + { + theme.VeinSpot[2] = 2; + theme.VeinSpot[3] = 2; + theme.VeinCount[2] = 0.5f; + theme.VeinCount[3] = 0.5f; + theme.VeinOpacity[2] = 0.5f; + theme.VeinOpacity[3] = 0.5f; + theme.RareVeins = theme.RareVeins.Append(8).ToArray(); + theme.RareSettings = theme.RareSettings.Concat(new float[] + { + 0.3f, 0.5f, 0.7f, 0.5f, + 0.3f, 0.5f, 0.7f, 0.5f, + 0.3f, 0.5f, 0.7f, 0.5f, + 0.3f, 0.5f, 0.7f, 0.5f, + 0.3f, 0.5f, 0.7f, 0.5f, + 0.3f, 0.5f, 0.7f, 0.5f, + }).ToArray(); + } + } + } + + private class WaterPumperCheat + { + [HarmonyTranspiler] + [HarmonyPatch(typeof(BuildTool_BlueprintPaste), "CheckBuildConditions")] + [HarmonyPatch(typeof(BuildTool_Click), "CheckBuildConditions")] + private static IEnumerable BuildTool_CheckBuildConditions_Transpiler(IEnumerable instructions) + { + var isFirst = true; + foreach (var instr in instructions) + { + if (instr.opcode == OpCodes.Ldc_I4_S && instr.OperandIs(22)) + { + if (isFirst) + { + isFirst = false; + } + else + { + yield return new CodeInstruction(OpCodes.Ldc_I4_S, 0); + continue; + } + } + yield return instr; + } + } + } +} diff --git a/DSP_Mods.sln b/DSP_Mods.sln index cbb0748..4435c63 100644 --- a/DSP_Mods.sln +++ b/DSP_Mods.sln @@ -14,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OCBatchBuild", "OCBatchBuil EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniverseGenTweaks", "UniverseGenTweaks\UniverseGenTweaks.csproj", "{9534694E-14F0-4498-852D-BBB3FCA986CD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OverclockEverything", "OverclockEverything\OverclockEverything.csproj", "{0168941C-EEA6-49CF-9A67-E829FE06CF9B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -48,5 +50,9 @@ Global {9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|Any CPU.Build.0 = Debug|Any CPU {9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|Any CPU.Build.0 = Release|Any CPU + {0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/OverclockEverything/BeltFix.cs b/OverclockEverything/BeltFix.cs new file mode 100644 index 0000000..0e1a357 --- /dev/null +++ b/OverclockEverything/BeltFix.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Reflection.Emit; +using HarmonyLib; + +namespace OverclockEverything; + +[HarmonyPatch] +public static class BeltFix +{ + private static CodeInstruction[] LdcInstrs = new[] + { + new CodeInstruction(OpCodes.Ldc_I4_0), new CodeInstruction(OpCodes.Ldc_I4_1), new CodeInstruction(OpCodes.Ldc_I4_2), + new CodeInstruction(OpCodes.Ldc_I4_3), new CodeInstruction(OpCodes.Ldc_I4_4), new CodeInstruction(OpCodes.Ldc_I4_5), + new CodeInstruction(OpCodes.Ldc_I4_6), new CodeInstruction(OpCodes.Ldc_I4_7), new CodeInstruction(OpCodes.Ldc_I4_8), + new CodeInstruction(OpCodes.Ldc_I4_S, 9), new CodeInstruction(OpCodes.Ldc_I4_S, 10) + }; + [HarmonyTranspiler, HarmonyPatch(typeof(CargoTraffic), "AlterBeltRenderer")] + public static IEnumerable CargoTraffic_AlterBeltRenderer_Transpiler(IEnumerable instructions) + { + bool lastIsSpeed = false; + foreach (var instr in instructions) + { + if (lastIsSpeed) + { + lastIsSpeed = false; + if (instr.opcode == OpCodes.Ldc_I4_1) + { + yield return LdcInstrs[Patch.beltSpeed[0]]; + } + else if (instr.opcode == OpCodes.Ldc_I4_2) + { + yield return LdcInstrs[Patch.beltSpeed[1]]; + } + else + { + yield return instr; + } + } + else + { + lastIsSpeed = instr.opcode == OpCodes.Ldfld && + instr.OperandIs(AccessTools.Field(typeof(BeltComponent), nameof(BeltComponent.speed))); + yield return instr; + } + } + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ConnGizmoRenderer), "AddBlueprintBeltMajorPoint")] + [HarmonyPatch(typeof(ConnGizmoRenderer), "AddBlueprintBeltPoint")] + [HarmonyPatch(typeof(ConnGizmoRenderer), "AddBlueprintBeltConn")] + public static void ConnGizmoRenderer_AddBlueprintBelt_Prefix(ref ConnGizmoRenderer __instance, ref uint color) + { + var bspeed = Patch.beltSpeed; + color = color >= bspeed[2] ? 3u : color >= bspeed[1] ? 2u : 1u; + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(ConnGizmoRenderer), "Update")] + public static IEnumerable ConnGizmoRenderer_Update_Transpiler(IEnumerable instructions, ILGenerator generator) + { + bool lastIsLdcI4_3 = false; + foreach (var instr in instructions) + { + if (lastIsLdcI4_3) + { + lastIsLdcI4_3 = false; + yield return instr; + if (instr.opcode == OpCodes.Stfld && instr.OperandIs(AccessTools.Field(typeof(ConnGizmoObj), nameof(ConnGizmoObj.color)))) + { + var label1 = generator.DefineLabel(); + var label2 = generator.DefineLabel(); + yield return new CodeInstruction(OpCodes.Ldloc_S, 6); + yield return LdcInstrs[Patch.beltSpeed[1]]; + yield return new CodeInstruction(OpCodes.Bne_Un_S, label1); + yield return new CodeInstruction(OpCodes.Ldloca_S, 0); + yield return new CodeInstruction(OpCodes.Ldc_I4_2); + yield return new CodeInstruction(OpCodes.Stfld, + AccessTools.Field(typeof(ConnGizmoObj), nameof(ConnGizmoObj.color))); + yield return new CodeInstruction(OpCodes.Br, label2); + yield return new CodeInstruction(OpCodes.Ldloc_S, 6).WithLabels(label1); + yield return LdcInstrs[Patch.beltSpeed[0]]; + yield return new CodeInstruction(OpCodes.Bne_Un_S, label2); + yield return new CodeInstruction(OpCodes.Ldloca_S, 0); + yield return new CodeInstruction(OpCodes.Ldc_I4_1); + yield return new CodeInstruction(OpCodes.Stfld, + AccessTools.Field(typeof(ConnGizmoObj), nameof(ConnGizmoObj.color))); + yield return new CodeInstruction(OpCodes.Nop).WithLabels(label2); + } + } + else + { + lastIsLdcI4_3 = instr.opcode == OpCodes.Ldc_I4_3; + yield return instr; + } + } + } +} diff --git a/OverclockEverything/OverclockEverything.cs b/OverclockEverything/OverclockEverything.cs new file mode 100644 index 0000000..3d9b42f --- /dev/null +++ b/OverclockEverything/OverclockEverything.cs @@ -0,0 +1,103 @@ +using BepInEx; +using BepInEx.Configuration; +using HarmonyLib; + +namespace OverclockEverything; + +[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] +public class Patch : BaseUnityPlugin +{ + private new static readonly BepInEx.Logging.ManualLogSource Logger = + BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME); + + private bool _cfgEnabled = true; + public static uint[] beltSpeed = { + 2, 5, 10 + }; + private static int inserterSpeedMultiplier = 2; + private static int assembleSpeedMultiplier = 2; + private static int powerConsumptionMultiplier = 2; + private static long powerGenerationMultiplier = 4; + private static long powerFuelConsumptionMultiplier = 1; + + private void Awake() + { + _cfgEnabled = Config.Bind("General", "Enabled", _cfgEnabled, "enable/disable this plugin").Value; + if (!_cfgEnabled) return; + beltSpeed[0] = Config.Bind("Belt", "MkI_Speed", beltSpeed[0], + new ConfigDescription("Speed for Belt Mk.I.\n 1: 6/s\n 2: 12/s\n 3: 15/s(Displayed as 18/s)\n 4: 20/s(Displayed as 24/s)\n 5+: 6*n/s", new AcceptableValueRange(1, 10))).Value; + beltSpeed[1] = Config.Bind("Belt", "MkII_Speed", beltSpeed[1], + new ConfigDescription("Speed for Belt Mk.II", new AcceptableValueRange(1, 10))).Value; + beltSpeed[2] = Config.Bind("Belt", "MkIII_Speed", beltSpeed[2], + new ConfigDescription("Speed for Belt Mk.III", new AcceptableValueRange(1, 10))).Value; + inserterSpeedMultiplier = Config.Bind("Inserter", "SpeedMultiplier", inserterSpeedMultiplier, + new ConfigDescription("Speed multiplier for Inserters", new AcceptableValueRange(1, 5))).Value; + assembleSpeedMultiplier = Config.Bind("Assemble", "SpeedMultiplier", assembleSpeedMultiplier, + new ConfigDescription("Speed multiplier for Smelters and Assembling Machines", new AcceptableValueRange(1, 10))).Value; + powerConsumptionMultiplier = Config.Bind("Assemble", "PowerConsumptionMultiplier", powerConsumptionMultiplier, + new ConfigDescription("Power consumption multiplier for Smelters and Assembling Machines", new AcceptableValueRange(1, 100))).Value; + powerGenerationMultiplier = Config.Bind("Power", "GenerationMultiplier", powerGenerationMultiplier, + new ConfigDescription("Power generation multiplier for all power providers", new AcceptableValueRange(1, 10))).Value; + powerFuelConsumptionMultiplier = Config.Bind("Power", "FuelConsumptionMultiplier", powerFuelConsumptionMultiplier, + new ConfigDescription("Fuel consumption multiplier for all fuel-consuming power providers", new AcceptableValueRange(1, 10))).Value; + Harmony.CreateAndPatchAll(typeof(Patch)); + Harmony.CreateAndPatchAll(typeof(BeltFix)); + } + + private static void BoostAssembler(int id) + { + var prefabDesc = LDB.items.Select(id).prefabDesc; + prefabDesc.assemblerSpeed *= assembleSpeedMultiplier; + prefabDesc.idleEnergyPerTick *= powerConsumptionMultiplier; + prefabDesc.workEnergyPerTick *= powerConsumptionMultiplier; + } + + private static void BoostPower(int id) + { + var prefabDesc = LDB.items.Select(id).prefabDesc; + prefabDesc.genEnergyPerTick *= powerGenerationMultiplier; + prefabDesc.useFuelPerTick *= powerFuelConsumptionMultiplier; + } + + [HarmonyPostfix, HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")] + private static void VFPreload_InvokeOnLoadWorkEnded_Postfix() + { + // Belts + LDB.items.Select(2001).prefabDesc.beltSpeed = (int)beltSpeed[0]; + LDB.items.Select(2002).prefabDesc.beltSpeed = (int)beltSpeed[1]; + LDB.items.Select(2003).prefabDesc.beltSpeed = (int)beltSpeed[2]; + + // Inserters + LDB.items.Select(2011).prefabDesc.inserterSTT /= inserterSpeedMultiplier; + LDB.items.Select(2012).prefabDesc.inserterSTT /= inserterSpeedMultiplier; + LDB.items.Select(2013).prefabDesc.inserterSTT /= inserterSpeedMultiplier; + + // Smelters + BoostAssembler(2302); + BoostAssembler(2315); + // Assemblers + BoostAssembler(2303); + BoostAssembler(2304); + BoostAssembler(2305); + // Chemical Plants + BoostAssembler(2309); + BoostAssembler(2317); + // Refiner + BoostAssembler(2308); + // Collider + BoostAssembler(2310); + + // Thermal + BoostPower(2204); + // Fusion + BoostPower(2211); + // Artificial Star + BoostPower(2210); + // Wind Turbine + BoostPower(2203); + // Solar Panel + BoostPower(2205); + // Geothermal + BoostPower(2213); + } +} diff --git a/OverclockEverything/OverclockEverything.csproj b/OverclockEverything/OverclockEverything.csproj new file mode 100644 index 0000000..29ef12a --- /dev/null +++ b/OverclockEverything/OverclockEverything.csproj @@ -0,0 +1,28 @@ + + + + net472 + org.soardev.overclockeverything + DSP MOD - OverclockEverything + 1.0.0 + true + latest + OverclockEverything + OverclockEverything + + + + + + + + + + + + + + + + + diff --git a/OverclockEverything/README.md b/OverclockEverything/README.md new file mode 100644 index 0000000..f104d4b --- /dev/null +++ b/OverclockEverything/README.md @@ -0,0 +1,12 @@ +# OverclockEverything + +#### Boost nearly all structures +#### 加速几乎所有建筑功能 + +## Usage + +* Boost power generation, assembling speed, belt and sorter speed. + +## 使用说明 + +* 加快发电,制造,传送带和分拣器速度。 diff --git a/OverclockEverything/package/icon.png b/OverclockEverything/package/icon.png new file mode 100644 index 0000000..2345e30 Binary files /dev/null and b/OverclockEverything/package/icon.png differ diff --git a/OverclockEverything/package/manifest.json b/OverclockEverything/package/manifest.json new file mode 100644 index 0000000..cf346cb --- /dev/null +++ b/OverclockEverything/package/manifest.json @@ -0,0 +1,9 @@ +{ + "name": "OverclockEverything", + "version_number": "1.0.0", + "website_url": "https://github.com/soarqin/DSP_Mods/tree/master/OverclockEverything", + "description": "Overclock everything in game / 加速游戏中的所有建筑", + "dependencies": [ + "xiaoye97-BepInEx-5.4.17" + ] +} diff --git a/README.md b/README.md index f715aff..0e70068 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,11 @@ Hide/Disable various tutorial tips/messages Can turn Storages and Tanks into Dustbin(Destroy incoming items) 储物仓和储液罐可以转变为垃圾桶(销毁送进的物品) +# [OverclockEverything](OverclockEverything) + +Boost nearly all structures +加速几乎所有建筑功能 + # [OrbitalCollectorBatchBuild](OCBatchBuild) Batch build Orbital Collectors