1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2025-12-09 06:13:36 +08:00
Files
DSP_Mods/MechaDronesTweaks/MechaDronesTweaks.cs
Trol1face f07ad5dfc9 Update MechaDronesTweaks.cs
Changed skipstage1 matcher from operand = 2 to opcode = ldc_i4_1
2024-03-10 21:09:35 +03:00

194 lines
9.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection.Emit;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
namespace MechaDronesTweaks;
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
[BepInDependency(FastDronesRemover.FastDronesGuid, BepInDependency.DependencyFlags.SoftDependency)]
public class MechaDronesTweaksPlugin : BaseUnityPlugin
{
public new static readonly BepInEx.Logging.ManualLogSource Logger =
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
private readonly Harmony _harmony = new(PluginInfo.PLUGIN_GUID);
public MechaDronesTweaksPlugin()
{
/* Remove FastDrones MOD if loaded */
try
{
if (FastDronesRemover.Run(_harmony))
{
Logger.LogInfo("Unpatch FastDrones - OK");
}
}
catch (Exception e)
{
Logger.LogWarning($"Failed to unpatch FastDrones: {e}");
}
}
public void Awake()
{
MechaDronesTweaks.UseFixedSpeed = Config.Bind("MechaDrones", "UseFixedSpeed", MechaDronesTweaks.UseFixedSpeed,
"Use fixed speed for mecha drones").Value;
MechaDronesTweaks.SkipStage1 = Config.Bind("MechaDrones", "SkipStage1",
MechaDronesTweaks.SkipStage1,
"Skip 1st stage of working mecha drones (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 (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<float>(6f, 1000f))).Value;
MechaDronesTweaks.SpeedMultiplier = Config.Bind("MechaDrones", "SpeedMultiplier",
MechaDronesTweaks.SpeedMultiplier,
new ConfigDescription("Speed multiplier for mecha drones, working only when UseFixedSpeed is disabled",
new AcceptableValueRange<float>(1f, 10f))).Value;
MechaDronesTweaks.EnergyMultiplier = Config.Bind("MechaDrones", "EnergyMultiplier",
MechaDronesTweaks.EnergyMultiplier,
new ConfigDescription("Energy consumption multiplier for mecha drones",
new AcceptableValueRange<float>(0f, 1f))).Value;
MechaDronesTweaks.EnergyMultiplier = Config.Bind("MechaDrones", "EnergyMultiplier",
MechaDronesTweaks.EnergyMultiplier,
new ConfigDescription("Energy consumption multiplier for mecha drones",
new AcceptableValueRange<float>(0f, 1f))).Value;
_harmony.PatchAll(typeof(MechaDronesTweaks));
}
}
public static class MechaDronesTweaks
{
public static bool UseFixedSpeed;
public static bool SkipStage1;
public static bool RemoveSpeedLimitForStage1 = true;
public static float FixedSpeed = 300f;
public static float SpeedMultiplier = 4f;
public static float EnergyMultiplier = 0.1f;
[HarmonyTranspiler]
[HarmonyPatch(typeof(ConstructionSystem), nameof(ConstructionSystem.UpdateDrones))]
[HarmonyPatch(typeof(UIMechaWindow), nameof(UIMechaWindow.UpdateProps))]
[HarmonyPatch(typeof(UITechTree), nameof(UITechTree.RefreshDataValueText))]
private static IEnumerable<CodeInstruction> UITechTreeRefreshDataValueText_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.constructionDroneSpeed)))
);
if (UseFixedSpeed)
{
matcher.Repeat(m => m.Advance(1).InsertAndAdvance(
new CodeInstruction(OpCodes.Pop),
new CodeInstruction(OpCodes.Ldc_R4, FixedSpeed)
));
}
else
{
matcher.Repeat(m => m.Advance(1).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldc_R4, SpeedMultiplier),
new CodeInstruction(OpCodes.Mul)
));
}
return matcher.InstructionEnumeration();
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(ConstructionModuleComponent), nameof(ConstructionModuleComponent.EjectBaseDrone))]
[HarmonyPatch(typeof(ConstructionModuleComponent), nameof(ConstructionModuleComponent.EjectMechaDrone))]
private static IEnumerable<CodeInstruction> MechaUpdateTargets_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
if (!SkipStage1)
return matcher.InstructionEnumeration();
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldc_I4_1),
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(DroneComponent), nameof(DroneComponent.stage)))
).Opcode = OpCodes.Ldc_I4_2;
return matcher.InstructionEnumeration();
}
[HarmonyTranspiler, HarmonyPatch(typeof(ConstructionSystem), nameof(ConstructionSystem.UpdateDrones))]
private static IEnumerable<CodeInstruction> MechaUpdateDrones_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
if (EnergyMultiplier >= 1f)
return matcher.InstructionEnumeration();
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(ModeConfig), nameof(ModeConfig.droneEnergyPerMeter)))
).Advance(1).Insert(
new CodeInstruction(OpCodes.Ldc_R8, (double)EnergyMultiplier),
new CodeInstruction(OpCodes.Mul)
);
return matcher.InstructionEnumeration();
}
[HarmonyTranspiler]
// ref CraftData craft, PlanetFactory factory, ref Vector3 ejectPos, float droneSpeed, float dt, ref double mechaEnergy, ref double mechaEnergyChange, double flyEnergyRate, double repairEnergyCost, out float energyRatio
[HarmonyPatch(typeof(DroneComponent), nameof(DroneComponent.InternalUpdate), new[] { typeof(CraftData), typeof(PlanetFactory), typeof(Vector3), typeof(float), typeof(float), typeof(double), typeof(double), typeof(double), typeof(double), typeof(float) }, new[] { ArgumentType.Ref, ArgumentType.Normal, ArgumentType.Ref, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Ref, ArgumentType.Ref, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Out })]
// ref CraftData craft, PlanetFactory factory, Vector3 ejectPos, float droneSpeed, float dt, ref long energy, double flyEnergyRate, double repairEnergyCost, out float energyRatio
[HarmonyPatch(typeof(DroneComponent), nameof(DroneComponent.InternalUpdate), new[] { typeof(CraftData), typeof(PlanetFactory), typeof(Vector3), typeof(float), typeof(float), typeof(long), typeof(double), typeof(double), typeof(float) }, new[] { ArgumentType.Ref, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Ref, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Out })]
private static IEnumerable<CodeInstruction> MechaDroneUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
if (RemoveSpeedLimitForStage1)
{
matcher.MatchForward(false,
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R4 && instr.OperandIs(1f)),
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R4 && instr.OperandIs(3f))
);
matcher.Advance(1).Operand = 10000f;
}
if (!UseFixedSpeed && Math.Abs(SpeedMultiplier - 1.0f) < 0.01f)
return matcher.InstructionEnumeration();
matcher.Start().MatchForward(false,
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldc_R4),
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(DroneComponent), nameof(DroneComponent.progress)))
);
matcher.Repeat(m =>
{
if (m.InstructionAt(1).OperandIs(0f))
{
m.InstructionAt(3).labels = m.Labels;
m.RemoveInstructions(3);
}
else if (m.InstructionAt(1).OperandIs(1f))
{
m.Advance(1).Operand = 0f;
m.Advance(2);
}
}
);
matcher.Start().MatchForward(false,
new CodeMatch(instr => instr.opcode == OpCodes.Ldc_R4 && instr.OperandIs(0.5f))
);
matcher.Repeat(m =>
{
if (UseFixedSpeed)
{
if (FixedSpeed > 75f)
{
m.Operand = 0.5f * FixedSpeed / 75f;
}
}
else
{
m.Operand = 0.5f * SpeedMultiplier;
}
}
);
return matcher.InstructionEnumeration();
}
}