Modders Notes the Dev team have thrown together for 1.12.0.
We upgraded the project to Unity 2019.4.18f1 LTS to position KSP on a long term support version of Unity. This should not have any major impact on mods.
API documentation can be found here.
Wheels and Landing Legs changes
ModuleWheelBase.useNewFrictionModel by default is false. Which means all wheels and landing legs using this module will use the old behaviour/logic by default. Set it to true in the part.cfg file to use the new friction model.
ModuleWheelSuspension.useDistributedMass by default is false. Which means all wheels and landing legs using this module will use the old behaviour/logic by default for suspension processing. Set it to true in the part.cfg file to use the new friction model.
ModuleWheelSteering.autoSteeringAdjust by default is false. Which means all wheels and landing legs using this module will use the old behaviour/logic by default for steering processing. Set it to true in the part.cfg file to use the new friction model.
Refer to the Wheels Devblog for more information about the functional changes that were made to wheels and landing legs.
The maneuver tool app has been designed in such a way to allow modders to easily add additional maneuver types to the app.
To do this you will need to create your own mod c# class that inherits class
TransferTypeBase - Base class for the transfer types.
The Manuever Tool app on startup finds all classes based on this base class and adds them into it’s maneuver type list. Refer to the API documentation for the abstract methods your class has to implement.
Additionally you must implement your own data class for your transfer type. Use this class as the base and assign to currentSelectedTransfer:
TransferDataBase - Base class for the TransferData for each transfer type. This class inherits AppUI_Data class that allows you to define UI fields for your transfer that will appear in the center part of the manuever tool UI. See the section below called “Generic UI framework” on how to define your UI fields. You will also want to assign your dataChangedCAllback and calculationStateChangedCallback.
Additionally you can use the following base class to define your own data class for the top slide out section of the maneuver tool app:
TransferDataTopDataBase - Base class for the TransferDataTop for each transfer type. This class also inherits from AppUI_Data class.
Another important class is ManeuverToolUIFrame. This manages the UI for the Manuever Tool App and has a number of useful methods. Refer to the API documentation.
The Alarm Clock follows a similar idea to most moddable things in KSP. The fundamental building blocks are:
AlarmClockScenario: The scenario module that runs and manages the alarms
AlarmTypeBase: The abstract class that all alarm types inherit from
I won’t go into all the specifics here as the API help should cover many of these things, but here’s some key pointers.
The scenario maintains the list of alarms and persists them into the save file. AddAlarm, RemoveAlarm, GetNextAlarm, etc help you manage the alarm list.There are GameEvents for changes to the list as well.
There is currently no “GetAllAlarms” method - Triggers apologies - this will be fixed
You define the input fields you want by attributing fields or properties with AppUI_Control types. These fields/properties can then be used in the AlarmType class to define the time for the alarm and any other behaviour. An example here is AppUI_InputDateTime which will give you a datetime input when creating/editing an alarm.
Some key fields/overrides in the alarm type include:
id - the persistent identifier for an alarm
GetDefaultTitle() - the string that will be the title of a new alarm
iconURL - a gamedatabase path to the icon to use in the drop downs and lists - the default ones are 64x64 pngs
ut - the time of the alarm in universal time
RequiresVessel() - when true the alarm will only be available in the UI to add when a vessel can be selected
CanSetAlarm(AlarmUIDisplayMode displayMode) - lets you control when the inputs are valid in add and edit mode to save changes
OnInputPanelUpdate(AlarmUIDisplayMode displayMode) - called in the Monobehavior update loop by the app for each alarm when it is displayed in the app
OnScenarioUpdate - called in the Monobehavior update loop by the scenario when the alarm is in the list.
Here’s an example of a very simple alarm type that will let you set a date
public class AlarmTypeTest : AlarmTypeBase
[AppUI_InputDateTime(guiName = "Alarm Date", datetimeMode = AppUIMemberDateTime.DateTimeModes.date)]
public double alarmDate;
iconURL = "TriggerTech/TestMod/AlarmIcons/DavesTest";
public override bool CanSetAlarm(AlarmUIDisplayMode displayMode)
public override string GetDefaultTitle()
return "Daves Test Alarm";
public override bool RequiresVessel()
public override void OnUIEndInitialization(AlarmUIDisplayMode displayMode)
if(displayMode == AlarmUIDisplayMode.Add)
alarmDate = Planetarium.GetUniversalTime() + 600;
AppUIMemberDateTime m = (AppUIMemberDateTime)uiPanel.GetControl("alarmDate");
m.DatetimeMode = AppUIMemberDateTime.DateTimeModes.date;
public override void OnInputPanelUpdate(AlarmUIDisplayMode displayMode)
ut = alarmDate;
Generic UI framework
The key driver for this system is the idea of moddable inputs to applications for various moddable functions. The fundamental idea being that in a UI you can place a panel that has a vertical layout group and an AppUIPanel component, call Setup with a data class and it will present the user with an editable section of UI that correlates to the data inputs. It edits the data class and the code can then use the edited object directly.
Steps to use it:
Create a “panel” in your UI that will hold the input fields.
Create a class that holds the inputs (inherits class AppUI_Data).
Apply the attributes to the fields that are for input within the class.
“Setup” the panel at the right time in code.
Classes of interest
AppUI_Data - this is your data class which can use attributes on fields to create UI controls.
The following UI controls can be used as attributes on your fields in your AppUI_Data class.:
File Folder Browser
Craft files are still stored as text in .craft files. The thumbnail naming convention has changed, but otherwise the thumbnail itself is generated no differently.
The search classes don’t have any exposed methods that can be used to actually do anything aside from literally starting and stopping a search using whatever information is in the search input text field.
The folder-action confirmation dialog for deleting and creating folders can be created and passed callbacks that are fired when the indicated action is confirmed.
The folder browser doesn’t use any config files that could be modified. Public methods and properties include querying if the currently selected folder is a player-craft or stock-craft folder, and querying if the currently displayed folder structure is for the VAB or SPH. Folder highlighting can be overridden using a craft’s file-path, and folder highlight overrides can also be turned off. Also exposed is a method for updating folder file-counts for all folders as well as for a specific folder.
Properties are exposed that return the local machine’s file path for the stock craft folder, the expansion directory folders, and the mission craft folders
We added the ability to disable and enable the Color Picker of the lights - use the KSPField disableColorPicker in the part.cfg file.
Also if one light has more than one transform you can control it with the same Module light. You can do this by defining one or more LIGHT submodes within the ModuleLight node in your part.cfg file. Eg:
name = ModuleLight
…. (normal ModuleLight fields)
lightName = light1
lightR = 1.0
lightG = 1.0
lightB = 1.0
flareRendererName = flare1
lightName = light2
lightR = 1.0
lightG = 1.0
lightB = 1.0
flareRendererName = flare2
Docking Port rotations.
Docking port parts are now able to do an alignment rotation once they are docked. In order to make a dock being able to rotate, you need to configure them so:
canRotate: set to True, when this rotating feature should be available to this part
rotationTransformName: Name of the transform of the model that will rotate.
maxMotorOutput: this is used for the electric charge resource consumption calculations. set this according to the part’s design guidelines
RESOURCE definition: this one should be the same for all docking ports that use this rotating feature. This is used to specify which resource is consumed by doing the rotation
These other KSPFields are optionally available to configure as well:
rotationAxis: The rotation axis, defaulted to the z axis. This is necessary as some docks might have a different rotation axis. Can be "X", "X-", "Y", "Y-" or "Z", "Z-"
traverseVelocity: The traverse speed (in deg/s for rotational motion)
hardMinMaxLimits: The angle range that's defined by the physical limits of the part model and/or the part's designer. The default values are -15, 15. A player must not be able to set an angle beyond this range. This is a Vector2 so, could be defined as “-15, 15“, for example.
efficiency: Servo efficiency (1 = 100%)
baseResourceConsumptionRate: Base resource consumption on motor output when the servo is moving
referenceConsumptionVelocity: The transform velocity (angular or positional) at which the resource consumption is 1 x the baseResourceConsumptionRate
New Slim Suit ID Maps
Other misc modding changes
Failed reflection calls to incompatible or otherwise invalid mods are now handled, so they don't stop the game from loading.
Custom suits now show the corresponding icon in all relevant screens. These have to be provided by the mod, the game will not generate them.
Added an additional useCustomThreshold field to ModuleOrbitalSurveyor. Setting it to true will allow the module to recalculate the minimum and maximum altitudes beyond the stock values.
When multiple versions of the same assembly are present, KSP now makes sure only the most recent one is loaded. It’s still a good idea to encourage people not to do this, to avoid clutter.
Tuned the logic to calculate space object resource percentages based on the lowRange and highRange values, preventing space objects from always having > 80% resources regardless of the range values.
Added a GameEvent for revert to launch that returns the current FlightState.