mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-02-05 00:22:21 +08:00
refactoring UXAssist and CheatEnabler
This commit is contained in:
346
UXAssist/Patches/PlayerPatch.cs
Normal file
346
UXAssist/Patches/PlayerPatch.cs
Normal file
@@ -0,0 +1,346 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Configuration;
|
||||
using CommonAPI.Systems;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
using UXAssist.Common;
|
||||
|
||||
namespace UXAssist.Patches;
|
||||
|
||||
public static class PlayerPatch
|
||||
{
|
||||
public static ConfigEntry<bool> EnhancedMechaForgeCountControlEnabled;
|
||||
public static ConfigEntry<bool> HideTipsForSandsChangesEnabled;
|
||||
public static ConfigEntry<bool> AutoNavigationEnabled;
|
||||
public static ConfigEntry<bool> AutoCruiseEnabled;
|
||||
public static ConfigEntry<bool> AutoBoostEnabled;
|
||||
public static ConfigEntry<double> DistanceToWarp;
|
||||
private static PressKeyBind _autoDriveKey;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
EnhancedMechaForgeCountControlEnabled.SettingChanged += (_, _) => EnhancedMechaForgeCountControl.Enable(EnhancedMechaForgeCountControlEnabled.Value);
|
||||
HideTipsForSandsChangesEnabled.SettingChanged += (_, _) => HideTipsForSandsChanges.Enable(HideTipsForSandsChangesEnabled.Value);
|
||||
AutoNavigationEnabled.SettingChanged += (_, _) => AutoNavigation.Enable(AutoNavigationEnabled.Value);
|
||||
EnhancedMechaForgeCountControl.Enable(EnhancedMechaForgeCountControlEnabled.Value);
|
||||
HideTipsForSandsChanges.Enable(HideTipsForSandsChangesEnabled.Value);
|
||||
AutoNavigation.Enable(AutoNavigationEnabled.Value);
|
||||
_autoDriveKey = KeyBindings.RegisterKeyBinding(new BuiltinKey
|
||||
{
|
||||
key = new CombineKey(0, 0, ECombineKeyAction.OnceClick, true),
|
||||
conflictGroup = KeyBindConflict.MOVEMENT | KeyBindConflict.FLYING | KeyBindConflict.SAILING | KeyBindConflict.BUILD_MODE_1 | KeyBindConflict.KEYBOARD_KEYBIND,
|
||||
name = "ToggleAutoCruise",
|
||||
canOverride = true
|
||||
});
|
||||
I18N.Add("AutoCruiseOn", "Auto-cruise enabled", "已启用自动巡航");
|
||||
I18N.Add("AutoCruiseOff", "Auto-cruise disabled", "已禁用自动巡航");
|
||||
}
|
||||
|
||||
public static void OnUpdate()
|
||||
{
|
||||
if (_autoDriveKey.keyValue)
|
||||
{
|
||||
AutoNavigation.ToggleAutoCruise();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uninit()
|
||||
{
|
||||
EnhancedMechaForgeCountControl.Enable(false);
|
||||
HideTipsForSandsChanges.Enable(false);
|
||||
AutoNavigation.Enable(false);
|
||||
}
|
||||
|
||||
private class EnhancedMechaForgeCountControl: PatchImpl<EnhancedMechaForgeCountControl>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnOkButtonClick))]
|
||||
private static IEnumerable<CodeInstruction> UIReplicatorWindow_OnOkButtonClick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(10))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 1000));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnPlusButtonClick))]
|
||||
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnMinusButtonClick))]
|
||||
private static IEnumerable<CodeInstruction> UIReplicatorWindow_OnPlusButtonClick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var label1 = generator.DefineLabel();
|
||||
var label2 = generator.DefineLabel();
|
||||
var label3 = generator.DefineLabel();
|
||||
var label4 = generator.DefineLabel();
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||
new CodeMatch(o => o.opcode == OpCodes.Add || o.opcode == OpCodes.Sub)
|
||||
).Advance(1).RemoveInstruction().InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.control))),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label1),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_S, 10),
|
||||
new CodeInstruction(OpCodes.Br_S, label4),
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.shift))).WithLabels(label1),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label2),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_S, 100),
|
||||
new CodeInstruction(OpCodes.Br_S, label4),
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.alt))).WithLabels(label2),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label3),
|
||||
new CodeInstruction(OpCodes.Ldc_I4, 1000),
|
||||
new CodeInstruction(OpCodes.Br_S, label4),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1).WithLabels(label3)
|
||||
).Labels.Add(label4);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(10))
|
||||
);
|
||||
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, 1000));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class HideTipsForSandsChanges: PatchImpl<HideTipsForSandsChanges>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(Player), nameof(Player.SetSandCount))]
|
||||
private static IEnumerable<CodeInstruction> Player_SetSandCount_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertySetter(typeof(Player), nameof(Player.sandCount)))
|
||||
).Advance(1).Insert(new CodeInstruction(OpCodes.Ret));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
public class AutoNavigation: PatchImpl<AutoNavigation>
|
||||
{
|
||||
private static bool _canUseWarper;
|
||||
private static int _indicatorAstroId;
|
||||
private static bool _speedUp;
|
||||
private static Vector3 _direction;
|
||||
|
||||
public static void ToggleAutoCruise()
|
||||
{
|
||||
AutoCruiseEnabled.Value = !AutoCruiseEnabled.Value;
|
||||
if (!DSPGame.IsMenuDemo && GameMain.isRunning)
|
||||
{
|
||||
UIRoot.instance.uiGame.generalTips.InvokeRealtimeTipAhead((AutoCruiseEnabled.Value ? "AutoCruiseOn" : "AutoCruiseOff").Translate());
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.GameTick))]
|
||||
private static IEnumerable<CodeInstruction> PlayerController_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BuildModel), nameof(BuildModel.EarlyGameTickIgnoreActive)))
|
||||
).Advance(1).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
Transpilers.EmitDelegate((PlayerController controller) =>
|
||||
{
|
||||
/* Update target astro if changed */
|
||||
_speedUp = false;
|
||||
var player = controller.player;
|
||||
var navi = player.navigation;
|
||||
if (navi.indicatorAstroId != _indicatorAstroId)
|
||||
{
|
||||
_indicatorAstroId = navi.indicatorAstroId;
|
||||
if (_indicatorAstroId == 0) return;
|
||||
}
|
||||
else if (_indicatorAstroId == 0) return;
|
||||
switch (controller.movementStateInFrame)
|
||||
{
|
||||
case EMovementState.Walk:
|
||||
case EMovementState.Drift:
|
||||
if (!AutoCruiseEnabled.Value) return;
|
||||
if (GameMain.localStar?.astroId == _indicatorAstroId) return;
|
||||
/* Press jump key to fly */
|
||||
controller.input0.z = 1f;
|
||||
break;
|
||||
case EMovementState.Fly:
|
||||
if (!AutoCruiseEnabled.Value) return;
|
||||
if (GameMain.localStar?.astroId == _indicatorAstroId) return;
|
||||
/* Keep pressing jump and pullup key to sail */
|
||||
controller.input0.y = 1f;
|
||||
controller.input1.y = 1f;
|
||||
break;
|
||||
case EMovementState.Sail:
|
||||
if (VFInput._pullUp.pressing || VFInput._pushDown.pressing || VFInput._moveLeft.pressing || VFInput._moveRight.pressing ||
|
||||
(!player.warping && UIRoot.instance.uiGame.disableLockCursor && (VFInput._moveForward.pressing || VFInput._moveBackward.pressing)))
|
||||
return;
|
||||
var playerPos = player.uPosition;
|
||||
var isHive = _indicatorAstroId > 1000000;
|
||||
ref var astro = ref isHive ? ref GameMain.spaceSector.astros[_indicatorAstroId - 1000000] : ref GameMain.galaxy.astrosData[_indicatorAstroId];
|
||||
var astroVec = astro.uPos - playerPos;
|
||||
var distance = astroVec.magnitude;
|
||||
if (distance < astro.type switch
|
||||
{
|
||||
EAstroType.Planet => 800.0 + astro.uRadius,
|
||||
EAstroType.Star => 4000.0 + astro.uRadius,
|
||||
EAstroType.EnemyHive => 400.0,
|
||||
_ => 2000.0 + astro.uRadius
|
||||
})
|
||||
{
|
||||
if (isHive)
|
||||
{
|
||||
player.uVelocity = Vector3.zero;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var autoCruise = AutoCruiseEnabled.Value;
|
||||
if (GameMain.instance.timei % 6 == 0 || _direction == Vector3.zero)
|
||||
{
|
||||
_direction = astroVec.normalized;
|
||||
|
||||
/* Check nearest astroes, try to bypass them */
|
||||
var localStar = GameMain.localStar;
|
||||
_canUseWarper = autoCruise && !player.warping && player.mecha.warpStorage.GetItemCount(1210) > 0;
|
||||
if (localStar != null)
|
||||
{
|
||||
var nearestRange = (playerPos - localStar.uPosition).sqrMagnitude;
|
||||
var nearestPos = localStar.uPosition;
|
||||
var nearestAstroId = localStar.astroId;
|
||||
foreach (var p in localStar.planets)
|
||||
{
|
||||
var range = (playerPos - p.uPosition).sqrMagnitude;
|
||||
if (range >= nearestRange) continue;
|
||||
nearestRange = range;
|
||||
nearestPos = p.uPosition;
|
||||
nearestAstroId = p.astroId;
|
||||
}
|
||||
|
||||
/* If targeting hives, do not bypass them */
|
||||
if (!isHive)
|
||||
{
|
||||
var hiveSys = GameMain.spaceSector.dfHives[localStar.index];
|
||||
while (hiveSys != null)
|
||||
{
|
||||
if (hiveSys.realized && hiveSys.hiveAstroId > 1000000)
|
||||
{
|
||||
ref var hiveAstro = ref GameMain.spaceSector.astros[hiveSys.hiveAstroId - 1000000];
|
||||
/* Divide by 4, so that the real range is 2 times of the calculated range,
|
||||
which means the minimal range allowed is 4000 */
|
||||
var range = (playerPos - hiveAstro.uPos).sqrMagnitude / 4.0;
|
||||
if (range < nearestRange)
|
||||
{
|
||||
nearestRange = range;
|
||||
nearestPos = hiveAstro.uPos;
|
||||
nearestAstroId = hiveSys.hiveAstroId;
|
||||
}
|
||||
}
|
||||
|
||||
hiveSys = hiveSys.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
if (nearestAstroId != _indicatorAstroId && nearestRange < 2000.0 * 2000.0)
|
||||
{
|
||||
Vector3 leavingDirection = (playerPos - nearestPos).normalized;
|
||||
var dot = Vector3.Dot(leavingDirection, _direction);
|
||||
if (dot < 0)
|
||||
{
|
||||
var cross = Vector3.Cross(_direction, leavingDirection);
|
||||
_direction = Vector3.Cross(leavingDirection, cross).normalized;
|
||||
}
|
||||
else
|
||||
{
|
||||
_direction = leavingDirection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 uVel = player.uVelocity;
|
||||
var speed = uVel.magnitude;
|
||||
if (player.warping)
|
||||
{
|
||||
_speedUp = false;
|
||||
if (autoCruise)
|
||||
{
|
||||
/* Speed down if too close */
|
||||
var actionSail = controller.actionSail;
|
||||
if (distance < GalaxyData.LY * 1.5)
|
||||
{
|
||||
if (distance < actionSail.currentWarpSpeed * distance switch
|
||||
{
|
||||
> GalaxyData.LY * 0.6 => 0.33,
|
||||
> GalaxyData.LY * 0.3 => 0.5,
|
||||
> GalaxyData.LY * 0.1 => 0.66,
|
||||
_ => 1.0
|
||||
})
|
||||
{
|
||||
controller.input0.y = -1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var mecha = player.mecha;
|
||||
var energyRatio = mecha.coreEnergy / mecha.coreEnergyCap;
|
||||
if (_canUseWarper && GameMain.localPlanet == null && distance > GalaxyData.AU * DistanceToWarp.Value && energyRatio >= 0.8 && player.mecha.UseWarper())
|
||||
{
|
||||
player.warpCommand = true;
|
||||
VFAudio.Create("warp-begin", player.transform, Vector3.zero, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Speed up if needed */
|
||||
_speedUp = autoCruise && AutoBoostEnabled.Value && speed + 0.2f < player.mecha.maxSailSpeed && energyRatio >= 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update direction, gracefully rotate for 2 degrees for each frame */
|
||||
var angle = Vector3.Angle(uVel, _direction);
|
||||
if (angle < 2f)
|
||||
{
|
||||
player.uVelocity = _direction * speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.uVelocity = Vector3.Slerp(uVel, _direction * speed, 2f / angle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_speedUp = false;
|
||||
break;
|
||||
}
|
||||
})
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(VFInput), nameof(VFInput._sailSpeedUp), MethodType.Getter)]
|
||||
private static IEnumerable<CodeInstruction> VFInput_sailSpeedUp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ret)
|
||||
);
|
||||
matcher.Repeat(m => m.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(AutoNavigation), nameof(_speedUp))),
|
||||
new CodeInstruction(OpCodes.Or)
|
||||
).Advance(1));
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
/* Disable Lock Cursor Mode on entering sail panel
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(UISailPanel), nameof(UISailPanel._OnOpen))]
|
||||
public static void OnOpen_Prefix()
|
||||
{
|
||||
if (_aimingEnabled)
|
||||
{
|
||||
UIRoot.instance.uiGame.disableLockCursor = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user