Chapter 13. Creating a Mod

One of the reasons why Kerbal Space Program is so popular is the wide array of custom parts and mods that the community has put together. If you get tired of building rockets using the built-in parts, you can download a pack of additional components and build more complicated ones. On top of this, you can download mods that add extra behavior to the game, as we discussed previously in Chapter 10 .

If you’re just using other people’s mods, you’re missing out on the fun of creating your own. In this chapter, you’ll learn how to create and add an entirely new part to Kerbal Space Program, and then learn how to write code that extends the behavior of the game.

Parts

Rockets are composed of parts . A part is composed of at least two elements:

  • A mesh , which is the 3D object that you see in game
  • A config file , which is a text file that describes to the game what the part is and how it works

To make a custom part, you need to create both of these files and then place them in a folder that the game will look inside at startup.

Creating a text file is easy — all you need is a text editor, like Notepad, TextMate, or emacs. Creating a 3D model is quite a bit trickier: you need a 3D model editor, as well as the knowledge of how to use it.

While we don’t have the space to teach you how to use a 3D modeling program from start to finish — we’d need a whole book for that — we can teach you how to use a specific 3D modeling program to create a specific part.

So, to get you started on the road to modding, we’ll introduce Blender , a free and open source modeling tool. We won’t teach all of Blender’s functionality; instead, we’ll teach you just enough to help you make a custom fuel tank, shown in Figure 13-1 .

krbl 1301
Figure 13-1. The part you’ll make in this chapter

Note

Kerbal Space Program’s engine, Unity , supports 3D models from pretty much any 3D modeling tool you can name. If you’re already familiar with 3D modeling tools (be it Blender or something else), you can skip this whole section and go straight to “Preparing the Part in Unity” .


Modeling a Part in Blender

If you don’t already have Blender installed, you can get it for free from http://www.blender3d.com . Follow the instructions on the website to download a copy and install it on your computer. Once you have it, start it up.

When you launch Blender, by default you’ll see a scene that contains three objects: a cube, a camera, and a light (see Figure 13-2 ).

krbl 1302
Figure 13-2. The initial state of Blender

We’ll start by removing all of the objects and replacing them with a cylinder. We’ll then start modifying that cylinder to make it look more like a fuel tank; finally, we’ll add a texture to it and then prepare it for use in-game.

  1. Delete everything by pressing A, then X. All objects will disappear from the scene.
  2. Open the Create tab on the lefthand side, and click Cylinder (see Figure 13-3 ).
    krbl 1303
    Figure 13-3. The create menu
  3. Configure the cylinder to have 12 vertices, a radius of 1.0, a depth of 1.5, and a location of (0, 0, 0). Cylinders are made up of several flat sections, which curve around in a circle; the more vertices you use, the more sections exist, and the smoother your part becomes.
    You configure the cylinder by changing the values in the pane beneath the Create menu (see Figure 13-4 ).
    krbl 1304
    Figure 13-4. Configuring the cylinder

    Note

    One unit in Blender is equal to 1.25 meters in Kerbal Space Program.


  4. Press the Tab key to enter Edit mode. The cylinder’s appearance will change to show the vertices that make up the object (see Figure 13-5 ).
    krbl 1305
    Figure 13-5. The cylinder in Edit mode

    Currently, the fuel tank is a very simple cylinder. We’ll add some caps to the top and the bottom, to make it look more fuel-tank-ish. To do this, we could design a cap for the top and then repeat the process for the bottom, but it’s more efficient to simply design the top cap and get Blender to duplicate our work for the bottom .
    To do this, we’ll cut the cylinder in half and then tell Blender to mirror it. This means that any work we do to the top will also appear on the bottom, halving the amount of work we need to do.
  5. Press Ctrl-R to perform a Ring Select and Cut. Move the mouse so that you’re cutting the cylinder into two shorter cylinders (see Figure 13-6 ), and then press Enter twice.
    krbl 1306
    Figure 13-6. Cutting the cylinder in half
  6. Hold down the Alt key (Option on OS X) and right-click on one of the vertices on the lowest ring of the cylinder. The entire lower ring will be selected.
  7. Press the X key and select Vertices from the menu that appears. The lower half of the cylinder will disappear.
  8. Click the Modifiers button in the Properties pane to open the Modifiers menu (see Figure 13-7 ).
    krbl 1307
    Figure 13-7. The Modifiers menu button
  9. Click Add Modifier, and then click Mirror.
  10. Set the mirror modifier’s axis to Z (see Figure 13-8 ).
    krbl 1308
    Figure 13-8. The Mirror modifier

    Anything done to the top of the object will now also affect the bottom. Next we’ll add the caps to the fuel tank.
  11. Alt-click one of the vertices at the top to select the upper ring (Option-click on OS X).
  12. Press E to extrude a copy of the vertices, and then press Enter without moving the mouse. This creates a duplicated copy of the vertices, which are linked to the top ring. We’ll use this to begin forming the cap.
  13. Press S to scale these new vertices out. Move the mouse to scale them out, and press Enter to confirm. The cylinder will now have a thin disc at each of its ends (see Figure 13-9 ).
    krbl 1309
    Figure 13-9. The beginning of the end caps
  14. Press E again to extrude a new top cap. Move the mouse up to thicken the cap, and press Enter to confirm. The end caps will now have a bit more substance to them (see Figure 13-10 ).
    krbl 1310
    Figure 13-10. The final end caps
  15. Go back to the Mirror modifier, press Tab to leave Edit mode, and click Apply. Press Tab to go back into Edit mode, and note that there are now more vertices. You’re now done creating the model, and it’s time to start preparing it to be textured .
    It’s helpful to think of texturing a mesh as unfolding it so that it lies flat on a sheet of paper. To do this, you’ll need to make some cuts along some of the edges, so that it can be laid perfectly flat. In Blender, these are called seams.
    Preparing a mesh for texturing is called UV unwrapping . To UV unwrap, you select the edges of the mesh that Blender should cut along as part of the unwrapping process.
  16. Press Ctrl-Tab to change the Mesh Select Mode, and select Edge.
  17. Alt-click the inner ring, outer rings, and the outermost edges of the cylinder (both the main body and the caps). See Figure 13-11 to get an idea of the edges you want to select.
    krbl 1311
    Figure 13-11. The edges to select for UV unwrapping
  18. Press Ctrl-E, and select Mark Seam (see Figure 13-12 ). This marks the selected edges as the ones to cut along.
    krbl 1312
    Figure 13-12. Marking the seams
  19. Press A to deselect all edges. Note that the edges that you marked as seams are outlined in red — when the mesh is unwrapped into a texture, these red lines are where the mesh is cut .
  20. Press A to select everything in the scene.
  21. Press U, and select Unwrap.
    When you do this, Blender creates a UV map , which identifies which parts of the mesh should show which parks of the texture. You don’t currently have a texture yet, so that’s what we’ll do next.
  22. Select UV Editing from the Layout menu at the top of the window (see Figure 13-13 ). You’re now looking at the unwrapped mesh (see Figure 13-14 ).

    Tip

    If the UV editor window doesn’t contain shapes that look at least similar to Figure 13-14 , your seams are probably not correct — run through the last several steps again.


    krbl 1313
    Figure 13-13. Selecting the UV Editing layout
    krbl 1314
    Figure 13-14. The UV Editing layout

    The UV Editing layout lets you see which parts of the mesh will map to which regions of the texture. On the lefthand side, you see the UV map — the regions that Blender has cut out for you, based on the seams that you marked. In the UV editor, these regions are called islands .
    You can select islands and press G to move them around, and press S to scale them.
  23. Press Ctrl-P to Pack Islands. This automatically adjusts the scale and position of the islands to fill the space.
  24. Create a new image by clicking the New button at the bottom of the UV pane (see Figure 13-15 ).
    krbl 1315
    Figure 13-15. Creating a new image
  25. Name the new image NiftyTank , make the width and height 1024 px, and set the Generated Type to Color Grid (see Figure 13-16 ).
    krbl 1316
    Figure 13-16. Configuring the new image

    You now have a texture, which looks like a rainbow-colored grid (see Figure 13-17 ).
    krbl 1317
    Figure 13-17. The generated texture

    It’s time to save your work.
  26. Save the blender file by pressing Ctrl-W and picking a location and filename. Call it NiftyTank.blend .
    Now to see your texture mapping in action!
  27. In the 3D view pane, change the Viewport Shading to Texture (see Figure 13-18 ). The object will then have the texture applied to it (see Figure 13-19 ).
    krbl 1318
    Figure 13-18. Selecting Textured mode
    krbl 1319
    Figure 13-19. The object, with the temporary texture

    This temporary texture isn’t the nicest looking, but it does give you an idea of how the image maps to the different parts of the mesh. Nonetheless, it’s now time to provide a better texture.
    When creating a texture, you need to know which parts of the image you create are mapped to the mesh, and how. To make this process easier, Blender can export the UV map as an image, which you can then draw over.
  28. Open the UVs menu, and choose Export UV Layout. Save the layout to an image called NiftyTank.png .
    The resulting image will look something like Figure 13-20 . It will probably vary a little, depending on whether you moved and scaled your UV regions.
    krbl 1320
    Figure 13-20. The exported UV regions
  29. Open this image in an image editor, then paint over it (if you like). You can use any image editor for this — we quite like Adobe Photoshop, but the open source image editor GIMP is available as a free download from http://www.gimp.org . The texture that we’ve created for this object looks like Figure 13-21 .
    krbl 1321
    Figure 13-21. The texture for the part
  30. Load the image back into Blender by opening the Image menu and choosing Open Image. The new texture will be applied to the mesh (see Figure 13-22 ).

    Note

    It’s common to want to make small changes to your texture and see how they look on the model. If you save your image, and then press Alt-R (Option-R on OS X) while the mouse cursor is in the UV Editor pane in Blender, the image will be reloaded and the updated texture will be applied to your object.


krbl 1322
Figure 13-22. The final model

You’re all done! When you’re happy with your model, save the file as NiftyTank.blend .

Preparing the Part in Unity

Once you’re done modeling your part, you need to prepare the object for use in the game. You do so using Unity, which is what Kerbal Space Program uses as its game engine. You use Unity to define certain pieces of information, such as the part’s collision shape.

Getting the tools

As we just mentioned, to prepare your parts for use in the game, you use Unity, the 3D game engine that powers Kerbal Space Program. You can download Unity from http://www.unity3d.com .


Note

Unity comes in both free and paid versions. The free version is all you need to make mods for Kerbal Space Program.


In addition to Unity, you also need to download a collection of tools from Squad, called the Part Tools . The Part Tools are used to export your processed parts into files that Kerbal Space Program can load.

Preparing your part

To prepare your part, follow these steps:

  1. Open Unity.
  2. Create a new project, and call it PartExporter. It can actually be called anything, but it doesn’t matter. Don’t import any packages when creating the project — you don’t need them.
  3. Unzip the Part Tools, and drag the PartTools folder into the Assets folder in the Project tab in Unity. Your Assets folder should now look like Figure 13-23 .
    krbl 1323
    Figure 13-23. Adding the Part Tools
  4. Drag the NiftyTank.blend file and your texture into the Assets folder. This adds a copy of it to your Unity project.
    We now need to configure a few things to do with the mesh. The most important thing we need to do is to make Unity generate a collider , which will tell Kerbal Space Program about the physical shape of this part. We’ll also make Unity smooth out the surface of the fuel tank.
  5. Select the NiftyTank file (it looks like a blue box); the Inspector will show the Import Settings.
  6. Set Normals to Calculate to make the tank look smooth, turn on Generate Colliders, and click Apply (near the bottom). You can see how the Inspector should look in Figure 13-24 .
    krbl 1324
    Figure 13-24. Configuring the fuel tank’s mesh
  7. Drag the NiftyTank out into the Scene tab to create an instance of it (see Figure 13-25 ).
    krbl 1325
    Figure 13-25. The mesh, added to the scene

    We’ll now prepare the part to be exported into a format that Kerbal Space Program can read.
  8. Open the GameObject menu, and choose Create Empty. A new GameObject object will appear in the Hierarchy tab.
  9. Double-click the new GameObject and rename it to “Part.”
  10. Drag the NiftyTank object in the Hierarchy tab into the Part object.
    When you’re done, the hierarchy should look like Figure 13-26 .
    krbl 1326
    Figure 13-26. The hierarchy, with the NiftyTank object inside the Part object
  11. Select the Part object. In the Inspector, click Add Component, and choose KSP > Part Tools.
    A Part Tools component will appear (see Figure 13-27 ).
    krbl 1327
    Figure 13-27. The Part Tools component

    The Part Tools component needs to know where you want to save the exported models.
  12. Create an empty folder where you want the generated files to go.
  13. Click “Set GameData directory.” A window will pop up; click Set Data Dir (see Figure 13-28 ).
    krbl 1328
    Figure 13-28. Setting the data directory
  14. Select the empty folder that you just created.
  15. Go back to the Part object. Set the Model Name to “model,” and Texture Format to “MBM” (see Figure 13-29 ).
    krbl 1329
    Figure 13-29. Configuring the export

    Tip

    MBM isn’t the only texture format you can use. Feel free to play around with others.


  16. Click Write.

If you go to the folder that you made, you’ll find model.mu and NiftyTank.mbm (see Figure 13-30 ).

krbl 1330
Figure 13-30. The exported files

You’ve now created two of the three files that this part needs to work: the .mu file contains the mesh, and the .mbm file is the texture. There’s one last thing to make: the .cfg file that describes to the game how the part works.

Writing the Config File

The config file contains all of the information that Kerbal Space Program uses to put your part in the game. This info ranges from the name of the part, to its mass, its resources, and what modules the part uses to define its behavior. (We’ll be talking about modules in more detail in “Creating a Module” .)


Note

The configuration file format consists of a sequence of nested ConfigNode, each of which consists of a label, and contains zero or more key-value pairs in curly braces. While the most commonly seen node is the PART node, there is no restriction as to what nodes can be called, which allows mods to use their own node types as appropriate. As we will see in this chapter, ConfigNodes can also be nested, and even modified after creation, which we’ll discuss in more detail in “Module Manager” .


The config file also defines important elements like where the attachment points for the parts are, and how the part can be connected to other parts.

To get started, use a text editor (Notepad, TextMate, Sublime Text, emacs, vim, etc.) to create a new file called Part.cfg , and place it next to model.mu and NiftyTank.mbm . Put the following text in it:

PART {

    // Internal name, not shown to the player
    name = niftyTank

    // What kind of part this is (leave as Part in most cases)
    module = Part

    // Who made this part?
    author = Jon Manning

    // The model file to use
    mesh = model.mu

    // How to scale this part (1.0 = original scale, <1.0 = shrink, >1.0 = grow)
    scale = 1.0

    // Top node is positioned -0.75 units below origin, angled down, normal size
    // (the fuel tank is 1.5 units tall, and centered on the origin)
    node_stack_top = 0.0, -0.75, 0.0, 0.0, -1.0, 0.0, 1

    // Bottom node is positioned 0.75 units above origin, angled up, normal size
    node_stack_bottom = 0.0, 0.75, 0.0, 0.0, 1.0, 0.0, 1

    // Attachment rules: stack, srfAttach, allowStack, allowSrfAttach,
    // allowCollision
    attachRules = 1,1,1,1,0

    // The technology you need to research in R&D to get this part
    TechRequired = basicRocketry

    // How much this part costs to add to your rocket
    cost = 450

    // Which category you can find the part in
    category = Propulsion

    // The name of the part
    title = Nifty Tank

    // The "manufacturer" of the part
    manufacturer = O'Reilly Media

    // The description of this part - no line breaks!
    description = This is a pretty nifty little fuel tank, if I say so myself.

    // Physics properties:
    mass = 0.25
    dragModelType = default
    maximum_drag = 0.2
    minimum_drag = 0.3
    angularDrag = 2
    crashTolerance = 6
    maxTemp = 2900
    breakingForce = 50
    breakingTorque = 50

    // The resources that this part contains: liquid fuel, and oxidizer
    // (Most liquid engines burn 0.9 liquid fuel for every 1.1 oxidizer you
    // burn, so include them in this ratio)
    RESOURCE
    {
        name = LiquidFuel
        amount = 90
        maxAmount = 90
    }

    RESOURCE
    {
        name = Oxidizer
        amount = 110
        maxAmount = 110
    }
}

Note

node_stack_top and node_stack_bottom are the names of the two “stack” attachment points. This allows it to be part of the stack. You can also specify node_stack_attach for an attachment point that’s off to the side.

The numbers you provide for the stack attachment points are, in order, its position x , position y , position z , normal x , normal y , normal z , and scale.

  • Position is the location of the node, relative to the origin point of the model.
  • Normal is the direction the node is facing.
  • Scale is how big the node should appear (0 = small, 1 = regular, 2 = big).

Once you’ve written your config file, it’s time to add the part to the game!

  1. Put all three files (model.mu , Part.cfg , NiftyTank.mbm ) into a folder called NiftyTank .
    Put this folder in a new folder called Parts . Put this folder in a folder called TheKerbalBook (or whatever else you want to call your mod), and put this folder in the GameData folder in your Kerbal Space Program installation (see Figure 13-31 for a more visual explanation).
    krbl 1330
    Figure 13-31. Adding the files to the game by placing them in the GameData folder

    You’re done!
  2. Start the game, and create a new rocket. Your part will appear in the Propulsion section in the Parts library (see Figure 13-32 ).
    krbl 1332
    Figure 13-32. The new part, in game
  3. Add the new part to a rocket, and fly it. It will work like a regular fuel tank.

Creating a Module

A module is a chunk of code that parts use to define their behavior. Modules make up a large percentage of the code in Kerbal Space Program: engines are modules, fuel tanks are modules, and landing gears are modules. When you’re creating a part, the role it plays in the game is defined by the modules that you use.

You can write your own modules for use in Kerbal Space Program. To do this, you write code in C# and create a .dll file containing all of your code. This .dll file is then copied into Kerbal Space Program, which loads it at startup. The code inside this module is only used when your vessel has a part that makes use of the module. This is why, for example, your ship only has access to the functionality of MechJeb when you have a MechJeb part attached to it.


Note

It really helps to know at least the basics of programming to make modules for Kerbal Space Program. Specifically, we’ll be programming this module in C#. There are many excellent resources out there to learn the language; we like Alex Okita’s Learning C# Programming with Unity 3D (CRC Press).


To get started, we’ll create a module that self-destructs when your vessel reaches a certain altitude. This module will need to be attached to a part in order for it to apply to your ship, which means that we’ll then add the module to the NiftyTank part that we created in “Parts” .

To create the module’s .dll file, you’ll need a tool to actually compile the code for you. Fortunately, if you’ve got Unity installed, you already have everything you need. Unity comes with MonoDevelop, an IDE that lets you write C#.


Note

MonoDevelop isn’t the only tool you can use. If you’re using Windows, you can also get a free copy of Microsoft Visual Studio Community.

In this book, we’re using MonoDevelop for a couple of reasons:

  • You get it as part of Unity, so you don’t need to download an additional piece of software.
  • Visual Studio Express is only available for Windows, so if you’re using OS X or Linux, you’re out of luck.

Writing the Code

Let’s get started by creating the project, and setting it up:

  1. Open MonoDevelop, open the File menu, and choose New → Solution. Go to the C# section and create a new library (see Figure 13-33 ). Name it TheKerbalBook.
    krbl 1333
    Figure 13-33. Creating the project
  2. We now need to make sure that the C# library targets the correct version of .NET. Right-click on the second TheKerbalBook icon, and choose Options. In the Build → General settings, set the Target Framework to “Mono / .NET 3.5”.
  3. When you create the project, it starts with a class called MyClass.cs . Right-click the MyClass.cs file and choose Rename. Rename the file to SelfDestruct.cs . See Figure 13-34 to see it in action.
    krbl 1334
    Figure 13-34. Renaming the class file

    We now need to give this project access to the code that powers Kerbal Space Program.
  4. Right-click the References folder, and choose Edit References (see Figure 13-35 ).
    krbl 1335
    Figure 13-35. Accessing the Edit References screen

    The Edit References window appears. In this window, you can specify which assemblies (chunks of code) the module will have access to.
  5. Go to the .Net Assembly tab, and browse to your KSP installation. You need to select the compiled game code so that you get limited access to the code:
    1. On Windows, go to the folder that contains KSP.exe and open the KSP_Data folder, then go to Managed.
    2. On OS X, go to the folder that contains KSP.app , go into KSP.app (it’s a folder), and go to Contents → Data → Managed.
    3. Select Assembly-CSharp.dll and UnityEngine.dll , and click Add, then click OK (see Figure 13-36 ).
krbl 1336
Figure 13-36. Selecting both Assembly-CSharp.dll and UnityEngine.dll

Your project now has access to Kerbal Space Program’s code. It’s time to write some code of your own!

To define a module, you create a subclass of the PartModule class. Inside this class, you provide your own functionality and data. There are three main things that you care about when writing a module: fields , events , and actions .

Fields
A field is a piece of data that’s stored in the part. Fields can be numbers, pieces of text, on/off values, or other kinds of data. Fields can optionally be exposed to the player to view or modify.
Events
An event is a function in your code that can be triggered by a button click. For example, when you right-click a separator, the blue buttons in the pop-up window are events.
Actions
Actions are similar to events, except that they’re triggered by the game as part of a group of other actions. The best example of this is when you define an action group in the editor: when you trigger the Abort action group by pressing backspace, all parts that have a module with an action in that action group run their code.

In addition to fields, events, and actions, your code can also override certain important functions that let you respond to the changing state of the game. For example, override the OnUpdate method to provide a method that’s run every frame:

  1. Open SelfDestruct.cs and add the following code:
    using System;
    
    namespace TheKerbalBook
    {
        public class SelfDestruct : PartModule
        {
            // The altitude at which we'll self destruct.
            [UI_FloatRange(minValue = 500f, maxValue=100000f,
                stepIncrement=1000f)]
            [KSPField(guiName="Altitude", guiActive=true, isPersistant=true)]
            float altitudeThreshold = 10000;
    
            // Whether or not automatic self-destruct is turned on.
            [UI_Toggle]
            [KSPField (guiName="Destruct", guiActive=true,
                isPersistant=true)]
            bool selfDestructEnabled = true;
    
            // Called every frame.
            public override void OnUpdate() {
    
                // If self-destruct is enabled, and the altitude of
                // the vessel that this part is attached to is over
                // the altitude threshold (defined above), then
                // self destruct
    
                if (vessel.altitude > altitudeThreshold &&
                    selfDestructEnabled) {
                    PerformSelfDestruct();
                }
    
                base.OnUpdate();
            }
    
            // Adds an action that can be added to an action group in the
            // editor.
            [KSPAction("Self Destruct")]
            public void PerformDestructAction(KSPActionParam param) {
                PerformSelfDestruct();
            }
    
            // Adds a button to the right-click menu in the editor. This
            // function is also called by the PerformDestructAction and the
            // OnUpdate functions (defined above)
            [KSPEvent(active = true, guiActive = true,
                guiName = "Self Destruct")]
            public void PerformSelfDestruct() {
    
                // Kaboom! This will destroy this specific part, leaving the
                // rest alone.
                part.explode();
            }
        }
    }
  2. Open the Build menu and select Build All.
    Your code will be compiled, and it’s now ready to be added to the game.
  3. Browse to the folder where your project files are stored.
    A new bin folder has been created. Inside this folder is a folder called Debug , and inside that is a file called TheKerbalBook.dll (among other files).
  4. Create a folder called Plugins inside your TheKerbalBook mod folder. Copy the TheKerbalBook.dll file into that folder.

Updating the Part

Your code will now be loaded when the game starts up. There’s one last thing left to do: add the module to the part. This will make the NiftyTank, and only the NiftyTank, have the self-destruct feature:

  1. Open the Part.cfg file that you created for the NiftyTank, and add the following MODULE section near the end:
        RESOURCE
        {
         name = Oxidizer
         amount = 110
         maxAmount = 110
        }
    
        MODULE
        {
         name = SelfDestruct
        }
    
    }

    It’s time to test!
  2. Run the game.
  3. Make a rocket that uses the NiftyTank. Right-click on the NiftyTank — note that you can set the self-destruct altitude, as well as whether or not self-destruct is enabled (see Figure 13-37 ).
    krbl 1337
    Figure 13-37. The module’s fields and events in the editor
  4. Launch the rocket, and fly around. When you hit 10,000 meters up, the rocket will explode. If you right-click on the part, you’ll get an additional button that, when clicked, detonates the part immediately (see Figure 13-38 ).
krbl 1338
Figure 13-38. The module also adds a button that instantly self-destructs the part in-flight

You’ve just made your first mod!

Module Manager

This section describes Module Manager (MM), a mod by Ialdabaoth (creator) and Sarbian (maintainer) that lets you change how parts are loaded by Kerbal Space Program. A complete description of parts and all their modules is beyond the scope of this book, but by looking at the files in the subdirectories of the Kerbal Space Program/GameData/Squad/Parts folder on your machine you can find most of the stock parts that ship with the game.

If you install any mod at all, there’s an excellent chance it will come with Module Manager. While it’s not necessary to understand MM in order to use and configure mods, it does provide a powerful way to alter the game and allows you to write many mods with no prior coding experience necessary. If you’re playing with mods, there’s a chance you’ve already got Module Manager installed; if not, you can install it easily using the CKAN (refer back to “Installing Mods Using the CKAN” for details).

The reason why Module Manager is so useful is that it allows you to alter existing parts and configuration for the game. For example, we may wish to alter the mass of the Mk1-2 pod to be 4.3675 tons (the same mass as the real-world Apollo command module). We can do this by placing the following into a .cfg file in your GameData directory containing the following:

@PART[Mark1-2Pod]
{
    @mass = 4.3675
}

This code looks very similar to how we would define a new part, except the at-signs indicate we wish to modify an existing part or attribute. By default, Module Manager will search for a part with the name specified in square brackets; however, as we’ll see in a moment, there are other ways to select parts.

A great many mods for the game are written entirely using Module Manager, as it can not only define new parts and change existing ones, but also place them in the tech tree, alter parameters for other mods, and generally allow you to configure everything .


Tip

If you have Module Manager installed, you can start KSP with the -nyan-nyan command-line switch for an even better loading screen.


Basic Operations

Module Manager supports a number of basic operations. The most commonly seen is the @ prefix, which changes existing values, as shown in the previous Mark1-2Pod example. However, the @ prefix does not create new values. This can be used to our advantage, as it ensures that Module Manager won’t create a part that isn’t loaded. However, when you are changing values within a part, it’s generally safer to use the % prefix, which creates the attribute if it does not already exist:

@PART[Mark1-2Pod]
{
    @mass = 4.3675  // Does nothing if the part had no mass
    %cost = 10000   // Creates the 'cost' field, even if previously absent
}

Note that if we didn’t use a prefix at all, Module Manager would add the field to our ConfigNode:

@PART[Mark1-2Pod]
{
    mass = 4.3675   // Uh oh, our pod now has mass *twice*.
}

Module Manager also allows you to delete nodes, which can be useful when you are performing complex changes, including removing behaviors or functionality you may not like. Note that when removing both simple attributes and larger modules, you still need to include a value or block (curly braces) for valid syntax, even though the values themselves are ignored:

@PART[Mark1-2Pod]
{
    !ContrabandSandwich = DELETE  // No contraband sandwiches here!
    !MODULE[ModuleReactionWheel]  // Remove the reaction wheel
    {
    }
}

Finally, you can clone nodes with the + operation. This is particularly useful for making a new part based on an existing part:

+PART[Mark1-2Pod]
{
// We need to change the part name, otherwise we'll end up
// with duplicate parts!
%name = ElectricPod
// Human visible title
%title = Electric Pod
%description = The Electric Pod is just like the Mk1-2 pod, but all the reaction
    wheel and monopropellant space has been filled with batteries!
!MODULE[ModuleReactionWheel]
{
}
!RESOURCE[MonoPropellant]
{
}
// Change existing resource limits.
    @RESOURCE[ElectricCharge]
    {
        %amount = 9001
        %maxAmount = 9001
    }
}

Selecting Parts

When modding, at some point you’ll likely want to find all the parts that have a particular attribute and change them in some way. For example, with a life-support mod you may wish to find all parts that have a crew capacity and add food, water, and oxygen supplies to them.

Module Manager supports a :HAS[] syntax for selecting parts, allowing you to select parts based upon the presence of an attribute or module. For example, if we wanted to select all single-person pods and passenger compartments, we could do this:

@PART[*]:HAS[#CrewCapacity[1]]
{
}

It’s possible to provide multiple :HAS[] conditions. We can select single-person pods (but not passenger compartments) by looking for the ModuleCommand module (designated with an @ ):

@PART[*]:HAS[#CrewCapacity[1],@MODULE[ModuleCommand]]
{
}

Likewise, we could select all single-person passenger compartments by looking for the absence of the same module:

@PART[*]:HAS[#CrewCapacity[1],!MODULE[ModuleCommand]]
{
}

One of the great uses for this technique is being able to add a module if it doesn’t already exist. For example, if we wanted to add MechJeb to all command parts that didn’t already have it, we can do so!

// Add MechJeb to all command-modules that don't already have it.
@PART[*]:HAS[@MODULE[ModuleCommand],!MODULE[MechJebCore]]
{
    MODULE
    {
        name = MechJebCore
    }
}

Load Order

When you are applying tweaks using Module Manager, it’s important for things to run in the right order, especially if you wish to make adjustments to an existing mod.

Module Manager allows for three special ordering directives: :BEFORE[] , :FOR[] , and :AFTER[] , which allow change ordering to be more precisely controlled.

By marking a stanza with :FOR[] , we can indicate it’s for a particular mod:

@PART[Mark1-2Pod]:FOR[KerbalBook]
{
    @mass = 4.3675
}

Module Manager will execute all the stanzas of a given mod together, even if they’re spread among different files. This makes it possible for other mods to ensure their work is done before or after that mod’s changes are made. For this reason, it’s considered best practice to always tag your stanzas with :FOR[] directives if you’re going to distribute them, so other mods can ensure they can run before or after your own changes.


Tip

Since a :FOR[] tag will signal to Module Manager that a given mod is installed, you should make sure that your mod-name is unique to your mod. This will allow other mods to better integrate with yours (discussed momentarily), and also make sure you don’t interfere with any other mod’s compatibility modes.

Module Manger will run a pass for every assembly and top-level folder in the GameData directory, so using a :FOR[] with the same name as your mod’s directory name is strongly recommended.


For example, if we wanted to adjust the antenna properties added by RemoteTech, we need to run after RemoteTech; otherwise, we’ll have no antenna module to change:

@PART[probeCoreOcto]:AFTER[RemoteTech]
{
    @MODULE[ModuleRTAntennaPassive]
    {
        // Boost the Octo's in-built antenna to 30k range.
        %OmniRange = 30000
    }
}

In the same way, it’s also possible to run :BEFORE[RemoteTech] (or any other mod), or :NEEDS[RemoteTech] if you just need RemoteTech to be installed but aren’t concerned about the ordering. A useful trick is to run code before your own mod, if there’s initialization work that needs to occur before the main changes are executed.

Module Manager considers mod names to be case-insensitive, so KerbalBook is the same as KERBALBOOK .

Module Manager also allows stanzas to be tagged as :FIRST or :FINAL . These don’t take any mod names but instead run before or after all other Module Manager passes. If you’re tweaking your own game, then using :FINAL is an easy way to make sure your changes happen after everything else (and hence take priority), but its use is discouraged in release mods, as it can prevent others from effectively building on your work, including providing compatibility between mods.


Tip

If you want a quick reference to the ordering of ModuleManager passes, they are:

  • :FIRST
  • Legacy passes (directives that don’t fit anywhere else)
  • :BEFORE[] ,:FOR[] ,:AFTER[] for each mod (in alphabetical mod order)
  • :FINAL

If a mod doesn’t exist, then any :BEFORE[] , :AFTER[] , or :NEEDS[] directives referring to that mod will not be executed, which is why it’s important not to accidentally add a directory, assembly, or :FOR[] which creates a pass by accident.


Advanced Example: Tweaking Science Experiments

One popular use of Module Manager is to tweak how science experiments work. For example, a thermometer’s readings are simple enough (a temperature) that they should be fully transmissible, whereas Mystery Goo represents a material sample that might have to be returned home to be properly studied.

Tweaking the transmit values requires quite a bit of Module Manager syntax, but it means we can adjust experiments even if mods have added new parts with them! Here’s how we can do that for the temperature scan:

    @PART[*]:HAS[@MODULE[ModuleScienceExperiment]
        :HAS[#experimentID[temperatureScan]]]:FINAL
    {
        @MODULE[ModuleScienceExperiment]:HAS[#experimentID[temperatureScan]]
        {
            @xmitDataScalar = 1.0
        }
    }

Note

The first line of the preceding code — that is, everything up to the curly brace ({ ) needs to be on the same line. We’ve had to break it into two lines here because it didn’t fit on the page, but when it appears in a file, it has to be in a single line.


While this code looks pretty scary, it’s not too hard to understand once we break it down into pieces. These changes apply to all parts (@PART[*] ) that run science experiments (:HAS[@MODULE[ModuleScienceExperiment]... ) that measure temperature (#experimentID[temperatureScan]]] ). Additionally, we then indicate that we want to run them after all other parts have been configured (:FINAL ).

Once we’ve found a part that matches what we’re after, we use Module Manager to find the module describing the temperature experiment (@MODULE[ModuleScienceExperiment]:HAS[#experimentID[temperatureScan]] ), and then modify the transmit value to send the full science value (@xmitDataScalar = 1.0 ).

This may seem like a lot of work, but we’ve purposely chosen a more complex example to show off the power of Module Manager to select and manipulate parts.


Note

We could have just used @PART[*] without any :HAS blocks at all and this still would have worked, as our inner block is specifically checking for the right experiment. The advantage of the long selector is that it’s easier for us to modify the code in the future in case we want to make other changes to temperature-scanning parts (but not necessarily to the science experiment itself), such as adjusting their price or ensuring they all have the same mass.


Summary

When you mod KSP, you’re opening a huge amount of possibility.

In this chapter, we’ve only had space to cover a fraction of what’s available to you when modding KSP. To learn more about what’s available, check out the community documentation , as well as the Add-on Development forum and TaranisElsu’s excellent example projects .

In the next chapter, we’ll move beyond the world of software and look at what you can do to add real-world hardware to the game.