Agathorn Posted July 24, 2014 Share Posted July 24, 2014 How can I put variables in the partmodule in the .cfg file and then read them in the plugin partmodule?If all you need is simple types, like string, or float, then you can just make them KSPFields. If you need to go more indepth, you need to use custom classes that implement IConfigNode. You can see my adventures learning this here:http://forum.kerbalspaceprogram.com/threads/86815-Unable-to-read-part-cfg-data-when-part-is-added-to-vessel Quote Link to comment Share on other sites More sharing options...
Agathorn Posted July 24, 2014 Share Posted July 24, 2014 How would I go about getting the mission elapsed time (MET) in a PartModule's OnUpdate?Looks like the answer is FlightLogger.met Quote Link to comment Share on other sites More sharing options...
NathanKell Posted July 24, 2014 Share Posted July 24, 2014 String or float, yes. Double, no. KSPField is *weird* Quote Link to comment Share on other sites More sharing options...
Agathorn Posted July 24, 2014 Share Posted July 24, 2014 You will want to look at this post from Mu about the introduction of PartModule, ConfigNode, KSPField, etc.. basically all the things you want to do. That said be aware that the developers examples do not work! LOL I know it sucks but its still good reference for 90% of it then you have to fight the rest of the way. But between this post and the one I linked earlier, all the information should be there.http://forum.kerbalspaceprogram.com/threads/7529-Plugin-Posting-Rules-And-Official-Documentation?p=156430&viewfull=1#post156430 Quote Link to comment Share on other sites More sharing options...
Malkanor Posted July 24, 2014 Share Posted July 24, 2014 No clue if this is the correct place to post about this, but...I've been looking for projects to work on, and am willing to help anyone with developing a plugin for their mod! Whether you want help on the workload, or aren't programming savvy... I'm just looking for things to work on xP Quote Link to comment Share on other sites More sharing options...
catgirltech Posted July 25, 2014 Share Posted July 25, 2014 hi. i'm working on a resource manager module. is there a way to add a resource display to the part's guiActive bubble? i have the module setup so you can add parts from the vessel to a list and select which resource types you want to manage. i want to have it display the resources it manages. (ideally i want to have it do resource transfers like any other two parts. but one step at a time.) Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 27, 2014 Share Posted July 27, 2014 Hi people, I'm trying to write a plugin that will perform some kind of action when a bool "lifespecimensFound" is true. I want the bool to have just a small chance of returning true each time the player lands the vessel, so I created a keyvaluepair list. Here it is:void Update(){List<KeyValuePair<bool, double>> lifespecimensList = new List<KeyValuePair<bool, double>>(); lifespecimensList.Add(new KeyValuePair<bool, double>(true, 0.1)); lifespecimensList.Add(new KeyValuePair<bool, double>(false, 0.9)); System.Random r = new System.Random(); double lifespecimensChance = r.NextDouble(); double cumulative = 0.0; for (int i = 0; i < lifespecimensList.Count; i++) { cumulative += lifespecimensList[i].Value; if (lifespecimensChance < cumulative) { lifespecimensFound = lifespecimensList[i].Key; break; } } if(newlandsite) { if(lifespecimensFound) { lifespecimensStatus = "Life Detected!"; } else { lifespecimensStatus = "No Life Detected."; } } else { unitStatus = "Must land at new site!"; }}However, as it in void Update(), the bool is constantly returning new values, but I want it to only return once (when a button is pressed via a KSPEvent, for example). But for some reason, when I try to do this, it returns no value at all. I'm really stumped. Thanks in advance for any advice! Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 27, 2014 Share Posted July 27, 2014 That sounds like how you are trying to tie it to the KSPEvent is the issue, not the code itself.How are you going about that?D. Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 27, 2014 Share Posted July 27, 2014 Well I tried a couple of things. One way I tried was like this:if(testing && statusInt == 0){ List<KeyValuePair<bool, double>> lifespecimensList = new List<KeyValuePair<bool, double>>(); lifespecimensList.Add(new KeyValuePair<bool, double>(true, 0.1)); lifespecimensList.Add(new KeyValuePair<bool, double>(false, 0.9)); System.Random r = new System.Random(); double lifespecimensChance = r.NextDouble(); double cumulative = 0.0; for (int i = 0; i < lifespecimensList.Count; i++) { cumulative += lifespecimensList[i].Value; if (lifespecimensChance < cumulative) { lifespecimensFound = lifespecimensList[i].Key; break; } } if(newlandsite) { if(lifespecimensFound) { lifespecimensStatus = "Life Detected!"; statusInt = 2; } else { lifespecimensStatus = "No Life Detected."; statusInt = 1; } } else { unitStatus = "Must land at new site!"; statusInt = 0;}With these KSPFields and KSPEvent so that it knows which value of the lifespecimensStatus string is returned and so in theory doesn't repeat the action but again, it doesn't do anything:[KSPField(guiActive = false, isPersistant = true)]public int statusInt = 0;[KSPField(guiActive = false, isPersistant = true)]public bool testing = false;[KSPEvent(guiActive = true, guiName = "", active = true)]public void Activate(){Events["Activate"].active = false;Events["Deactivate"].active = true;testing = true;} Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 28, 2014 Share Posted July 28, 2014 Nor would it work with a simpler code with the list in another bool I made: "unitActive" I'll just give all the code in case I've done something stupid somewhere else in the code.using UnityEngine;using System;using System.Collections.Generic;namespace RUILifeTech005{ public class RUILifeTech005 : PartModule { [KSPField(guiActive = false, isPersistant = true)] public bool newlandsite; [KSPField(guiActive = false, isPersistant = true)] public bool lifespecimensFound; [KSPField(guiActive = false, isPersistant = true)] public bool unitActive = false; [KSPField(guiActive = true, guiName = "", isPersistant = true)] public string lifespecimensStatus; [KSPField(guiActive = true, guiName = "", isPersistant = true)] public string unitStatus; [KSPEvent(guiActive = true, guiName = "", active = true)] public void Activate() { Events["Activate"].active = false; Events["Deactivate"].active = true; unitActive = true; } void Update() { switch(this.vessel.checkLanded()) { case true : newlandsite = true; break; case false : newlandsite = false; break; } if(unitActive) { List<KeyValuePair<bool, double>> lifespecimensList = new List<KeyValuePair<bool, double>>(); lifespecimensList.Add(new KeyValuePair<bool, double>(true, 0.1)); lifespecimensList.Add(new KeyValuePair<bool, double>(false, 0.9)); System.Random r = new System.Random(); double lifespecimensChance = r.NextDouble(); double cumulative = 0.0; for (int i = 0; i < lifespecimensList.Count; i++) { cumulative += lifespecimensList[i].Value; if (lifespecimensChance < cumulative) { lifespecimensFound = lifespecimensList[i].Key; break; } } if(newlandsite) { if(lifespecimensFound) { lifespecimensStatus = "Life Detected!"; } else { lifespecimensStatus = "No Life Detected."; } } else { unitStatus = "Must land at new site!"; } } } }} Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 28, 2014 Share Posted July 28, 2014 Not sure what the problem was, but I think I've fixed it. Thanks anyway. Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 28, 2014 Share Posted July 28, 2014 Does anyone know how I would go about defining a science experiment via a plugin. I know that usually, one would use a science cfg file but I was wondering if I'd be able to do the same thing via a KSPEvent button in a plugin? Quote Link to comment Share on other sites More sharing options...
Crabsticks Posted July 28, 2014 Share Posted July 28, 2014 Hi.I'm trying to use triggers in my mod/plugin to detect the parts of a vessel, or even just the vessel, as they move through an area. I've set up the collider I'm using as istriggered and set up my OnTriggerEnter(Collider). Unfortunately it only seems to recognize a few cetain parts (RCS blocks, landing legs and EVAkerbals) but nothing much else. Anyone know how to solve this? I've attempted adding rigidbodies and colliders to all loaded parts in the area but this has had limited success and I have no idea how to set these up so that they don't mess up the physics of the part/vessel, but still get recognized by the trigger.If I can't get this to work I'll give up trying to use triggers and use a calulation based on the position vector of the parts and vessels.I'd appreciate any help or suggestions,Thanks. Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 29, 2014 Share Posted July 29, 2014 Hi, can anyone help me with how to use Part.AddModule()? I'm trying to add a new ScienceExperiment module to a part on a KSPEvent button press. I tried this:Part.AddModule("lifetech", ModuleScienceExperiment);but it didn't work. The API I looked at says it should be Part.AddModule(string partModule) but not sure what I'm doing wrong. Any help? Thanks Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 29, 2014 Share Posted July 29, 2014 There is no comma in the addmodule, it is expecting a single variable of type string.So you want Part.addModule("lifetech");, with lifetech being a class defined as a partModule.D. Quote Link to comment Share on other sites More sharing options...
blizzy78 Posted July 29, 2014 Share Posted July 29, 2014 Part.AddModule("lifetech", ModuleScienceExperiment);A method with that signature does not exist. You either need to provide the part module name, or a config node that has it (along with other module parameters you want.) Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 30, 2014 Share Posted July 30, 2014 Okay, config nodes time.In a scenario module, I have the following:public override void OnSave(ConfigNode node) { if (HighLogic.LoadedSceneIsEditor) { if (!node.nodes.Contains("EDITOR")) { node.AddNode("EDITOR"); } AGXEditorNode = node.GetNode("EDITOR"); node.SetNode("EDITOR",EditorSave(AGXEditorNode)); }}and then EditorSave() is: public ConfigNode EditorSave(ConfigNode AGXEditorNode) { if (!AGXEditorNode.nodes.Contains(EditorLogic.fetch.shipNameField.Text)) { AGXEditorNode.AddNode(EditorLogic.fetch.shipNameField.Text); } ConfigNode thisVsl = new ConfigNode(); thisVsl.AddValue("AGXNames","namesTest"); thisVsl.AddValue("AGXKeySet", "KeysetTest"); foreach (Part p in EditorLogic.SortedShipList) { if(!thisVsl.HasNode(p.name.Remove(p.name.Length - 8))) { thisVsl.AddNode(p.name.Remove(p.name.Length - 8)); } ConfigNode partTemp = new ConfigNode(); partTemp.AddValue("relLoc",(p.transform.position-EditorLogic.startPod.transform.position).ToString()); thisVsl.SetNode(p.name.Remove(p.name.Length - 8), partTemp); } AGXEditorNode.SetNode(EditorLogic.fetch.shipNameField.Text, thisVsl); return AGXEditorNode; }and I expect the following (actual strings replaced with the calculation values from the previous code block):SCENARIO { name = AGextScenario scene = 7, 6, 9 EDITOR { EditorLogic.fetch.shipNameField.Text //new module, using the ship name { AGXNames = namesTest AGXKeySet = KeysetTest p.name.Remove(p.name.Length - 8) //new confignode level, partname (less the (CLONE) added in the editor) { relLoc = Vector3 numbers as string } //repeat for as many parts on the vessel } }Instead I get:SCENARIO { name = AGextScenario scene = 7, 6, 9 EDITOR { } }So the code in the actual OnSave method is running, but my call to EditorSave does not seem to process. There are no errors thrown to the log, can anyone point out to me what I am doing wrong? Can I not call ConfigNodes to other methods like this or something?D. Quote Link to comment Share on other sites More sharing options...
blizzy78 Posted July 30, 2014 Share Posted July 30, 2014 AGXEditorNode.AddNode(EditorLogic.fetch.shipNameField.Text);You need to be very careful when doing that. Config node names and key names do not allow all characters. You may instead want to go for this structure:EDITOR{ ship // fixed node name { name = <ship name> }}(Of course, the values also don't allow all characters, most notably '/'.)The same goes for your part sub-node's name. Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 30, 2014 Share Posted July 30, 2014 Bah, that is probably it.I was using the stock Kerbal 2 for tests and I'll bet you that space it in was the issue.Thanks for the assist.D. Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 30, 2014 Share Posted July 30, 2014 A method with that signature does not exist. You either need to provide the part module name, or a config node that has it (along with other module parameters you want.)Well, first I found it was in fact part rather than Part. So I now have this:public class RUILifeTech005 : PartModule{[KSPEvent(guiActive = true, guiName = "Activate", active = true)] public void Activate() { Events["Activate"].active = false; Events["Deactivate"].active = true; part.AddModule("lifetech"); }} So, then your saying I should make another class within the plugin like:public class lifetech : ModuleScienceExperiment{}So then I somehow need to define the experiment id, title, baseValue, etc? Any idea how I'd do that? I know it sounds kinda bad asking for code details but I've only made ScienceExperiment modules in a cfg file, which I don't want to do with this mod. Thanks. Quote Link to comment Share on other sites More sharing options...
Zyrac Posted July 30, 2014 Share Posted July 30, 2014 Or rather this?:public class lifetech : PartModule{}With ConfigNode.AddNode(); Something like that? Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 31, 2014 Share Posted July 31, 2014 (edited) Okay, I must be missing something fundamental to how confignodes are supposed to work.In my scenario module:public class AGextScenario : ScenarioModule //this runs on flight scene start { public ConfigNode AGXBaseNode = new ConfigNode(); //initialize the three configNodes I am using public ConfigNode AGXFlightNode = new ConfigNode(); public ConfigNode AGXEditorNode = new ConfigNode(); public void Start() { try { if(File.Exists(new DirectoryInfo(KSPUtil.ApplicationRootPath).FullName + "saves/" + HighLogic.SaveFolder + "/AGExt.cfg")) //does AGExt.cfg exist for this save game? It saves to the same folder as persistent.sfs { AGXBaseNode = ConfigNode.Load(new DirectoryInfo(KSPUtil.ApplicationRootPath).FullName + "saves/" + HighLogic.SaveFolder + "/AGExt.cfg"); //file exists, load it print("AGX ConfigNode Load Okay!"); } else { print("AGX ConfigNode not found, creating....."); AGXBaseNode.AddNode("FLIGHT"); AGXBaseNode.AddNode("EDITOR"); AGXBaseNode.Save(new DirectoryInfo(KSPUtil.ApplicationRootPath).FullName + "saves/" + HighLogic.SaveFolder + "/AGExt.cfg"); //file does not exist, create it with empty FLIGHT and EDITOR nodes } AGXFlightNode = AGXBaseNode.GetNode("FLIGHT"); //load FLIGHT and EDITOR nodes AGXEditorNode = AGXBaseNode.GetNode("EDITOR"); } catch (Exception e) { print("AGXScenStart Fail " + errLine + " " + e); } }This works. If AGExt.cfg does not exist in the save folder, it creates it with a FLIGHT and EDITOR node that are empty. It then loads the AGXFlightNode and AGXEditorNode configNodes from the file. (They will be empty nodes if I just created the AGExt.cfg file.)However, this appears to do nothing: (still in the scenario module)public override void OnSave(ConfigNode node) { print("AGXScenSaving"); //this prints to the log so the method excutes if (HighLogic.LoadedSceneIsEditor) //this code can only run in the editor, will be different for flight mode { try { string hashedShipName = EditorHashShipName(EditorLogic.fetch.shipNameField.Text); //as per my previous post, I hash the shipname to a string of numbers so I'm guaranteed to not have any illegal characters//I have a print() in the EditorHashShipName method that prints the number so I know this is working. if (!AGXEditorNode.nodes.Contains(hashedShipName)) { AGXEditorNode.AddNode(hashedShipName); //make the node for the vessel, using the hashed ship name as node name } ConfigNode thisVsl = new ConfigNode(); //new config node for the vessel thisVsl.AddValue("AGXNames", "namesTest"); //add my test values thisVsl.AddValue("AGXKeySet", "KeysetTest"); AGXEditorNode.SetNode(hashedShipName, thisVsl); //save vessel config node as sub-node of the EDITOR node AGXBaseNode.SetNode("EDITOR", AGXEditorNode); //save the modified EDITOR node to the root node of the AGExt.cfg file AGXBaseNode.Save(new DirectoryInfo(KSPUtil.ApplicationRootPath).FullName + "saves/" + HighLogic.SaveFolder + "/AGExt.cfg"); //the actual write command to the disk } catch (Exception e) { print("AGXScen EditorSave Error " + errLine + " " + e); } } }I am expecting this to add a sub-node in the EDITOR node in my AGExt.cfg file with a node name as a string of numbers and two test values, but it does nothing that I can see. Notably however, there are no errors in the log so I'm not sure where things are going wrong.I'm sure it is something simple, but where is my assumptions about how ConfigNodes work wrong? D. Edited July 31, 2014 by Diazo Quote Link to comment Share on other sites More sharing options...
blizzy78 Posted July 31, 2014 Share Posted July 31, 2014 Diazo, nothing in particular jumps out at me in your code. However, I don't use node.nodes.Contains(), or node.SetNode(). Can you retry using node.HasNode() and simply .AddNode() in combination with removal for replacing an existing node? This always worked for me.https://github.com/blizzy78/ksp_toolbar/blob/master/Toolbar/Internal/Extensions.cs#L61-L88 Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 31, 2014 Share Posted July 31, 2014 Alright, I'll try that.I'm out of other ideas at this point, I spent all my time last night on this one issue and I'm starting to wonder if I'm using using confignodes correctly.For the record, I'm trying to make an AGExt.cfg file in the same directory as your persistance.sfs file that has this format:FLIGHT{ Vessel1 { Part1 { Action1 { //data } Action2 { //data } } Part2 { Action1 { //data } } }}Confignodes can do this correct? When I open the persistent.sfs file I see that there are nested config nodes this deep so I assume I can do it also?D. Quote Link to comment Share on other sites More sharing options...
Noro Posted July 31, 2014 Share Posted July 31, 2014 Hello, I have a question about ScenarioModule.Is it possible to instantiate a class based on ScenarioModule? I tried it may ways around and it still gets destroyed every time the scene changes I'm using construction like: [KSPScenario(ScenarioCreationOptions.AddToNewCareerGames, new GameScenes[] { GameScenes.FLIGHT, GameScenes.SPACECENTER, GameScenes.SPH, GameScenes.EDITOR })] public partial class MyClass : ScenarioModuleI even use DontDestroyOnLoad(this) in my OnAwake() method but I still get all static class data wiped at the scene change. So is it possible at all to get an instance of the ScenarioModule based plugin? Or I should rewrite all that I have to KSPAddon format? I started to use ScenarioModule since it have easy save/load functionality but I didn't think it wouldn't be able to save static data between scenes 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.