KspNoobUsernameTaken Posted June 7 Share Posted June 7 How do you access a config node? I've been using this code but can't seem to figure it out: public class BPManagedResource { //public string ManagedResource = ConfigNode.GetNode("BPManagedResource"); public void OnLoad(ConfigNode BPManagedResourceNode) { string BPManagedResourceValueHelper = BPManagedResourceNode.GetValue("BPManagedResource"); } public string BPManagedResourceValue = BPManagedResourceValueHelper } But it keeps giving this error: Error CS0103: The name 'BPManagedResourceValueHelper' does not exist in the current context Quote Link to comment Share on other sites More sharing options...
0111narwhalz Posted June 10 Share Posted June 10 On 6/7/2024 at 12:34 AM, KspNoobUsernameTaken said: Error CS0103: The name 'BPManagedResourceValueHelper' does not exist in the current context This indicates that the variable name has exited the scope. If you look at the curly brackets, the variable BPManagedResourceValueHelper was defined inside the function OnLoad. If you try to use it outside of that function, there's no way for the compiler to know what variable you're talking about (since there might be other functions with variables with the same name in them, or indeed none at all). Instead, you need to define BPManagedResourceValue in the class scope, as you have, and then set it in the function scope (since that's where […]Helper is defined). Order shouldn't matter here, but it's considered good practice to put your class variables ("fields") above your class functions ("methods"), so you can immediately see all the fields of a class. Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted June 10 Share Posted June 10 7 minutes ago, 0111narwhalz said: This indicates that the variable name has exited the scope. If you look at the curly brackets, the variable BPManagedResourceValueHelper was defined inside the function OnLoad. If you try to use it outside of that function, there's no way for the compiler to know what variable you're talking about (since there might be other functions with variables with the same name in them, or indeed none at all). Instead, you need to define BPManagedResourceValue in the class scope, as you have, and then set it in the function scope (since that's where […]Helper is defined). Order shouldn't matter here, but it's considered good practice to put your class variables ("fields") above your class functions ("methods"), so you can immediately see all the fields of a class. Thank you, but I think I solved this. It is still quite helpful. Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 9 Share Posted July 9 (edited) Please help, I don't understand why this doesn't work: using System; using UnityEngine; namespace ConfigFileReader { [KSPAddon(KSPAddon.Startup.Instantly, false)] public class ConfigFileReader : MonoBehaviour { static readonly string ConfigFilePath = KSPUtil.ApplicationRootPath + "GameData/MyMod/Settings.cfg"; static ConfigNode Node1 = ConfigNode.Load(ConfigFilePath); static string Value1 = Node1.GetValue("Value1"); static ConfigNode Node2 = GameDatabase.Instance.GetConfigNode("TestNode"); static string Value2 = Node2.GetValue("Value2"); public void Update() { Debug.Log(Time.realtimeSinceStartup + "Value1 is: " + Value1); Debug.Log(Time.realtimeSinceStartup + "Value2 is: " + Value2); } } } It gives a NRE: object reference not set to instance of an object. Edit: This code doesn't error: using System; using UnityEngine; namespace ConfigFileReader { [KSPAddon(KSPAddon.Startup.Instantly, false)] public class ConfigFileReader : MonoBehaviour { static readonly string ConfigFilePath = KSPUtil.ApplicationRootPath + "GameData/MyMod/Settings.cfg"; static ConfigNode Node1; static string Value1; static ConfigNode Node2; static string Value2; public void Start() { Node1 = ConfigNode.Load(ConfigFilePath); Value1 = Node1.GetValue("Value1"); Node2 = GameDatabase.Instance.GetConfigNode("TestNode"); Value2 = Node2.GetValue("Value2"); } public void Update() { if (String.IsNullOrEmpty(Value1)) { Debug.Log(Time.realtimeSinceStartup + "Value1 is empty"); } else { Debug.Log(Time.realtimeSinceStartup + "Value1 is: " + Value1); } if (String.IsNullOrEmpty(Value2)) { Debug.Log(Time.realtimeSinceStartup + "Value2 is empty"); } else { Debug.Log(Time.realtimeSinceStartup + "Value2 is: " + Value2); } } } } But it gives empty values. For reference, the cfg file is in a file named Settings.cfg under MyMod and these are the contents: NODE { name = TestNode Value1 = "Blue" Value2 = "Red" } Edit 2: I think I found something useful here: Testing this tommorow: Value1 = Node1.GetNode("TestNode").GetValue("Value1"); Edited July 9 by KspNoobUsernameTaken Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted July 9 Share Posted July 9 10 hours ago, KspNoobUsernameTaken said: static ConfigNode Node2 = GameDatabase.Instance.GetConfigNode("TestNode"); Node2 = GameDatabase.Instance.GetConfigNode("TestNode"); NODE { name = TestNode Value1 = "Blue" Value2 = "Red" } In these lines, I think the problem is that your code is using "TestNode" instead of "NODE". GetConfigNode doesn't care about the value of the nested "name" key, it cares about the string that comes right before the open curly brace. 10 hours ago, KspNoobUsernameTaken said: static ConfigNode Node1 = ConfigNode.Load(ConfigFilePath); static string Value1 = Node1.GetValue("Value1"); Node1 = ConfigNode.Load(ConfigFilePath); Value1 = Node1.GetValue("Value1"); NODE { name = TestNode Value1 = "Blue" Value2 = "Red" } Similarly, here you're not even trying to get the node at all. There should be a GetNode("NODE") in there somewhere to handle that structure. Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 9 Share Posted July 9 Oof. My brain seems to have malfunctioned here @HebaruSan. Will try and come back to you. Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 10 Share Posted July 10 (edited) So, tried this for Settings.cfg: TestNode { name = TestNode Value1 = "Blue" Value2 = "Red" } The following is an excerpt from debug log: [LOG 13:19:13.702] 12.83139Value1 is: "Blue" [LOG 13:19:13.702] 12.83148Value2 is empty [LOG 13:19:13.732] 12.86122Value1 is: "Blue" [LOG 13:19:13.732] 12.86133Value2 is empty [LOG 13:19:13.732] Load(Audio): Squad/Alarms/Sounds/Classic [LOG 13:19:13.734] 12.8632Value1 is: "Blue" [LOG 13:19:13.734] 12.86331Value2 is empty [LOG 13:19:14.061] 13.19004Value1 is: "Blue" [LOG 13:19:14.061] 13.1907Value2 is empty [LOG 13:19:14.062] 13.19196Value1 is: "Blue" [LOG 13:19:14.062] 13.19204Value2 is empty So approach 1 works, approach 2 does not. This is satisfactory for me. Next step: actually integrate it into beamed power. Thanks for the help @HebaruSan Edit: I noticed that the GameDatabase.Instance.GetConfigNode asks for a url, not a node name... is the url something different from the "string right before the curly braces?" Edit 2: Ok, on review of this thread by me: The node name is the correct input, so that isn't the issue. Edited July 10 by KspNoobUsernameTaken Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted July 10 Share Posted July 10 (edited) 15 hours ago, KspNoobUsernameTaken said: I noticed that the GameDatabase.Instance.GetConfigNode asks for a url, not a node name... is the url something different from the "string right before the curly braces?" Oh sorry, my advice was distorted by some messy API design choices: When these functions ask for URLs, that's a reference to the file path on disk. When they ask for a typeName, then that's the "NODE" or "TestNode" string we've been discussing. I was referencing working code that calls GetConfigNodes and reasonably but incorrectly extrapolating that GetConfigNode would work similarly, given that the only difference between them is plural vs singular. I'd go with GetConfigNodes and then just add a thin layer of logic to reconcile multiple return values if there are multiple. Edited July 10 by HebaruSan Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 11 Share Posted July 11 6 hours ago, HebaruSan said: When these functions ask for URLs, that's a reference to the file path on disk. That's quite interesting, and not what I expected. If I do use .instance.getconfignode, and input the file url, will any MM patches applied to it not function? I.E, will MM patches change the file url in the game database? Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted July 11 Share Posted July 11 2 hours ago, KspNoobUsernameTaken said: That's quite interesting, and not what I expected. If I do use .instance.getconfignode, and input the file url, will any MM patches applied to it not function? I.E, will MM patches change the file url in the game database? I believe you can still rely on having all the Module Manager patches applied. Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 11 Share Posted July 11 1 hour ago, HebaruSan said: I believe you can still rely on having all the Module Manager patches applied. Excellent, will test. Thanks for the help. Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 17 Share Posted July 17 Anyway to use KSPUtil.applicationRootPath at the initialization of a class? Before any other variables are initialized? Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 29 Share Posted July 29 Hi, I've got this code which is throwing NRE's, and I don't understand what's wrong with it: void Awake() { string ConfigFilePath = KSPUtil.ApplicationRootPath + "GameData/BeamedPowerStandalone/Settings.cfg"; ConfigNode MainNode; MainNode = ConfigNode.Load(ConfigFilePath); ManagedResource = MainNode.GetNode("BPSettings").GetValue("ManagedResource"); ResourceHash = PartResourceLibrary.Instance.GetDefinition(ManagedResource).id; Debug.Log(Time.realtimeSinceStartup + ManagedResource); } The settings.cfg file: BPSettings { ManagedResource = ElectricCharge } Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted July 29 Share Posted July 29 (edited) 1 hour ago, KspNoobUsernameTaken said: I don't understand what's wrong with it: A good way to start is to narrow down which part of which line is throwing. Edited July 29 by HebaruSan Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 29 Share Posted July 29 2 hours ago, HebaruSan said: A good way to start is to narrow down which part of which line is throwing. I found this in the KSP log, which I'm guessing is a stack trace: [ERR 11:28:12.512] PartLoader: Encountered exception during compilation. System.NullReferenceException: Object reference not set to an instance of an object at PartModule.Load (ConfigNode node) [0x0010d] in <4b449f2841f84227adfaad3149c8fdba>:0 at Part.AddModule (ConfigNode node, System.Boolean forceAwake) [0x0006f] in <4b449f2841f84227adfaad3149c8fdba>:0 at PartLoader.ParsePart (UrlDir+UrlConfig urlConfig, ConfigNode node) [0x00f10] in <4b449f2841f84227adfaad3149c8fdba>:0 at PartLoader+<CompileParts>d__56.MoveNext () [0x00685] in <4b449f2841f84227adfaad3149c8fdba>:0 UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[]) ModuleManager.UnityLogHandle.InterceptLogHandler:LogFormat(LogType, Object, String, Object[]) UnityEngine.Debug:LogError(Object) <CompileParts>d__56:MoveNext() UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) <CompileAll>d__13:MoveNext() UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) PartLoader:StartLoad() <LoadSystems>d__11:MoveNext() UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) [ERR 11:28:12.512] PartCompiler: Cannot compile part UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[]) ModuleManager.UnityLogHandle.InterceptLogHandler:LogFormat(LogType, Object, String, Object[]) UnityEngine.Debug:LogError(Object) <CompileParts>d__56:MoveNext() UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) <CompileAll>d__13:MoveNext() UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) PartLoader:StartLoad() <LoadSystems>d__11:MoveNext() UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) But I can't figure out what any of this means. Seems to me like ConfigNode.load is having some kind of error. Maybe moving the code to Start() will help. Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted July 29 Share Posted July 29 9 hours ago, KspNoobUsernameTaken said: But I can't figure out what any of this means. Seems to me like ConfigNode.load is having some kind of error. Maybe moving the code to Start() will help. Hmm, are you trying to write a PartModule? Because the stack trace says there's some problem loading a part, and it doesn't mention ConfigNode.Load at all. This could be some completely unrelated problem from another mod. 9 hours ago, KspNoobUsernameTaken said: at PartModule.Load (ConfigNode node) [0x0010d] in <4b449f2841f84227adfaad3149c8fdba>:0 at Part.AddModule (ConfigNode node, System.Boolean forceAwake) [0x0006f] in <4b449f2841f84227adfaad3149c8fdba>:0 Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 29 Share Posted July 29 5 hours ago, HebaruSan said: Hmm, are you trying to write a PartModule? Because the stack trace says there's some problem loading a part, and it doesn't mention ConfigNode.Load at all. This could be some completely unrelated problem from another mod. That's correct, it's a part module. I have identical code in several other classes too. I thought PartModule.Load is the same as ConfigNode.Load so I thought that was the error. Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted July 29 Share Posted July 29 (edited) 15 hours ago, KspNoobUsernameTaken said: But I can't figure out what any of this means. 18 hours ago, HebaruSan said: A good way to start is to narrow down which part of which line is throwing. OK, so the way you do this is with basic logic. Comment out a block of lines, compile, run, see if it still crashes. If so, then the exception is thrown by the part you didn't comment out. Otherwise it's in the part you did comment out. Change what's commented out, try again, and so on until you figure it out. Edited July 29 by HebaruSan Quote Link to comment Share on other sites More sharing options...
KspNoobUsernameTaken Posted July 29 Share Posted July 29 (edited) On 7/30/2024 at 6:40 AM, HebaruSan said: OK, so the way you do this is with basic logic. Comment out a block of lines, compile, run, see if it still crashes. If so, then the exception is thrown by the part you didn't comment out. Otherwise it's in the part you did comment out. Change what's commented out, try again, and so on until you figure it out. Oh. That seems obvious in hindsight. The funny part is I actually did this for MM patches, just never thought to apply it for programming. Edit: To anyone in the future: I think my error was that a static method called from a different class seems to count as a class initialization, even if it was called from Start(). KSP won't allow usage of ConfigNode.load during initialization, causing errors. Any data loading code should be outside class initialization. Edited August 3 by KspNoobUsernameTaken Quote Link to comment Share on other sites More sharing options...
Krafpy Posted August 3 Share Posted August 3 (edited) Hi everyone! I'm struggling to understand how the orbits and their coordinate systems are managed, and there are some behaviours that I don't understand at all... The most basic weird situation I encountered is the following code: CelestialBody body = // Get Mun's CelestialBody double now = Planetarium.GetUniversalTime(); body.orbit.GetOrbitalStateVectorsAtUT(now, out var r, out var v); Orbit orbitFromState = Orbit.OrbitFromStateVectors(r, v, body.orbit.referenceBody, now); // Draw orbitFromState in planetarium view in red // Draw body.orbit in planetarium view in green The rendererd orbits in the tracking station: The green orbit is the Mun's one, drawn for reference to check that this is not an issue from my renderer. The red one is the one calculated by OrbitFromStateVectors. I would expect GetOrbitalStateVectorsAtUT and OrbitFromStateVectors to be reciprocals of each others, but it's apparently not the case, why? Not only the calculated orbit is completely flipped 90 degrees, it also has wrong radius/semi major axis and eccentricity. I tried using getPositionAtUT and getRelativePositionAtUT as the position parameter for OrbitFromStateVectors: getPositionAtUT gives a 90 degrees flipped orbit but with the correct semi major axis and eccentricity (at least visually) getRelativePositionAtUT gives a 90 degree flipper orbit with wrong semi major axis and eccentricity, but a bit different from the one from GetOrbitalStateVectorsAtUT: the closest point to the Mun is closer for the orbit of getRelativePositionAtUT than for GetOrbitalStateVectorsAtUT (still not interesecting the Mun). I've read the available information on the Orbit class, from the official and community API documentations. From what I understood so far is that some method of the Orbit class return vectors where the y and z component are flipped (could explain the 90° flip), but not which ones explicitely nor why. I'm also aware different reference frames are used for different situation. Some function are "relative to the body" or "body ref centered" (according to the documentation), and others are in "world space". Is there any comprehensive documentation on how are orbits handled in KSP? More specifically, I'm looking for the following: What are KSP's different coordinate systems (naming conventions)? What is up (y? z?)? When are they used? How do I retrieve the physical body-centered inertial position and velocity of a body or vessel relative to the its reference body (with units in meters and meters/second)? What are the mEp and t parameters of the Orbit's constructor? Given an orbit (Orbit class instance), initial position on this orbit and the UT time t0 of this position, what are the proper steps to propagate that position to get the state vectors at time t0 + some delta t? I'd be very grateful of any help on this! Thank you very much in advance! Edited August 3 by Krafpy Clearer description Quote Link to comment Share on other sites More sharing options...
Ubus99 Posted August 13 Share Posted August 13 Hi, this might be answered somewhere already, but I could not find anything: How do I Access VesselDeltaV & DeltaVApp in VAB? When my mod executes on Start(), they are not yet instantiated and querying them returns null. I can access them by querying every frame until they are there, but that cant be a permanent solution. Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted August 14 Share Posted August 14 3 hours ago, Ubus99 said: I can access them by querying every frame until they are there, but that cant be a permanent solution. Try subscribing to GameEvents.onDeltaVCalcsCompleted. https://github.com/HebaruSan/SmartTank/blob/master/src/SmartTank.cs Quote Link to comment Share on other sites More sharing options...
Ubus99 Posted August 14 Share Posted August 14 8 hours ago, HebaruSan said: Try subscribing to GameEvents.onDeltaVCalcsCompleted. https://github.com/HebaruSan/SmartTank/blob/master/src/SmartTank.cs Thank you, but this event only toggles after a craft has been created. Is there a way to get it when entering the editor? By now I have also found basic dv's solution of polling it using a coroutine. But if there is an event that is triggered after all editor modules are loaded, that would be great. Quote Link to comment Share on other sites More sharing options...
HebaruSan Posted August 14 Share Posted August 14 5 hours ago, Ubus99 said: Thank you, but this event only toggles after a craft has been created. Is there a way to get it when entering the editor? I think I'm missing something. You want the result of the calculation before the calculation is performed? Quote Link to comment Share on other sites More sharing options...
Ubus99 Posted August 14 Share Posted August 14 47 minutes ago, HebaruSan said: I think I'm missing something. You want the result of the calculation before the calculation is performed? No. Right now I just want to understand the editor code, but eventually I want to modify the dv display & config panel itself. 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.