Jump to content

Modders Notes for Making History Expansion


Recommended Posts

 

Making History Modders Doc.

Overview and Basic starting Info
Making History adds the Mission Builder and Missions game mode to KSP.
There are two new game modes: MISSION and MISSION_BUILDER.
Both of these game modes can only be used and will only run if the Making History expansion is installed.
The mission builder is a new scene which is used to create missions which then can be shared and played.
This document gives some basic information for how to mod Making History.

Localizing a Mission
Preparations
Before you begin your localization efforts, there are a few definitions that you have to plan. You need to define your auto-localization key format and create your dictionary files.
1. Auto-localization format: Making good auto-localization keys requires for them to be unique.

Within the scope of the Missions Editor, we recommend a naming convention of #<Name> <Mission> <purpose_or_number>, where "Name" is your name or alias, "Mission" is a short name for your mission and the third component is an identifier, it can be a number or description of where the text is used.
Examples: #Me_MyAwesomeMission_0000 ; or #JohnDoe_JohnsAwesomeMission_beginTest;
or anything of the sort.
Note! This is just a suggestion, remember, as long as your keys are unique and they begin with "#" you can define whatever format you like.

2. Dictionary file: Create a text file inside your mission folder (<KSPRoot>/Missions/<yourMissionName>/Localization), if the directory doesn’t exist you can create it yourself. The file must be have a .cfg extension. In
that file, copy the following text:
 

Localization
{
    en-us
    {
        #Me_MyAwesomeMission_0000 = Cool Mission
        #JohnDoe_JohnsAwesomeMission_beginTest = Do awesome Kerbal stuff
        .
        .
        .
    }
    es-es
    {
        #Me_MyAwesomeMission_0000 = Mision Genial
        #JohnDoe_JohnsAwesomeMission_beginTest = Haz grandiosas cosas Kerbal
        .
        .
    }
    //all the other languages you want to support
}

Warning! Remember to substitute the id with your mission’s and the text with some relevant lines that you are going to localize in your mission.
Note that the auto-localization key for the equivalent line in all the languages is the same. You
also begin the section with the language id of the language to localize, these are the languages supported in KSP and their id’s:

  • english en-us
  • German de-de
  • French fr-fr
  • Italian it-it
  • Spanish es-es
  • Russian ru
  • Japanese ja
  • Simplified Chinese zh-cn
  • Portuguese pt-br

On another note, if for whatever reason you need more than one dictionary file, you can create as many as you like, as long as they are in the Localization subdirectory of your mission, have a .cfg file extension and follow the format, they will be picked up by KSP.

Localizing your Mission
Play your mission thoroughly and identify all the text that’s presented to the player, this is the only text that we recommend you localize. Define your autoLOC format and dictionary file as per the instructions in the previous section and you’re all set to start!

We present a very simple example with just a few nodes, but it’s enough to illustrate the concept.

EenwTgAnW37UYEZ48UArCPVZJAjUxXdnqjO7ppd7

In this example the only nodes that require localization are the Dialog Messages and, very important, the briefing. Open the dictionary.cfg file and assign auto localization keys to the strings you need to localize. After that, create the language nodes that you want and are able to support. It may be a good idea to ask around in the community if anyone is able to help you with languages that you don’t speak yourself. Save your file when you’re done.


When you have the auto-localization keys and the strings matched, all you have to do is input
them in the appropriate text field in the Mission Editor (ME). If your dictionary file was already saved before you opened the ME, the keys will be translated into text instantly. Otherwise, you can reload the ME and they will show.
You will also notice that a text field is blocked after you use an auto-localization key in it. You used the wrong key and can’t correct it because the field is locked? No problem, open the Debug Menu (Left Alt+F12) and navigate to Mission Tools. You will see a checkbox that says "Override Mission Editor auto-localization lock", activate it, and the field will be open for editing again.

Auto-localization string showing in the text field.

Nnkna_1YhvSRmUxK4pfCiJC-qvesnW0GiP-29J5H

 

Locked field showing the localized text.

MRV2TEt-04LkTCg0o0dYWnfYijklUW2-reaapfCD

 

Debug Menu override.
c12A5PErNM9pJSXZ2-eCqfFCq6kWYUbwscYK8asg

Once you’re done editing, you can save your file and it’s ready to be shared. If you start the mission when KSP is set to a language defined in your dictionary, the mission will just be translated, no further intervention will be needed.

Spanish nodes translated like magic.
DZTtKvnHzESD8bMdcdzoGn1-jNoUCDKqvYH1fOA3

 

File Persistence

Missions consist of a number of files for each mission.
persistent.mission - The actual mission file itself.
Persistent.loadmeta - Meta data used in the in-game dialogs.

You will also see a number of other files in the saves folders for missions (when missions are played or tested).
These include .loadmeta files and .missionsfs files.
The .missionsfs files are copies of the .sfs file during mission playthrough that are created at various checkpoints in the mission (currently - at the very start and when vessels are created).

Path Structures
\KSP\Missions\* contains all user created missions. One folder for each mission.
Inside these folders you will find a .mission file which is the actual mission file itself that is generated in the Mission Builder.
There will also be a Banners sub-folder which is where you can place your own banners for mission fail, success, and mission play dialog.
The Ships sub-folder will contain SPH and VAB folders with .craft files. These are where the creator defined craft files are stored for the mission.

When a player plays a mission from the main menu the .mission file is read and a Game save is generated into a .sfs save file which is then saved into the \KSP\saves\missions\* folder.
When a player tests a mission from within the mission builder the .mission file is saved and then re-read and a Game save is generated into a .sfs save file which is then saved into the \KSP\saves\test_missions\* folder.

The saves folders will also contain copies of any craft files that are either creator defined or player defined during the mission playback. These are automatically copied by the mission system when a mission playthrough is started or a mission test session is started.

Each Mission referenced via the MissionSystem contains a reference to it’s MissionInfo (MissionFileInfo) file.
MissionFileInfo Class
SimpleMission - returns a copy of the Mission (.mission file) without craft files.
MetaMission - the meta file (.loadmeta) info for the mission.
savedMission - the saved (.sfs) file for the mission, or null if there isn’t one.
MetaSavedMission - meta file (.loadmeta) for the saved mission if it exists.

Static:
CreateFromPath - will create and return a MissionFileInfo instance for any mission found at the supplied input file path.

There are a number of other helper methods and properties.
Refer to the API docs on this class for further info.


Defining Mod nodes.
The mission Builder loads and builds a list of what’s called Basic Node’s (templates populated into MEBasicNode class) for each node available in the mission builder on startup.
These nodes are the ones listed in the toolbar on the left side of the mission builder.

When creating your own Mod node you need to not only define your mod node in a class/code and compile to a plug-in DLL but you also need to define the Basic Node for the mission builder to make it available to players.

This is done by defining a cfg text file that you can place anywhere in GameData.
For the stock nodes supplied in the Making History expansion these are stored in \GameData\SquadExpansion\MakingHistory\Nodes folder if you want to refer to some examples.

MEBASICNODE fields

  • name - the internal name of the node.
  • displayName - the localization tag/text that is displayed in the UI to the user for the node.
  • description - the localization tag/text that is displayed in the UI to the user for the node.
  • tooltipDescription - the localization tag/text that is displayed in the UI to the user as a tooltip when hovering over the node in the toolbar.
  • isObjective - if true this node is treated by default as an objective node in missions. Mission creators can change a node to be an objective in the SAP. But this defines the default value for the node.
  • Category - this is the category (group) this node belongs to and used to categorize them in the toolbar within the mission builder.
  • categoryDisplayName - The localization tag/text for the category.
  • iconURL - The URL for the icon for the node that is displayed in the UI.
  • actions - the name of an ActionModule (class) attached to this node. You can specify multiple actions = parameters inside the node.
  • tests - the name of a TestModule (class) attached to this node. You can specify multiple tests = parameters inside the node.
  • SAP_PARAMETERS - this group will have a sub-node (MODULE_PARAMETER) for each parameter that is to be displayed from the module code in the SAP to the mission creator.
    • Each MODULE_PARAMETER will have:
      • module - the class name of the module.
      • parameter - the parameter field name (the name of the field in the C# class) of the parameter.
  • NODEBODY_PARAMETERS - this group works the same as SAP_PARAMETERS but defines which fields are available/will display in the node body for the node on the misison builder canvas.


Adding Test Modules
 
The Test modules are one of two types of modules that can be attached to a node in the Making History expansion, these modules are used to test certain conditions are true or not and if true the mission system will activate the node that the test module is connected to.
Creating and implementing a basic TestModule
The following steps will guide us to how to create and implement a custom test module in one of our tests.
The first step is to create a custom test module class, in our example we are going to create a test module that tests if the active vessel has 2 or more kerbals on-board.
1 Create our ActionModule class
Typically when creating custom test modules we need to override the following methods from the TestModule base class:

  • Awake: This is the entry point of the TestModule think of this as the constructor is used to set default values and initialize variables.
  • Initialize: This method is called when the node is initialized and is used to set up things that may need the MENode (the node this module is a part of) prior to Awake. But always remember to call the base.Initialize first.
  • Test: This method is called when the actual node is being tested by the Mission System. If the Test returns true the Mission System will make the node this Test is attached to the active node in the mission.GetInfo: This method returns the description of this node to be displayed in the UI.
  • GetAppObjectiveInfo: This method returns a string that is displayed for the test to the mission player in the Missions App when playing the mission.
  • GetNodeBodyParameterString: This method receives the field that is going to be displayed in the node body and returns a formatted string with useful information about that field.

r6r4uHeexi6llC7nI5uwje0aPfinS2hbrEtTpe6E

2 Add the custom logic to the test

After the class has been created we need to input our new logic into the override methods, so we start with the main functionality and override the Test method to something like this.

eQh5X1sphRARQ9lrI2bxdpUeRMF87KG6wzk5Pfln

Then we modify the other methods to set all the UI for our score system as follows

dnBFuIYUAqGxTGThrGcUwWKIhmY3CIQWsQ3s0cGw

3 Make our custom values persistent in the mission

As all the other module classes in the expansion this class needs to save and load its values from the mission or savegame cfg file for them to be persistent, so we need to override the Save and Load methods from the IConfigNode interface.

Ch-QjwdSPjkFgXtPd1qzZCTaE4schJ09OHX70OMg

 

Adding Action Modules

The Action modules are one of two types of modules that can be attached to a node in the Making History expansion, these modules are used to perform actions when the node is executed.

Creating and implementing a basic ActionModule

The following steps will guide us to how to create and implement a custom action module in one of our tests.

1 Create our ActionModule class

The first step is to create a custom action module class, in our example we are going to create an action module that send a debug message when triggered.
Typically when creating custom action modules we need to override the following methods from the ActionModule base class:

  • Awake: This is the entry point of the ActionModule think of this as the constructor and is used to set default values and initialize variables.
  • Initialize: This method is called when the node is initialized and is used to set up things that can only be set when the node is active or that may need the MENode (the node this module is a part of) prior to Awake.  But always remember to call the base.Initialize first.
  • Fire: This method is called when the actual node is triggered and the action is going to be performed.
  • GetInfo: This method returns the description of this node to be displayed in the UI.
  • GetAppObjectiveInfo: This method returns a string that is displayed for the test to the mission player in the Missions App when playing the mission.
  • GetNodeBodyParameterString: This method receives the field that is going to be displayed in the node body and returns a formatted string with useful information about that field.

NJt6RAmIFiMqV719p35GdkpQoUJKxS8HyR0wbU1h

2 Add the custom logic to the action

After the class was created we need to input our new logic into the override methods, so we start with the main functionality and override the Fire method to something like this.

VCRumCF8VH0TtJiLEoq1y9QvNgDOySyAYZKd1b8P

Then we modify the other methods to set all the UI for our score system as follows

bfdcsGqXw5iOK4y6B_d3515UF_tyakzS9ZtvUn8L

3 Make our custom values persistent in the mission

As all the other module classes in the expansion this class needs to save and loads its values from the mission or savegame cfg file for them to be persistent, so we need to override the Save and Load methods from the IConfigNode interface.

XTAZb6VF8LVma1-fTgm2kjkQtg5k2wOJobNl3a9m

 

 

Modding - Part adjusters / failures / repairs

Part adjusters can be added/modded and used in all game modes in KSP as long as the Making History expansion is installed. If it is not installed they won’t break KSP but they also will not function (will do nothing).
Adjusters tweak the parameters on a part module. Failures are just more drastic adjusters that break some of the part module functionality. They both use the same framework, so the term adjusters will be used for both in this document.

Creating an adjuster or failure

A list of all adjusters and failures that we’ve implemented can be found here:
https://kerbalspaceprogram.com/api/namespace_expansions_1_1_missions_1_1_adjusters.html

Subclass the appropriate base class if there is one, such as AdjusterEnginesBase if you’re creating an engine adjuster, otherwise subclass AdjusterPartModuleBase.

If you don’t want your adjuster to be added to the list visible in the mission builder (because it’s the parent class for a bunch of other adjusters for example), make it abstract. The list is populated automatically and will skip abstract classes.

To control the data that’s displayed in the SAP that allows users of the mission builder to customise the adjuster, you can use attributes on your fields. Look at the child classes of MEGUI_Control for the ones that will work for adjusters. They are listed here:
https://kerbalspaceprogram.com/api/class_expansions_1_1_missions_1_1_editor_1_1_m_e_g_u_i___control.html

The fields disableKSPActions, disableKSPEvents, disableKSPFields will disable each of those display types in the Parts Action Window when the adjuster/failure is activated. Set them in the constructor.
The field canBeRepaired is used to allow the player to repair the failure with a kerbal. If it’s set to false, then only the mission creator can repair the failure with a repair action node. Set the default in the constructor.
Override the GetTargetPartModule() method and return the type of the class that will work with the failure. So for example, return typeof(ModuleEngines) if the adjuster modifies the engines. (If you’re subclassing one of our base classes apart from AdjusterPartModuleBase, then you can ignore this because they do this already.)
Use the Activate() method to perform any one-time processing that must be done when the adjuster is added to the part module. Also, make sure to call UpdateStatusMessage() to set the status message that will appear in the Parts Action Window. It will appear even if you've turned off the rest of the PAW displays.
If you want to modify some part parameters every frame, please keep in mind that adjusters can stack. Implementing a type of update that will allow several adjusters to operate together at the same time is highly recommended, so multiply numbers instead of setting them to specific numbers for example.
Don’t forget to override the Save() and Load() functions!
If you’re implementing adjusters for your PartModules, OnModuleAdjusterAdded() will be called when an adjuster is added and OnModuleAdjusterRemoved() will be called when one is removed.
Adjusters will be added to part modules through the part failure node, but to manually add an adjuster to a part module, call PartModule.AddPartModuleAdjuster().

 

Repairs

Repairs work by removing the adjuster from the list of adjusters acting on the part module.
Adjusters will be removed from part modules through the part repair node, but to manually remove an adjuster from a part module, call PartModule.RemovePartModuleAdjuster().
The Deactivate() method will be called on the adjuster when it is removed. Use this to fix all of the failures that you caused when it was added!

 

 

Scoring and Objectives

The score system allows the mission to implement multiple criteria and customization to how the score awarded during the mission.

How does it work?

The MissionScore class is the main class of the score system, it handles how many score systems are available and which ones are currently active in the active node.

Each score module inherits from the ScoreModule class, this class is similar to the TestModule or ActionModule classes and contains default methods to interface the system, the principal method is AwardScore this method receives the current mission score and then returns the modified value, this method is called on each of the active score systems by the MissionSystem when the action is executed.

To add new score modules we need to create our own ScoreModule classes that will handle how the score is awarded and add them to the global score systems. These are defined as an static list in the MissionScore class and can be expanded by mods.

Creating and implementing a basic ScoreModule

1 Create our ScoreModule class

The first step is to create a custom score module class, in our example we are going to create a score module that awards you a higher score based on how many parts your vessel has..
Typically when creating custom score modules we need to override the following methods from the ScoreModule base class:

  • GetDisplaName: Returns the UI display name of the ScoreModule this is value is displayed in the SAP control.
  • AwardScore: This method receives the current mission score and returns the new mission score to be applied.
  • ScoreDescription: This method returns a string with the description of what this score module does to be displayed at the end mission summary or the score summary in the mission briefing dialog.
  • GetDefaultPinnedParameters: This method returns a list of field names within this class that want to be pinnable in the SAP to be displayed in the node body.
  • GetNodeBodyParameterString: This method receives the field that is going to be displayed in the node body and returns a formatted string with useful information about that field.

WZv7qT5MnR0PTvpCZi647C6tMWGCpKmodNRDU-Pz

2 Add the custom logic to change the score

After the class is created we need to input our new logic into the override methods, so we start with the main functionality and override the AwardScore method to something like this.

cqkJjVKQ7YUa1cr4hxKNXhz5i5_IBNSEZ6xreXE1

Then we modify the other methods to set all the UI for our score system as follows

VbcWklRz5fLOfayh7rSyYysg__QhDv5Xpkd-rmol

3 Make our custom values persistent in the mission

As all the other modules class in the expansion this class needs to save and loads its values from the mission or savegame cfg file for them to be persistent, so we need to override the Save and Load methods from the IConfigNode interface.

Zd7f7pJa9SJKU-0RhWVYf_Mb09xNBLFdvfIElA2v

4 Register the new ScoreModule

Now as a final step we need to register the new score module to the list of global score modules, to do that we need to call the static method of the MissionScore class AwardedScoreDescription.

JMqhuw8uI4xpov9G8S7Dof_hnwCauHVPx6F-TMq-

Use it in game

Now the score module should be visible in game like this in any of the score nodes

1djREiIasa8W7oNObJjqZbpzisorJ66AtDloxya5

2lXqoEtDnj2e9BCWcENwdHfGIa8GAltZCLOcL3B3

 

Launchsites

With the Making History DLC it is possible to add launchsites into the stock game.
Making History adds several new stock launchsites to the base game and these launchsites are available in all game modes as long as the Making History Expansion is installed.
Mods are also able to add launchsites to the game that will function in all game modes as long as the Making History Expansion is installed (if it is not installed, they will not be availlable or functional).
It is also possible to add mod launchsites to missions as well by defining a launchsite and adding a basic node configuration to the game.

This is all controlled via the PSystemSetup class. Once you have met the prerequisites and written a plug-in to add your launchsite into the game it will automatically appear in the list of launchsites in the VAB/SPH and the vessel launch dialogs when clicking the Runway and LaunchPad in the KSC scene.

PSystemSetup class

Properties:

  • StockLaunchSites - an array of the stock launchsites available in any game mode. Mods cannot add to this list.
  • NonStockLaunchSites - an array of non stock launchsites - this includes mission placeable launchsites during mission play, but also contains mod launchsites added in any game mode. NB: You cannot change this array directly, rather you add launchsites using the methods below.
  • LaunchSites - a list of all LaunchSites currently in the game.

Methods:

  • IsStockLaunchSite - can be called to determine if a launchsite (by name) is stock or non stock.
  • RemoveNonStockLaunchSites - as the name implies - it will remove ALL non stock launchsites.
  • GetLaunchSite - find and return a launchsite by name.
  • GetLaunchSiteBody - return the CelestialBody a launchsite is situated on (by name).
  • GetLaunchSiteBodyName - return the CelestialBody name a launchsite is situated on (by name).
  • GetLaunchSiteBodyDisplayName - return the CelestialBody display name (localized) a launchsite is situated on (by name).
  • AddLaunchSite - Add a launchsite into the game. (See below on what is required before you can call this).
  • RemoveLaunchSite - Remove a launchsite from the game.

How to add a LaunchSite into KSP with Making History Expansion installed.

Pre-requisites:

  • A launchsite model. This document will not go into the details of how to get your model into the game. But this is possible to do (not as a part) using asset bundles or you can create a mu file for your model which the GameDatabase will load as a model (no cfg file) and you can then get the model from GameDatabase and instantiate an instance.
  • The model instance must have a PQSCity2 component. - you will have to add this component using plug-in code and define the necessary variables for this class. See the API docs for this class.
  • The model must have spawn point reference transform/s. (At least one). This is a transform where launched vessels will be spawned on the model.

Adding:

  • Once you have your model and it's instance setup you need to define the LaunchSite class by creating a new LaunchSite instance using it's constructor and then passing it into PsystemSetup.Instance.AddLaunchSite method.

To construct a LaunchSite class you need the following variables:

  • The internal Name of the LaunchSite, should contain no special characters or spaces.
  • The PQS Name the LaunchSite is on.
  • The Name of the LaunchSite (displayed/localized name).
  • The SpawnPoints array for the LaunchSite - you will need to create an array of LaunchSite.SpawnPoints[] that have been setup appropriately. See the API docs for the LaunchSite class.
  • The URL for the launch Site transform from the PQS down it's children path.
  • The Editor Facility the launch site is associated with.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...