Diazo Posted December 20, 2016 Share Posted December 20, 2016 (edited) The basics, getting started with writing plug-ins. Welcome to a quickstart guide on how to start writing a code plug-in for Kerbal Space Program. This is a quick guide intended as an overview on getting started and what hooks are available in KSP where you can attach your code. It is not intended as a step-by-step tutorial, rather it is intended to make you aware of your options so you can then investigate in more detail which options you wish to use. IDE Setup The hooks. KSPAddon ScenarioModule VesselModule PartModule Common Methods Common References On-Screen GUI Toolbar button GameEvents System ConfigNode overview Save/Load Data 1) IDE Setup Writing a code plug-in for KSP is done in C# so we need a program (IDE) to write code in that can produce the .dll file from that code that KSP will recognize. Any program that can make .dll files will work, this document uses Microsoft Visual Studio for its examples. Once the IDE program is installed, start a new project and make sure you set the “.Net Version 3.5”. If you do not the project will compile for the most recent version of .Net which is 4.5 and KSP will not handle it correctly and throw errors when it tries to load. We then need to tell the IDE where to find the References to the KSP files. In your project, add a reference to UnityEngine.dll, UnityEngine.UI.dll, Assembly-Csharp.dll, Assembly-Csharp-firstpass.dll. These files are found in the “KSP_Install\KSP_x64_Data\Managed”. Then at the top, add a line below “using System;” that says “using UnityEngine”. Our blank project is now ready to go and we can start coding. To test, copy-paste the following code into your program: using System; using UnityEngine; namespace HelloWorld { [KSPAddon(KSPAddon.Startup.MainMenu, false)] public class Hello : MonoBehaviour { public void Update() { Debug.Log("Hello world! " + Time.realtimeSinceStartup); } } } then compile your .dll file and place it in the KSP_Install\GameData folder. It can be in a sub-folder, typically you will make a sub-folder for your mod in order for the players to keep things straight. When you start KSP and reach the main menu, if everything is setup correctly, the code above will spam "Hello world!" to the console which is toggled on with Alt-F12. It will also append the time since the game was started so you can see the lines of text change. 2) Basic hooks In order to actually do anything, we need to hook into KSP so that our code will run. There are 4 ways to do this, which one you use will depend on what purpose your code has. Note that using multiple methods for different pieces of code is a valid approach. KSPAddon The KSPAddon hook is used when you want to run some code that is attached to a specific scene. Use this when you code runs and affect the Flight scene, the Tracking Station scene, the Editor scene, and so on. KSP will automatically create an instance of a class tagged this way at the start of the scene and destroy it at the end of the scene. Note: There is no integrated save/loading of data in the KSPAddon hook, you must do that manually. Use cases: Permanent changes to how the scene works, either the game-space itself or the UI. As there is no save/loading of data, the changes need to be the same every time. KSPAddon(Scene,Dont_Destroy) Scene: The Scene enumerator, in which scene does an instance of this class get loaded. This takes values from the KSPAddon.Startup enum and multiple values to start in multiple scenes can be selected. Dont_Destroy: Don’t destroy the class when the scene ends. Highly recommended to leave false until you understand how Unity creates/destorys objects in and across different scenes. Is a boolean value. [KSPAddon(KSPAddon.Startup.Flight, false)] public class MyKSPAddon : MonoBehavior { //your code here. } This will tell KSP to spawn an instance of MyKSPAddon when the Flight scene starts and destroy it when the Flight scene ends. It is high recommended that the class inherit from MonoBehavior (or other class that inherits from MonoBehavior) so that the Common Methods are available to you. ScenarioModule The Scenario Module is used for when a mod needs to affect a large part of the game and provides the ability to Save/Load data. One caveat is that different scenes have different objects so make sure to check what scene you are in before referencing objects that exist in multiple scenes. ScenarioModule(ScenarioCreatingOptions, Gamescene) ScenarioCreationOptions: What type of games do we add this to? Take from the ScenarioCreateOptions enum. GameScene: The Scene enumerator, in which scene does an instance of this class get loaded? Takes from the GameScenes enum. [KSPScenario(ScenarioCreationOptions.AddToNewCareerGames | ScenarioCreationOptions.AddToExistingCareerGames, GameScenes.SPACECENTER)] class MyScenario : ScenarioModule { //your code here } This will add you ScenarioModule to all games in career mode and create an instance of this class in the Space Center scene. Note that it must inherit ScenarioModule. VesselModule An single instance of a VesselModule is automatically added to every vessel that exists (can be switched to in the tracking station). Note that VesselModule's will still execute for unloaded vessels which PartModules will not. public class MyVesselModule : VesselModule { //your code here. } A VesselModule must inherit from VesselModule and no Attribute is required on the preceding line. Note that while a VesselModule does save/load data it does not have any provision for transfer of data between two VesselModules, such as when two vessels dock and combine, or an undock happens and a single vessel becomes two. PartModule A PartModule is a class that gets attached to a part. This is done through the use of ModuleManager (another mod) and scripts that control which parts your PartModule gets attached to. These scripts are very flexible and you can attach only to your desired parts and attach multiple instance of your PartModule if you desire. Module Manager download, and instructions on how to use, can be found here. public class MyPartModule : PartModule { //your code here. } A PartModule must inherit from PartModule. 3) Common Methods There are several common methods inside these 4 hooks that KSP will automatically execute for you. (This section assumes KSPAddon inherits from MonoBehavior.) public void Awake() { } KSPAddon, ScenarioModule, VesselModule, PartModule Called once and runs when an instance of the class is first created. Not recommended in most cases as it may not run when you expect as this is not tied to a scene. Not recommended at all in PartModule as KSP uses Awake() in a PartModule for its own purposes. public void Start() { } KSPAddon, ScenarioModule, VesselModule, PartModule Called once and is where any setup or “on-spawn” code should go. This method runs when your class spawns into the correct scene and runs before all other methods (except Awake()). Note that all Start() methods that need to run in a scene run sequentially, if you are trying to reference another object it may not exist yet and could require using a Coroutine to delay running some of your code. public void Update() { } KSPAddon, ScenarioModule, VesselModule, PartModule Called every update frame and is in sync with the actual frame that gets drawn on the monitor. If KSP is running at 60fps, this method will get called 60 times a second, once for each frame on the monitor. Anything code relating to the UI or the player interacts with should go here. public void FixedUpdate() { } KSPAddon, ScenarioModule, VesselModule, PartModule Called every physics frame and anything physics or game related should happen here. Caution: Update and FixedUpdate are NOT synchronized. Depending on current frame rates and demand on the CPU, multiple (or no) Update frames could happen between two FixedUpdate frames, or multiple (or no) FixedUpdate frames could happen between two Update frames. public void OnDisable() { } KSPAddon, ScenarioModule, VesselModule, PartModule Runs when the class is destroyed. Important for unsubscribing from GameEvents and destroying Toolbar buttons. Public void OnSave(ConfigNode node) { } ScenarioModule, VesselModule, PartModule Run when a game save happens. You can add your data to the node object in order to load it later. Note that any KSPFields are automatically save/loaded and do not require using this method. public void OnLoad(ConfigNode node) { } ScenarioModule, VesselModule, PartModule Run when a game load happens. Any data added to the node object in the OnSave method will be available in the node object passed by KSP to this method. Note that any KSPFields are automatically save/loaded and do not require using this method. 4) Common Properties/Objects FlightGlobals.ActiveVessel (Flight): A static that is the vessel that currently has focus. Vessel.Parts (Flight): A list of Parts on the vessel. EditorLogic.sortedShipList (Editor): A list of parts placed in the Editor. Part.Modules (Editor/Flight): A list of PartModules attached to this part. PartModule.vessel(Flight): The vessel containing the part this partModule is attached to. This is different than FlightGlobals.ActiveVessel KSPField Attribute. Tag an object with this inside a PartModule, VesselModule, or ScenarioModule and KSP will automatically save and load it for you. Note that only data types of string, bool, int, float, Vector2, Vector3, Vector4 or Quaternion can be tagged this way. Notably this means that the double data type can not be a KSPField. [KSPField(isPersistant = true, guiActive = false)] public bool savedBoolean; This will cause KSP to automatically save/load whether savedBoolean is true or false and it will not be visible in the GUI. If you set one of the GUI booleans to true, the KSPField will show in that part's right click menu (when in a partModule) so the player can edit the value in-game. KSPEvent Attribute: Only available in a PartModule, this causes a button to show in a Part's right-click menu in editor and flight mode to execute the attached code. [KSPEvent(guiName ="MyEvent")] public void MyEvent() { //code to run on player clicking button in part right-click menu } The guiName variable is the text that will be visible to the player in-game. There are several other values that can be set as well to control visibility of the Event, but there are too many to list here so check the Object Viewer in your IDE for them all. KSPAction Attribute: Only available in a PartModule, this adds an action to the action group list for a part in the editor so the player can add it to an action group. [KSPAction("MyAction")] public void myAction(KSPActionParam param) { //code to run when the player presses the action group key. } The "MyAction" text is what will show in game as the action name. KSPActionParam param is just a fancy boolean passed to the method to indicate if the action group is being activated or deactivated. 5) On-Screen GUI Legacy GUI system (Obsolete). Before KSP 1.0/1.1, what is now referred to at the LegacyGUI system was used. This method used the OnGUI() method to draw 2D UI objects on the screen. It is recommended that you not use this system any more and use the current UI Canvas system. UI Canvas system (Current). Please see this guide: http://forum.kerbalspaceprogram.com/index.php?/topic/151354-unity-ui-creation-tutorial/ UI creation is a complex beast with 3 different ways of doing it and the link covers how to work with it. 6) Toolbar button. Squad has a write-up of how to make a button on the stock toolbar here: http://forum.kerbalspaceprogram.com/index.php?/topic/78231-application-launcher-and-mods/ Blizzy's toolbar is also popular and instructions for using it can be found here: http://forum.kerbalspaceprogram.com/index.php?/topic/54734-120-toolbar-1713-common-api-for-draggableresizable-buttons-toolbar/ 7) GameEvents system. The GameEvents system is how you trigger parts of your code to run when events in the game happen. All the available GameEvents in the stock game can be found in the GameEvents class in the object browser. public void Start() { GameEvents.onPartDie.Add(PartDead); } public void PartDead(Part p) { //add code here to run when a part dies. //Note that this event fires every time a part dies. //You will have to check Part p to see which part died, it is not necessarily the part this piece of code is attached to. } public void OnDisable() { GameEvents.onPartDie.Remove(PartDead); } Here we subscribe to the GameEvent so that the PartDead method will run anytime a part is destroyed. Note this will run anytime a part dies, so in a big crash this method will run many times, once for each part that dies. Note that we unsubscribe in the OnDisable method. This is very important as if you forget this step you will cause Null-Ref errors as anytime a part dies, KSP will still try to call your PartDead method even though it no longer exists. As of KSP 1.2.2, mods can now trigger game events that other mods can subscribe to for inter-mod communication. Further details on this can be found here: http://forum.kerbalspaceprogram.com/index.php?/topic/153112-ksp-122-gameevents-extension/ 8) ConfigNode overview. KSP uses ConfigNodes to save/load data. A configNode has the following structure: NODE { key1 = value1 key2 = value2 SUBNODE1 { key3 = value3 key4 = value4 } } The only valid data type in a ConfigNode is string and is made up of Nodes and Key/Value pairs. The following code makes the above node layout: ConfigNode myNode = new ConfigNode("NODE"); myNode.AddValue("key1","value1") myNode.AddValue("key2","value2") ConfigNode mySubNode1 = new ConfigNode("SUBNODE1") myNode.AddNode(mySubNode1); mySubNode1.AddValue("key3","value3") mySubNode1.AddValue("key3","value3") Then to retrieve values, the following code extracts them from the node: ConfigNode myNode = //load ConfigNode here, see section 9, Save/Load data. string myValue1 = myNode.GetValue("key1"); string myValue2 = myNode.GetValue("key2"); ConfigNode mySubNode1 = myNode.GetNode("SUBNODE1"); string myValue3 = mySubNode1.GetValue("key3"); string myValue4 = mySubNode1.GetValue("key4"); Note that ConfigNodes are very dumb. If you GetValue('Key5") when Key5 doesn't exist, KSP throws a Null Reference Exception and stop running your code. If you AddValue("Key1","Value1") when the node already has a Key1 present it will add a second Key1 value to the node instead of updating the existing value. You can SetValue("Key1","Value1") instead to update an existing Key1 value, but if Key1 doesn't exist, it will Null Reference and stop running your code. When working with ConfigNodes, you can use the "Debug.Log(MyConfigNode.ToString()); command to print the contents of the entire ConfigNode to the log. 9) Save/Load data. The simplest way to save/load data is to use the KSPField attribute as listed in the Common Properties/Objects section and let KSP do all the work for you. If you needs are more complex you can use the OnSave/OnLoad methods to save to the confignode, or you can directly save to a file on disk. OnSave/OnLoad methods: Public void OnSave(ConfigNode node) { node.AddValue("myValue","Hello World!") } Public void OnLoad(ConfigNode node) { string myValue2 = node.GetValue("myValue"); } This will save a key/value pair with a key name of myValue with a value of Hello World! and then when the load happens, myValue2 will have a value of Hello World loaded into it. See the ConfigNode section for working with ConfigNodes. Save/Load directly to disk: ConfigNode myNode = ConfigNode.Load(KSPUtil.ApplicationRootPath + "GameData/MyModFolder/MyMod.settings"); //Loads a file from disk into a ConfigNode for use in code. ConfigNode myNode.Save(KSPUtil.ApplicationRootPath + "GameData/MyModFolder/MyMod.settings"); //Saves a confignode to disk. This will save/load to the MyMod.settings file in the MyModFolder. The file structure is a ConfigNode so see that section on working with them. And those are the absolute basics of how to start modding for KSP. If you spot any discrepancies or basics that were missed that should be mentioned please let me know. Apr 12/17: Update VesselModules now run on unloaded vessels. (New in KSP 1.2) Edited April 12, 2017 by Diazo Quote Link to comment Share on other sites More sharing options...
Aghanim Posted January 7, 2017 Share Posted January 7, 2017 On 12/20/2016 at 11:49 AM, Diazo said: When you start KSP and reach the main menu, if everything is setup correctly, the code above will spam "Hello world!" to the console which is toggled on with Alt-F12. It will also append the time since the game was started so you can see the lines of text change. This is slightly misleading, because 9 minutes ago, nightingale said: @Aghanim - This line: [KSPAddon(KSPAddon.Startup.Flight, false)] Means that your addon will be started in the flight scene. You'll see your log spam if you launch a vessel. and that will probably leads people (like me) thinking that there might be something wrong with their code or setup because they checked the console at main menu and nothing happens, when in fact the plugin is fine, it just fires at flight scene not at main menu Quote Link to comment Share on other sites More sharing options...
Diazo Posted January 7, 2017 Author Share Posted January 7, 2017 Thanks for catching that, fixed. One of these days I'll stop making copy-paste errors. I grabbed some of my own code that runs in the flight scene for an example and that slipped through. D. Quote Link to comment Share on other sites More sharing options...
gomker Posted January 10, 2017 Share Posted January 10, 2017 Nice overview You mentioned KSPFields with VesselModules, from what I have read they do not save any data, something worth mentioning (unless something changed recently) Part Module: One set of modules per part. Number of modules for a part is set in part configuration file. Active during initial loading (do try not to...), editor, and flight scenes. Save persistence of variables using the KSPField attribute with the option isPersistant set true KSP Addon: Single instance. Only one instance of the plugin object running, limited to either a single scene or all scenes Scenario Module: Single instance per save, used for storing/retrieving persistent data that isn't associated with a part (? I haven't used this one so I don't know much about it) Vessel Module: One instance per physics enabled vessel object. Only active in the flight scene. No direct access to the persistence file. Quote Link to comment Share on other sites More sharing options...
Diazo Posted January 10, 2017 Author Share Posted January 10, 2017 @gomker The linked thread is from when VesselModules were originally implemented in KSP 1.0 and at the time they did not save data. In KSP 1.1 (or 1.1.1?) VesselModules gained the ability to save/load data via the standard OnSave()/OnLoad() methods that PartModules have. I'm pretty sure this included the KSPField for save/loading data from what I recall at that time but I will admit I didn't actually that feature when I was writing the guide. I'll look into that in the next few days here. D. Quote Link to comment Share on other sites More sharing options...
sarbian Posted January 10, 2017 Share Posted January 10, 2017 (edited) 7 hours ago, gomker said: Vessel Module: One instance per physics enabled vessel object. Only active in the flight scene. No direct access to the persistence file. Err, Load and Save calls were added in 1.2 so that s no longer the case. Edit : and I should learn to read replies Edited January 10, 2017 by sarbian Quote Link to comment Share on other sites More sharing options...
Rodhern Posted June 26, 2017 Share Posted June 26, 2017 On 12/20/2016 at 5:49 AM, Diazo said: KSPAddon ... the KSPAddon.Startup enum and multiple values to start in multiple scenes can be selected. The scenes have ordinal values like Editor= 6, Flight= 7, TrackingStation= 8, and so on. There are also some predefined combinations like FlightAndEditor= -4. Is there a way to select multiple values other than picking one of the predefined combinations ? Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted June 26, 2017 Share Posted June 26, 2017 13 minutes ago, Rodhern said: The scenes have ordinal values like Editor= 6, Flight= 7, TrackingStation= 8, and so on. There are also some predefined combinations like FlightAndEditor= -4. Is there a way to select multiple values other than picking one of the predefined combinations ? No; the pattern I've seen for multiple scenes is to inherit several scene-specific classes from your main plugin class, one per attribute. https://github.com/TriggerAu/TransferWindowPlanner/blob/master/TransferWindowPlanner/TWP.cs#L16-L25 Quote Link to comment Share on other sites More sharing options...
Brendan_ Posted August 31, 2017 Share Posted August 31, 2017 On 12/19/2016 at 10:49 PM, Diazo said: These files are found in the “KSP_Install\KSP_x64_Data\Managed”. I am brand new and confused to modding! Also to C#, and Visual Studio, and actually programming. I'm basically insane. But I did want to share that in my install, KSP 1.3.0 Linux (Lubuntu 16.04, if it matters) installed through Steam, the files are in "Kerbal Space Program/Launcher_Data/Managed". There is no "KSP_Install\KSP_x64_Data\Managed" as there's only a "Mono" dir in my "KSP_x64_Data". As the OP was last edited 8/9 months ago, I'm presuming this is more a version update thing than a Linux/Windows thing, but I wouldn't know. Potentially this will help someone though! Quote Link to comment Share on other sites More sharing options...
bananasrawesome Posted September 2, 2017 Share Posted September 2, 2017 (edited) What are the things in the "[ ]" called? Edited September 2, 2017 by bananasrawesome Quote Link to comment Share on other sites More sharing options...
TheRagingIrishman Posted September 2, 2017 Share Posted September 2, 2017 1 hour ago, bananasrawesome said: What are the things in the "[ ]" called? Attributes Quote Link to comment Share on other sites More sharing options...
bananasrawesome Posted September 2, 2017 Share Posted September 2, 2017 @TheRagingIrishman Thanks Quote Link to comment Share on other sites More sharing options...
Benjamin Kerman Posted September 3, 2017 Share Posted September 3, 2017 (edited) 20 hours ago, TheRagingIrishman said: Attributes I know you use them in KSPFields, but what else are they used for? Edit: For anyone wondering, https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx Edited September 3, 2017 by Benjamin Kerman Quote Link to comment Share on other sites More sharing options...
Rodhern Posted September 3, 2017 Share Posted September 3, 2017 28 minutes ago, Benjamin Kerman said: I know you use them in KSPFields, but what else are they used for? Attributes are more or less used to give KSP information about your mod (dotnet classes). One that is often used is KSPAddon, e.g. [ KSPAddon (KSPAddon.Startup.TrackingStation, false) ] that way KSP knows that you want that class 'created'/'loaded'/'started' every time the player goes to the tracking station, and that the class can 'unload' when the player exits the tracking station. The attributes are discovered by KSP/Unity/Mono by something called "reflection". Something about Unity can make it quite a bit more confusing than it ought to be. Some classes are found by reflection due to their inheritance, some methods are identified by reflection due to the name, and some are found by reflection due to their attributes (e.g. KSPField and KSPAddon). Look at the first few posts of this thread - there are good explanations there. Quote Link to comment Share on other sites More sharing options...
Benjamin Kerman Posted September 3, 2017 Share Posted September 3, 2017 So they take the form of enums? Quote Link to comment Share on other sites More sharing options...
Rodhern Posted September 3, 2017 Share Posted September 3, 2017 2 minutes ago, Benjamin Kerman said: So they take the form of enums? Are you asking about attributes? Attributes inherit from System.Attribute (as described in the link you gave above), and are just classes. The difference is that they are often used in a bit of a different way from other classes. Quote Link to comment Share on other sites More sharing options...
c4ooo Posted July 18, 2018 Share Posted July 18, 2018 I dont quite understand how to write an addon that gets created once and then persists through the entire game. I have tried "[KSPAddon(KSPAddon.Startup.MainMenu, true)]", which, as far as i understand should be started once the main menu loads and never be destroyed. However it gets destroyed once the scene changes (eg i load a save). Quote Link to comment Share on other sites More sharing options...
DMagic Posted July 18, 2018 Share Posted July 18, 2018 @c4ooo You have to specifically tell it not to be destroyed. private void Awake() { DontDestroyOnLoad(gameObject); } Put that in the MonoBehaviour you are creating and it won't be destroyed unless you do it manually. Quote Link to comment Share on other sites More sharing options...
c4ooo Posted July 18, 2018 Share Posted July 18, 2018 2 hours ago, DMagic said: @c4ooo You have to specifically tell it not to be destroyed. private void Awake() { DontDestroyOnLoad(gameObject); } Put that in the MonoBehaviour you are creating and it won't be destroyed unless you do it manually. Thanks, that seemed to have worked Should i leave the Dont_Destroy boolean true or false? Quote Link to comment Share on other sites More sharing options...
toric5 Posted July 31, 2019 Share Posted July 31, 2019 in https://wiki.kerbalspaceprogram.com/wiki/Tutorial:Creating_your_first_module , It says: Verify your project targets .NET 3.5 - many newer compilers and IDEs target 4.0. (Not relevant for newer KSP; 1.4.x uses Unity 2017 with .NET 4.5). Should I be targeting 3.5 or 4.5 for ksp 1.7.3? Ive tried both, but neither run... Quote Link to comment Share on other sites More sharing options...
Tonka Crash Posted July 31, 2019 Share Posted July 31, 2019 1 hour ago, toric5 said: Should I be targeting 3.5 or 4.5 for ksp 1.7.3? Ive tried both, but neither run... It's still 3.5. Anything newer will throw errors in the log even it it seems to run fine. Quote Link to comment Share on other sites More sharing options...
sarbian Posted August 2, 2019 Share Posted August 2, 2019 On 7/31/2019 at 7:17 PM, toric5 said: (Not relevant for newer KSP; 1.4.x uses Unity 2017 with .NET 4.5). It does not. Whoever added that to the wiki is wrong. Quote Link to comment Share on other sites More sharing options...
AndrewCoja Posted October 21, 2019 Share Posted October 21, 2019 Is this guide still the way to do it? I'm trying to get into modding KSP, but every guide seems to be from 2013. Following what is in the first post here, I set up visual studio and have added the references mentioned. But when I paste in the first example, Visual Studio says that it doesn't know what MonoBehaviour or Debug.Log is. Quote Link to comment Share on other sites More sharing options...
Grigetio Posted October 21, 2019 Share Posted October 21, 2019 (edited) You probably need to download mono. Having said that, what you really want is Unity (and the proper version) https://unity3d.com/unity/whats-new/2019.2.2 Edit: the Unity install installs Unity tools for VS, which is what you want and need. You will still develop in VS, but unity install will give you the proper dev environment. See these two threads: Edited October 21, 2019 by Grigetio clarification Quote Link to comment Share on other sites More sharing options...
AndrewCoja Posted October 21, 2019 Share Posted October 21, 2019 Ah cool thanks. Looks like it is compiling now and I'm back on track. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.