Jump to content

Diazo

Members
  • Posts

    2,077
  • Joined

  • Last visited

Everything posted by Diazo

  1. Hmmm. Lots of things to think on and test. Any tests on my end will have to wait until the weekend as I really won't have enough time to work on this until then. First, on the object life cycle I think we just need to be clear that the OnDisable() method is used. (I think that is what Unity calls it's on destroy method.) This is true not just for this but for other things as well (toolbar buttons, etc.) so it's something a modder will need to know regardless. I think the benefits of having the event initialized as soon as the game loads to avoid race conditions is of a bigger benefit then destroying/recreating the event would be during the game to destroy orphaned delegates from event. I'm not aware of any method where the event itself can check for null and remove delegates from itself? Second, for the object passed I think it's going to be a "container" object that never changes, just the data inside. I can't see any other way to handle multiple vessels. For instance, a static Dict<Vessel,List<bool>> created when the game loads that could be passed by public EventData<Dict<Vessel,List<bool>> actionGroupStates and then AGX would add/remove vessels to that dictionary as they came into or left physics range and kOS should see them automatically update. This would require significant testing of course, but I think everything in that event is a reference type so this works in theory. It would also require null checks all over the place as AGX would be adding/removing vessels to the dictionary without warning kOS about it. Lastly, this is my first real foray into events so my terminology is iffy. Notably I'm not sure I'm using 'delegate' right, is the event itself a delegate, or the methods that get attached to the event via .add() the delegates? D.
  2. That would work? That opens up possibilities. As for what gets passed, I just threw out ConfigNode because that's what KSP uses to store data, the event could be attached to anything. Now, I'm on my mobile and can't run test code, just to be clear what should happen (non-working pseudo-code): In AGX: public class EventHandler { public static List<bool> actionGroupStates public static EventData<> ActionGroupStateRequest public static EventData<List<bool>> ActionGroupsStateData ActionGroupStateRequest.Add(requestFire) public void requestFire() { ActionGroupsStateData.Fire(actionGroupStates) } } then in kOS: [KSPAddon.Flight] public class kOSFlight { public List<bool> actionGroupsState; public void Start() { ActionGroupStateData.Add(handleData); ActionGroupStateRequest.Fire(); } public void handleData(List<bool> groupsList) { actionGroupsState = groupsList; } } So after all this code is run, when AGX updates EventHandler.actionGroupStates, those changes will be reflected in kOSFlight.actionGroupsState without any other code required? Interesting and will be quite useful. However that requires some code on the kOS end of things to handle it, the question becomes which is the "better" way to handle things, this way via events or the existing reflection system we have setup? One of my goals here is to make AGX easier to integrate with on a basic level for smaller mods, it's quite possible there will be a set of events for basic use of AGX, then stay with reflection for the more complex stuff kOS uses. (No comment on the IList thing, that will have to wait until I'm at my KSP computer.) D.
  3. Hmmm, not sure I have an answer, but see my comments in line: public static double SuicideBurnCountdown(Orbit orbit, VesselState vesselState, Vessel vessel) { //make sure we have a vessel reference if (vesselState.mainBody == null) return 0; //make sure our orbit actually will hit the ground. Note this check assumes the planet is a perfect sphere with ground always at zero altitdue. if (orbit.PeA > 0) return Double.PositiveInfinity; //how far off horizontal are we for our thrust vector? double angleFromHorizontal = 90 - Vector3d.Angle(-vessel.srf_velocity, vesselState.up); //sanity check that doesn't really work, see my comments below angleFromHorizontal = MuUtils.Clamp(angleFromHorizontal, 0, 90); //Untiy does math in radians for some reason so convert double sine = Math.Sin(angleFromHorizontal * UtilMath.Deg2Rad); //current force of gravity double g = vesselState.localg; //current available max thrust. This is calculated elsewhere. double T = vesselState.limitedMaxThrustAccel; //now this is a mess, see my comments below double effectiveDecel = 0.5 * (-2 * g * sine + Math.Sqrt((2 * g * sine) * (2 * g * sine) + 4 * (T * T - g * g))); //we know how fast we can decel, find out how long it takes us to stop double decelTime = vesselState.speedSurface / effectiveDecel; //take a guess at our landing site, this won't be too accurate but close enough Vector3d estimatedLandingSite = vesselState.CoM + 0.5 * decelTime * vessel.srf_velocity; //get height of terrain at our estimated impact site, note no check for ocean double terrainRadius = vesselState.mainBody.Radius + vesselState.mainBody.TerrainAltitude(estimatedLandingSite); double impactTime = 0; try { //set impactTime to equal the time our *current* orbit intersects that altitude, so without a burn. impactTime = orbit.NextTimeOfRadius(vesselState.time, terrainRadius); } catch (ArgumentException) { return 0; } //actually return how long our suicide burn will take return impactTime - decelTime / 2 - vesselState.time; } First, this code makes a lot of assumptions. For just displaying a "Suicide Burn Time" number it gets away with them, but I'm not sure I'd tie this directly into a control circuit. You say it's for KER so no issue there. Notably this code assumes we are already in a mostly vertical descent on final approach. Some of the numbers returned are "close enough" in that case, but go out of wack otherwise. if (orbit.PeA > 0) return Double.PositiveInfinity; -> No check for mountains. Are you in a low orbit around the Mun and have the bad luck of intersecting a mountain range several KM high? Sorry, this code thinks you will miss them as it checks current orbit against sea level to see if you are going to hit the ground. double angleFromHorizontal = 90 - Vector3d.Angle(-vessel.srf_velocity, vesselState.up); -> Assumes our engines are always point in a downwards direction even if they are pointing up. So if your engines are point 45° above the horizon, this line will think your engines are 45° below the horizon. Vector3d estimatedLandingSite = vesselState.CoM + 0.5 * decelTime * vessel.srf_velocity; -> Guess our landing site based on our *currently available* horizontal thrust based on how far off vertical we are. Are we almost vertical on final approach? Close enough. Are we higher up with a significant sideways speed remaining with vessel off vertical? Will be way out of wack. Player doesn't see this so probably not an issue. Now for the kicker, and I can't fully parse this line: double effectiveDecel = 0.5 * (-2 * g * sine + Math.Sqrt((2 * g * sine) * (2 * g * sine) + 4 * (T * T - g * g))); Breaking it down, but I'm not sure of my logic here. First, get rid of all the numbers, they may be needed for accuracy in the math but for figuring the logic out we can ignore them, so: double effectiveDecel = -1 * g * sine + Math.Sqrt((g * sine) * (g * sine) + (T * T - g * g))); So inside the square root we are left with two pythagoreas calcs. The first is our available thrust after accounting for gravity: t^2 = T^2 - g^2 Then the second is the g*sine, so x^2 = (g*sine)^2 + t^2 That is our effective thrust, so we then subtract gravity (-1 * g *sine) from it again? That makes no sense. It's also the best explanation I can come up with so I'm stumped. D.
  4. @xEvilReeperx That sounds exactly what I want to do. I just don't have a clue what you mean by "fill in" data. I'm going to head to google after this post and see what I find, but my current understanding is: Make onTestEvent. In AGX: onTestEvent.Add(onEventFire); In ModB call: onTestEvent.Fire(); That causes onTestEvent to be triggered by ModB and onEventFire to run in AGX and can pass data from ModB to AGX, but I'm blanking on how that gets data back to ModB. Ignoring code for a second, what I'm trying to accomplish is: A kOS script needs to know if action group 15 is on or off, that data is stored in AGX so it queries AGX "What is AG15s state?" AGX then returns "AG15 is on/off" depending on the groups current state. Currently we've worked out the raw reflection ourselves to get something that works, but that is messy and requires coordinating code between the two mods so I was hoping to streamline/simplify things with these new events, but it's not turning out to be as striaghtforward as I'd hoped. D.
  5. EDIT: See this post for the answer and example code on how to sync data between two mods by passing a reference. To answer my question, the method called by the event firing cannot be static. So in my example above, once I made the testAGXemthod(string str) non-static, things appear to work. At least this step does, now to move on and find the next issue. D. edit: My next question is handling "requests". Using my AGX example, ModB wants to know which action groups have actions assigned. This is going to require two events, one to trigger the request, one to return the data. I'm thinking something like: public static EventData<string,ConfigNode> onAGXDataRequest; public static EventData<string,ConfigNode> onAGXDataReturn; ModB would trigger onAGXDataRequest when it wants data, then AGX would trigger onAGXDataReturn with the data. The String would be an identifier, remember that ALL mods that subscribe to onAGXDataReturn will see the data so you need a way to tell which request is yours. The ConfigNode will contain the data requested and then the data returned. However, this is messy because it breaks the code up in ModB. The request event gets fired, then there is a break in the code until ModB sees the data returned when the second event fires. For something like kOS that needs instant data I'm not sure this works too well but I can't think of any better ideas. Anyone have any thoughts on this? D.
  6. The issue is that you talk about "a" part (singular) and part"s" (plural) in your post. Notably you talk about ModuleDecouple (joins two parts together) and a part that has launch bays, but no mention of how the launch bays will hold pods. Are they going to be clip-in where you add the launch bays part, then add each pod to a bay in the editor? Or will it be one part where you add the launch bays part in editor and the pods magically appear when you actually abandon ship? Both methods are possible, but very different in code. D.
  7. I can't actually answer any of these questions, but as a modder who will be looking at supporting translations the way I'd intended to approach it avoids those questions (I think). I'm simply going to support loading text strings from a text file so anyone who does a translation of my mod can distribute it themselves, I don't have to get involved. I intend to go this route to avoid update delays, once a translation is done it can be released in a usable format by the translator, they don't have to forward it to me to compile into the mod and wait for me to get around to it. It is a bit of extra work in the code to support this, probably more then just directly adding another language myself would be, but if the mod is translated into two or three (or more) languages, this way results in less time required on my part. And so I avoid those questions you've posted, I distribute only my mod and the translator distributes his translation file. Any issues with the files being distributed by the translator are clearly their problem this way as they (not me) are distribution the translation. Disclaimer: Not an employee of Squad or a lawyer, just how I intend to handle it. D.
  8. Okay, not sure what is going on here, running some test code to understand things before I start actually using this. Due to how I want to use this, I am going to end up with a Static event handler class, my current test case is as follows: namespace ActionGroupsExtended { public static class AGXEventHandler { public static EventData<string> onTestEvent; public static void init() { Debug.Log("AGX event init fired!"); onTestEvent = new EventData<string>("onTestEvent"); Debug.Log("AGX event init2fired!"); onTestEvent.Add(testAGXmethod); Debug.Log("AGX event init 3fired!"); } public static void testAGXmethod(string str) { Debug.Log("AGX sees event fire!"); } } } the "init()" method is called from within another class running as a KSPAddon.Instantly so that runs very early in KSP's loading sequence. I did move this to KSPAddonMainMenu but the same error was thrown. The error in question is thrown by the "onTestEvent.Add(testAGXmethod);" line and is as follows: NullReferenceException: Object reference not set to an instance of an object at EventData`1+EvtDelegate[System.String]..ctor (.OnEvent evt) [0x00000] in <filename unknown>:0 at EventData`1[System.String].Add (.OnEvent evt) [0x00000] in <filename unknown>:0 at ActionGroupsExtended.AGXEventHandler.init () [0x00000] in <filename unknown>:0 at ActionGroupsExtended.AGXInstantly.Start () [0x00000] in <filename unknown>:0 Note despite the reference to the Event's .ctor method, this nullRef is happening when I try to .Add(testAGXmethod) as I see the "AGX event init2fired!" in the log just before the error and "AGX event init 3fired!" does not show. What am I missing here? D.
  9. Not sure the exact config change you used @Cheesecake, but the fix I can apply from my end changes AGX's module manager config. If anyone else is having this issue, if you go to GameData\Diazo\AGExt\part.cfg and change it's contents to: @PART[*]:FINAL { MODULE { name = ModuleAGX } } That will resolve this. The only change is adding the ":FINAL" in the first line. This change will be included in AGX's next update, but that is a ways off. Happy KSPing all. D.
  10. It looks like there still is the issue. Error "7g1" means the partModule isn't present which due to the fact it is a Procedural Fairing makes sense. I'll poke at it again and see what I can do. D.
  11. As requested, ModActions is updated for those actions. Some of them were already in the mod (toggle/invert motors and traction control) but steering toggle/invert and friction control were missing and have been added. Let me know if there are any issues. D.
  12. Version 1.5 More updates to support the new wheel system. (From KSP 1.1) -Wheel steering enable/disable/toggle and steering direction enable/disable/toggle. -Friction control enable/disable/set value. Friction control works on a value from 0 to 5 and the value it is currently set to can not be viewed in game, although whether Friction Control is on or off can be seen in the part right-click menu. Github download. Added some actions that were missed when I originally updated this mod for the new wheel system in KSP 1.1, thanks to @supergameplayer for pointing them out. Happy KSP'ing all. D.
  13. My ModActions mod does this, but I didn't realize that some of the stock action groups had gone missing in 1.2 and so probably aren't in the mod yet. What actions are you specifically looking for? I should be able to add them to ModActions in the next day or two. D.
  14. Own its own it does not. However, if you grab my other mod called 'ModActions' it has the ability to add new actions to parts, including the ability to set RCS thrust limits. Once those actions are added to the part through ModActions, you can then add them to an action group with AGX the same as any other action. D.
  15. While I'm not sure I can actually help, I'm pretty sure that everything you are seeing comes from the fact that the root part is the "start" of the vessel layout in the data file. So I presume that when you change the root in flight, there is no more "start point" for building the vessel and while it may render on-screen, a whole bunch of behind the scenes stuff has gone wrong. Now, Squad obviously has code buried in the game somewhere to handle the changing of root parts, at the very least undocking would require this. If you can hook into that you are good to go, otherwise I'd look at trying to resolve your issue another way. Trying to reverse engineer everything that goes on and change the root part yourself is just asking to summon the kraken if you miss the tiniest thing. It would also be very prone to breaking any time KSP updated. D.
  16. Hmmm, alright. I'll jump back into my test code and see, maybe I just had a typo or something. Will post my test code once I'm home after work. D.
  17. Looking at the new GameEvents extension, it could actually solve a lot of my problems with inter-mod communication I'm running into for AGX. However, one trick I haven't figured out is how to send data the other way. This works: 1) AGX makes an "action group triggered!" event. 2) OtherMode subscribes to the event so it knows an action group has been triggered by AGX and can do it's own thing. What I want to do. 1) AGX makes an "trigger action group!" event. 2) OtherMod triggers the event so AGX knows an action group has been triggered and does it's thing. Note how the mod that makes the event (AGX) is not the same mod triggering it (OtherMod). For people here who are actually programmers and know C#, is this something that is doable with this new GameEvents functionality or am I still stuck with using my own reflection code to take care of this? D.
  18. Well, not having tested it I see the STATIC keyword on the event method where it is created. Statics can only exist once, so if you have a partModule with an "EventA" event, because it's static there is only one "EventA", even if there are multiple copies of the partModule loaded. So you would need to pass the part or partModule triggering the event as the EventData to keep things straight. I also see no mention of inheriting from MonoBehavior being necessary. I assume there is reflection trickery involved here finding all static methods with the EventData return type. If I ever use this, my first attempt would be making a static class to hold my static event calls, then in a KSPAddon.MainMenu initialize them. Then when they fire, just call the event from whatever code is running at the time. Since they are a static method in a static class I can access the .Fire method at any time. I see a LOT of problems trying to add this in a partModule as the event has to exist before the other mod subscribes to it. D.
  19. @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.
  20. Version 2.1 Download here. -Fix PQS math error when oceans are present. -Reduce size of ASL/AGL text. Alright, this should fix the errors in altitude being displayed over the ocean. @A_name Are you able to test the second case in your pictures again? (Where the correct altitude was 9km and this mod was displaying 3km) I'm asking because I can see how the error I fixed could cause a incorrectly high reading, I can't see how it would cause an incorrectly low reading. Now, it was a pretty major math error so it might be fixed but I'd like to confirm. I also reduce the size of the AGL/ASL text over the pressure gauge as per comments in thread. This work any better? Happy KSPing all. D.
  21. Click to change the mode, one of the available modes has the text hidden and auto-switches based on Surface or Orbit mode. D.
  22. Weird. The latter part of the sequence of pictures is up at 9km altitude, this mod is supposed to disable itself when you are that high because the ground is outside the physics bubble so there is no ground for the raycast to hit. Should get a chance to investigate tomorrow, I need to launch KSP and watch the numbers I'm doing math with to see what is happening. D.
  23. 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.
  24. My ModActions mod does allow you to set the part that is the "Control From Here" part via action groups. However, it does not allow you to change the up direction without changing to another part as requested in the opening post. The root issue is that there isn't actually a "Vessel" object in the game, just a "Collection of Parts" that looks like a vessel. So there is no "Vessel" up direction to modify, vessel up is actually whatever is up for the current Control From Here part. The only way I can even think of fixing it is adding an invisible Part somehow, but that creates a host of other problems that I'm not sure are solvable. D.
  25. Say hello to a lot of the IT help requests I get, this is distressingly common in any sort of server file storage environment. Never had to use the backups for their intended purpose yet (hallelujah!) but they've paid for themselves so many times over due to stuff like this. It's actually distressing how many times I get "but I only deleted the file!" when it was actually the folder in the left-hand tree pane that had focus so they deleted the entire directory, had half the accounting system vanish last year due to that ..... D.
×
×
  • Create New...