Search the Community
Showing results for tags 'code'.
-
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)
- 34 replies
-
- 30
-
So there is bugs, yea we expected some. but looking at the most common bugs raises concerns that they need to go "back to formula" see what outers think is simply a annoyance bug points to much larger issues. and there are a few "gotcha's" First off is simply user interface, how key and button input is handled. but also how it is processed. an example is when writing a ship's name, M key takes you to a map view. this shows inputs are global instead of mode specific and/or the mode swapping is not handled properly. then there is the lack of response from interface when crafts of extreme loads are being launched, lets say you get time to pass once every 10 seconds, pressing esc you wait up to 10 seconds to see map. this is first a ticking issue, shows the menu is not calculated independently and have to wait for the world render cycle to complete before it is acted upon. the menu us a slave function to rendering. this should not be so. next there is time itself. time should pass once every second, no lag or load should reduce that. any function should be a slave of time and use "time passed since last action" as part of its calculations. instead of relying on each action's output to calculate the next, formula's should allow passing of any amount of time and be able to adapt to those. an example is rotating to a position over time, instead of needing to take action at every passing unit of time, a simple formula can be used to see how far it would be towards its goal giving this amount of time passed. so if a craft would need 8 seconds to rotate from prograde to retro, and you are on 10x speed, then simply assume that in the passing of 10 seconds it made the rotation and set it as such, and deduct the propellant it would have used for that. simple this will fix rotation and acceleration not functioning over time warp of any kind. then as for physics, this should be simplified where you can pre-calculate it take the assembled craft in its current state, then do a linetrace from it from every direction, get the relevant angle of the hit and assign a value to it. do an additive overlay for control surfaces and other moving parts. now simplify it into center of drag, and center of mass use this along with speed to calculate everything else needed, bit you now get to treat it as a single part and not 100's of parts, and only needs to recalculate if the assembly changes. you can further pre-calculate each part and in the final calculation use those as an is visible basis. you're welcome. the current setup looks to prioritize visual priority of execution should be: 1 - time 2 - interface input and response 3 - control input and response 4 - vehicle movement 5 - actual rendering, here going LOD or even complete basic Low poly will be acceptable as long as time keeps passing, input responding and actions happening reliably. next assembly again looks like rendering is prioritized. it looks like everything is as movable and lighting is dynamic, this is wrong and even bad for performance. treat every placed object as static, use directional light and pre-bake light as much as possible, then calculate dynamic shadows for the single combined model. also VAB should have better uniform lighting with less shadows, it's a rocket factory after all so can assume its getting at least 4x light from each side and from on top, this makes baking light easier. as for placement sockets, sure snapping to anything is a function now, but how about if we mid-mouse-button select something to then prioritize snapping to the object that we are focusing our view on? also you dont have to make an entire assembly as moveable to attach it, simply rendering a 2d version of it for the current view and using a depth offset, use that as a card for the moveable part, and hide the static once you render the card, then you dont even need movables. there is also collision issues with many parts, the simple solution is to do a visual interrace and get tangent at location, use that instead of collision, so a surface mount item will mount to the visual outer surface. these are just a few bug fixes and performance booster i would have looked at. again this is speculative and only the opinion of a play test, and I have no actual knowledge of how the code actually functions
-
First for those who have remembered my old threads on coding I have decided to bite the proverbial bullet and learn python soon. I wanted to ask a few questions. First I have been informed by a mostly reliable source that Python can interface with hardware such as motors and electric "stuff" in general. This is true right? Secondly I have no intention of doing this anytime in the next year but is Python capable of making an AI of sorts. I ask all of this because I want to make a model rocket that has a full guidance system as well as staging system ect and I want to make sure before I put a bunch of time into learning this code that is it worth my time and is what Im looking for. Is this true? Finally are they any pointers that people can suggest to learning this language if it is really what im looking for.
-
A while back I asked a question on how to make your own code in this forum. After lengthy conversations I came to the conclusion that it was not wise to bother trying. Now I pose this question as follow up. When computers were first invented how exactly did they manage to code them. I ask this because when I asked the question of making your own code I was given answers that seemed that they all required a base code to work with in the first place. Then the question is raised assuming that this is the case, how was that code formed. I'm asking fundamentally how software works and went from a circuit into something you can code with using a screen.
-
Is it possible to add kOS syntax highlighting to the "insert code" function in the forum post editor? If it is possible, how do we make it happen?
-
Hi all, I'dd like to setup an action on each new year, the 1st of January. I've never moded KSP before, but have knowledge in C# and Unity. I have not found any pre-existing events, but suppose I could use the 'GameEvents Extension' (below link) to create such an event. Could someone point me in the right direction on how one would setup such an event? Thanks!
-
Situation: New Science game. First Command Pod sitting on launch pad with a custom ModuleScienceContainer. This Event is active: [KSPEvent(active = true, guiActive = true, guiName = "Review Custom ScienceData")] public void ShowCustomDataEvent() { print("[SensibleScience] ModuleSensibleScienceContainer :: ShowCustomDataEvent"); var data = new ScienceData(30f, 1f, 0f, "surfaceSample@KerbinSrfLandedLaunchPad", "Random Data"); var page = new ExperimentResultDialogPage(part, data, data.baseTransmitValue, data.transmitBonus, false, "", true, new ScienceLabSearch(vessel, data), new Callback<ScienceData>(onDiscardData), new Callback<ScienceData>(onKeepData), new Callback<ScienceData>(onTransmitData), new Callback<ScienceData>(onSendToLab)); ExperimentsResultDialog.DisplayResult(page); } If I click on the event with no other interaction, I get an ExperimentsResultDialog with the specified 30 Mits but no science value. However, if I EVA my kerbal, grab a surface sample and dump/reset it, then re-board my pod and click on the event the ExperimentsResultDialog now shows the expected science (and FULL xmit value, as defined). Does KSP track activated experiments/situations? If so, what calls do I need to make to activate specific experiment or subject IDs?
-
private void ResetExperimentGUI() { //print("Resetting GUI..."); if (SkinStored != null) { SkinStored.box.normal = StyleDefault; SkinStored.box.normal.background = GameDatabase.Instance.GetTexture("CactEye/Icons/ExperimentGUIBackground", false); SkinStored.box.fixedWidth = 0f; SkinStored.box.fixedHeight = 0f; SkinStored.window.fixedWidth = 400f; } else { Debug.Log("CactEye 2: Logical Error 3: SkinStored is null!"); } ScienceStyle.fixedHeight = 0f; ScienceStyle.fixedWidth = 0f; } #endregion } } Can someone tell me what's wrong here?
-
How to get access to KSP Physics configuration settings by code?
- 2 replies
-
- physics
- configuration
-
(and 1 more)
Tagged with:
-
Currently Kerbal Konstructs can modify the home planet Kerbin and place any structures around the planet. The author coudn't find any programming way to do the same with other planets. Plus noone could find a way to place custom anomalies (easter eggs) as well. To make this possible we need a coding support from SQUAD.