Skip to content

Commit 8a44584

Browse files
authored
Allow targeting the currently orbited parent body, or any body the parent body is a descendant of (#285)
* Use a prefix to skip calling `OrbitTargeter.DropInvalidTargets` entirely. The only function of this method is to drop the target if it is the current parent or any body the parent body is a descendant of. * Use a transpiler to modify `FlightGlobals.UpdateInformation`. One of the primary functions of this method is to check the validity of the current target and drop it if invalid. The first two branches of the set of if statements call `FlightGlobals.SetVesselTarget` to drop the target if it is the current parent or any body the parent body is a descendant of. These first two if statements are entirely replaced with Nops.
1 parent 9010ae1 commit 8a44584

File tree

4 files changed

+75
-0
lines changed

4 files changed

+75
-0
lines changed

GameData/KSPCommunityFixes/Settings.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ KSP_COMMUNITY_FIXES
308308
// Optional MM-patcheable toggle to always disable the MH features
309309
OptionalMakingHistoryDLCFeaturesAlwaysDisable = false
310310
311+
// Allow targeting the parent body of the current craft, or any body in the parent hierarchy
312+
TargetParentBody = true
313+
311314
// ##########################
312315
// Performance tweaks
313316
// ##########################

KSPCommunityFixes/KSPCommunityFixes.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
<Compile Include="QoL\AutostrutActions.cs" />
220220
<Compile Include="QoL\BetterEditorUndoRedo.cs" />
221221
<Compile Include="QoL\OptionalMakingHistoryDLCFeatures.cs" />
222+
<Compile Include="QoL\TargetParentBody.cs" />
222223
<Compile Include="QoL\ToolbarShowHide.cs" />
223224
<Compile Include="QoL\DisableNewGameIntro.cs" />
224225
<Compile Include="QoL\NoIVA.cs" />
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using System.Reflection.Emit;
5+
using HarmonyLib;
6+
7+
namespace KSPCommunityFixes.QoL
8+
{
9+
class TargetParentBody : BasePatch
10+
{
11+
protected override Version VersionMin => new Version(1, 8, 0);
12+
13+
protected override void ApplyPatches()
14+
{
15+
AddPatch(PatchType.Prefix, typeof(OrbitTargeter), nameof(OrbitTargeter.DropInvalidTargets));
16+
17+
AddPatch(PatchType.Transpiler, typeof(FlightGlobals), nameof(FlightGlobals.UpdateInformation));
18+
}
19+
20+
// OrbitTargeter.DropInvalidTargets is only ever used to clear the target if the target is in the Parent body heriarchy
21+
// Always return false and do not run the base method
22+
private static bool OrbitTargeter_DropInvalidTargets_Prefix(bool __result)
23+
{
24+
__result = false;
25+
return false;
26+
}
27+
28+
// FlightGlobals.UpdateInformation contains two sequential if statements that each make a call to FlightGlobals.SetVesselTarget
29+
// to clear the target if the target is the direct parent of the vessel or in the parent body heriarchy
30+
// Starting from the end of the if statement making the second call to FlightGlobals.SetVesselTarget, iterate backwards and
31+
// replace opcodes with Nop until reaching the beginning of the first if statement
32+
static IEnumerable<CodeInstruction> FlightGlobals_UpdateInformation_Transpiler(IEnumerable<CodeInstruction> instructions)
33+
{
34+
FieldInfo FlightGlobals_currentMainBody = AccessTools.Field(typeof(FlightGlobals), nameof(FlightGlobals.currentMainBody));
35+
MethodInfo FlightGlobals_SetVesselTarget = AccessTools.Method(typeof(FlightGlobals), nameof(FlightGlobals.SetVesselTarget));
36+
37+
List<CodeInstruction> code = new List<CodeInstruction>(instructions);
38+
int numFlightGlobals_currentMainBodysSeen = 0;
39+
int numFlightGlobals_SetVesselTargetsSeen = 0;
40+
for (int i = 1; i < code.Count; i++)
41+
{
42+
if (code[i].opcode == OpCodes.Br
43+
&& code[i - 1].opcode == OpCodes.Call
44+
&& ReferenceEquals(code[i - 1].operand, FlightGlobals_SetVesselTarget))
45+
{
46+
numFlightGlobals_SetVesselTargetsSeen++;
47+
if (numFlightGlobals_SetVesselTargetsSeen == 2)
48+
{
49+
for (int j = i; j >= 0; j--)
50+
{
51+
if (code[j].opcode == OpCodes.Ldsfld && ReferenceEquals(code[j].operand, FlightGlobals_currentMainBody))
52+
{
53+
numFlightGlobals_currentMainBodysSeen++;
54+
}
55+
OpCode opcode = code[j].opcode;
56+
code[j].opcode = OpCodes.Nop;
57+
code[j].operand = null;
58+
if (numFlightGlobals_currentMainBodysSeen == 2 && opcode == OpCodes.Ldarg_0)
59+
{
60+
break;
61+
}
62+
}
63+
break;
64+
}
65+
}
66+
}
67+
return code;
68+
}
69+
}
70+
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ User options are available from the "ESC" in-game settings menu :<br/><img src="
109109
- **ResourceLockActions** [KSP 1.8.0 - 1.12.5]<br/>Add part actions for locking/unlocking resources flow state.
110110
- [**BetterEditorUndoRedo**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/172) [KSP 1.12.3 - 1.12.5]<br/>Invert the editor undo state capturing logic so part tweaks aren't lost when undoing. NOTE: this patch is disabled when TweakScale/L is installed.
111111
- [**OptionalMakingHistoryDLCFeatures**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/218) [KSP 1.12.3 - 1.12.5]<br/>Allow to disable the Making History DLC mission editor and additional launch sites features to decrease memory usage and increase loading speed. The Making History parts will still be available. Can be toggled from the KSPCF in-game settings (requires a restart), or from a MM patch (see `Settings.cfg`).
112+
- **TargetParentBody** [KSP 1.8.0 - 1.12.5]<br/>Allow targeting the parent body of the current craft, or any body in the parent hierarchy.
112113

113114
#### Performance tweaks
114115

0 commit comments

Comments
 (0)