Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

##### Unreleased
**New/Improved patches**
- New KSP bugfix : **UncrewedControlPointFallback** Fix a vessel created by decoupling, undocking or a part being destroyed getting no control point unless it carries a part with a kerbal aboard, leaving the navball, SAS and autopilots oriented by its root part. An uncrewed control source (probe core, empty command pod...) is now used as a fallback.
- Improved the **FastLoader** patch to reuse the initial GameDatabase directory tree during the second config pass while refreshing files and directories created or modified by `Startup.Instantly` addons. Avoids reparsing unchanged configs and saves several seconds in heavily modded installs.

**Bug Fixes**
Expand Down
5 changes: 5 additions & 0 deletions GameData/KSPCommunityFixes/Settings.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@ KSP_COMMUNITY_FIXES
// dialog being wildly inflated.
FlightLoggerInflatedDistance = true

// Fix a vessel created by decoupling, undocking or a part being destroyed getting no control point
// unless it carries a part with a kerbal aboard, leaving it oriented by its root part instead. An
// uncrewed control source (a probe core, an empty command pod...) is now used as a fallback.
UncrewedControlPointFallback = true

// ##########################
// Obsolete bugfixes
// ##########################
Expand Down
74 changes: 74 additions & 0 deletions KSPCommunityFixes/BugFixes/UncrewedControlPointFallback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// When a vessel is split off another one (decoupling, undocking, a part being destroyed) or loaded
// without a valid reference transform, Vessel.FallBackReferenceTransform() is responsible for picking
// a control point for it. It delegates that choice to ShipConstruction.findFirstCrewablePart() :
//
// public void FallBackReferenceTransform()
// {
// if (this[referenceTransformId] == null)
// SetReferenceTransform(ShipConstruction.findFirstCrewablePart(rootPart), true);
// }
//
// public static Part findFirstCrewablePart(Part part)
// {
// if (part.CrewCapacity > 0 && part.protoModuleCrew.Count > 0 && part.isControlSource > Vessel.ControlLevel.NONE)
// return part;
// ...recurse over part.children...
// }
//
// findFirstCrewablePart() answers a different question than the one being asked : it looks for a part a
// kerbal is sitting in and can fly the vessel from, which is what its other callers (crew transfer, vessel
// spawning) want. A probe core fails the crew capacity test outright, and an empty command pod fails the
// "crew aboard" test, so an uncrewed vessel gets no control point at all : SetReferenceTransform(null, true)
// resets referenceTransformId to 0 and referenceTransformPart to null, and the vessel is then oriented by
// its root part. Every navball reading, SAS hold and autopilot attitude on that vessel is taken from
// whatever the root part happens to be, until the player manually picks a control point.
//
// We reimplement FallBackReferenceTransform() so that when findFirstCrewablePart() comes up empty, it falls
// back to the first part that is a control source, searched in the same root-first order. A crewed part
// still wins, matching how KSP ranks a kerbal above a probe core elsewhere in its control state handling.
// findFirstCrewablePart() itself is left alone, as its other callers want its existing meaning.

using System;
using System.Collections.Generic;

namespace KSPCommunityFixes.BugFixes;

internal class UncrewedControlPointFallback : BasePatch
{
protected override Version VersionMin => new(1, 8, 0);

protected override void ApplyPatches()
{
AddPatch(PatchType.Override, typeof(Vessel), nameof(Vessel.FallBackReferenceTransform));
}

private static void Vessel_FallBackReferenceTransform_Override(Vessel __instance)
{
if (__instance[__instance.referenceTransformId].IsNotNullOrDestroyed())
return;

Part referencePart = ShipConstruction.findFirstCrewablePart(__instance.rootPart);

// This is the part we are actually intending to patch : stock passes the null straight through.
if (referencePart.IsNullOrDestroyed())
referencePart = FindFirstControlSourcePart(__instance.rootPart);

__instance.SetReferenceTransform(referencePart, true);
}

private static Part FindFirstControlSourcePart(Part part)
{
if (part.isControlSource > Vessel.ControlLevel.NONE)
return part;

List<Part> children = part.children;
for (int i = 0; i < children.Count; i++)
{
Part controlSource = FindFirstControlSourcePart(children[i]);
if (controlSource.IsNotNullOrDestroyed())
return controlSource;
}

return null;
}
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ User options are available from the "ESC" in-game settings menu :<br/><img src="
- [**FIUpdateRadiation**](https://github.com/KSPModdingLibs/KSPCommunityFixes/pull/364) [KSP 1.12.0 - 1.12.5]<br/>Fix radiation flux being inconsistent for timewarp rates between 1x and 100x, caused by `PartThermalData.expFlux` / `unexpFlux` being mutated during every thermal integration pass.
- [**EditorAnimatedPartsShipModified**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/388) [KSP 1.12.0 - 1.12.5]<br/>Fix the Engineer's Report craft dimensions (and other `onEditorShipModified` consumers) lagging one vessel modification behind when an animated part is actuated in the editor (deployable solar panels/radiators/antennas, `ModuleAnimateGeneric` animations, Breaking Ground robotic servos), by re-firing the modification event once the animation has actually finished.
- [**FlightLoggerInflatedDistance**](https://github.com/KSPModdingLibs/KSPCommunityFixes/pull/402) [KSP 1.12.0 - 1.12.5]<br/>Fix the "distance travelled" / "distance over ground" values shown in the F3 flight results dialog being wildly inflated.
- **UncrewedControlPointFallback** [KSP 1.8.0 - 1.12.5]<br/>Fix a vessel created by decoupling, undocking or a part being destroyed getting no control point unless it carries a part with a kerbal aboard, leaving the navball, SAS and autopilots oriented by its root part. `Vessel.FallBackReferenceTransform()` now falls back to the first uncrewed control source (probe core, empty command pod...) when `ShipConstruction.findFirstCrewablePart()` finds nothing.
- **PartTooltipUpgradesApplyToSubstituteParts** [KSP 1.12.0 - 1.12.5]<br/>Disabled by default, you can enable it with a MM patch. Fix part upgrades being applied directly to the prefab part when creating the `PartListTooltip`, instead using a substitute part instance. Requires **UpgradeBugs** to be enabled.

#### Quality of Life tweaks
Expand Down