Cephei

The official unoffical "help a fellow plugin developer" thread

Recommended Posts

in OnPartLoad call a hand-written parser, check the fx definition sections for the group names, then

if (part.findFxGroup(fxgroupname) == null ){part.fxGroups.Add(new FXGroup(fxgroupname));}

After that it doesn\'t throw that error.

Or just define all the necessary groups.

Share this post


Link to post
Share on other sites

Yep, that appears to be the bit I was missing. Works great, thank you. I don\'t bother parsing the .cfg manual, just add the needed groups in onPartLoad() and it parses the fx_ lines properly.

Share this post


Link to post
Share on other sites

I\'m even not sure which way to use for my engine module. Imagine 36 nozzles each with its own fxgroup? Well, for N1 Block A engine (engine designers\' worst nightmare) it could be possible to reduce logical nozzle number to 15 or less, but, for example, LOK (Block I) engine includes 2 engines (the bigger one has 2 chambers), several (I\'m not even sure how many) steering nozzles that are connected to the engines (but respond to attitude control, so each should be processed separately) and 16 RCS nozzles on the rear skirt.

The fun part is that some of the structures (at least arrays) are passed from what was parsed during loading when creating a new part but some (structs, objects) aren\'t. In some cases it\'s easier to call the main parser in onPartStart() or onFlightStart(), than to stick that amount of data in arrays and other structures, that are copied, and then process it again into what actually is used.

Share this post


Link to post
Share on other sites

Just wanted to mention, Alchemist, C# gets awful 'funny' when it comes to data structures. Most stuff is actually a pointer(lvalue), while some stuff is an actual rvalue, but C# hides both types behind variable types that don\'t necessarily correspond with what one might expect. MS calls it reference and value types, but it\'s really just a game of hiding the pointers. Unfortunately, since you can\'t see the actual pointer syntax, you can never be quite sure whether or not they need referencing, or a new heap block assigned.

You mentioned arrays being parsed correctly, but structs not. AFAIK, arrays are actually pointers, and structs are actually rvalues. I can\'t see the parser code, or the part class constructor, but I bet it\'s a heap allocation problem.

Share this post


Link to post
Share on other sites

Hey, i\'m actually working on a plugin that uses warp rate and i wondered... with the 'warp rate modifying' code (see wiki), can you set it up so you can go BACK IN TIME ???

Share this post


Link to post
Share on other sites

If you mean 'run the clock backward', I have no idea, you\'d have to try it out yourself, none of us actually know what the tools we were given do under the hood.

If you mean 'everything goes back the way it was', then no.

Share this post


Link to post
Share on other sites

I reckon going back in time as it were won\'t work, as KSP will recalculate the data involved, and depends if on rails or not will change the math involved.

So if it can run backward it won\'t work properly.

Share this post


Link to post
Share on other sites

I just tried it, but it seems i messed up something in my code... I\'ll retry it

Share this post


Link to post
Share on other sites

Now I\'m very confused. I\'ve got a function to pack a bunch of cfg-parsed-fields into a list<> for iteration sanity. If I understand what Alchemist wrote, I can just call that function from OnPartLoad and be done with it.

But I thought each physical part on the ship got it\'s own instance of the corresponding part class...how can the instance of a class possibly exist at game loading if it\'s not created until you pick it in the VAB? I\'m probably just tired and not thinking this through, otherwise Squad\'s invented a code time machine.

Share this post


Link to post
Share on other sites

I\'ve been looking at that recently because I\'ve been getting some really weird behaviour in plugins, with bugs appearing or disappearing depending on whether you construct a new ship in the VAB, restart with an unmodified ship in the VAB, or resume an already running ship etc.

As far as I can tell, after onPartLoad() is called (during the initial game loading) the game saves the state of the part using serialization. It doesn\'t seem to use the standard C#/.NET serialization routines (maybe Unity\'s built-in serialization but I can\'t find much info on it). Then when a part instance is created it deserializes the stored part.

Anyway, it looks like it serializes only public fields so you should be able to declare your List<> as public and anything done in onPartLoad() should carry through to each part instance.

Share this post


Link to post
Share on other sites

After much testing, tinkering, and general screwing around, I can say that


protected override void onGamePause()
{
KFTDWindowCrap.Pause();
MonoBehaviour.print('K Paused');
MonoBehaviour.print('FD.Pause = ' + FlightDriver.Pause.ToString());

base.onGamePause();
}

protected override void onGameResume()
{
KFTDWindowCrap.UnPause();

MonoBehaviour.print('K Unpaused');
MonoBehaviour.print('FD.Pause = ' + FlightDriver.Pause.ToString());

base.onGameResume();
}

shows the static property

FlightDriver.Pause

seems to be usable in place of onGamePause()/resume with one notable exception.

-When switching flights with the tracking station, onGamePause() is called if you use the ESC menu to switch OUT of a flight. onGameResume() is NOT called when switching back INTO a flight. Unknown yet if FlightDriver.Pause updates itself in this instance, but I suspect it does, so if you really need to know if the game is paused, it might be better to check against FlightDriver.Pause than handling onGamePause()/resume.

Now I\'ve got two questions:

-Does anyone know of a way to catch when a flight is ended(as in switching flights, ending them, or whatever)? Ending a flight even through vessel switching seems to clear whatever GUI callbacks you had setup(with no additional code on your part), and this is giving me problems as I need to know if I have to reinstate the GUI callback.

-RenderingManager.AddToPostDrawQueue() takes an int 'queueSpot' as it\'s first param, however, there doesn\'t seem to be a provided getter function to return a valid entry for this. At first, I assumed this was a sort of unique GUID so the wrapper can keep track of handles, but then I noticed there\'s also

public Callback[] postDrawQueue;

which is an array, not a list, which would imply it has a predetermined number of elements.

My questions, if anyone knows the answers are what are we supposed to pass as queueSpot, and are we limited to a predetermined number of registered callbacks, and if so, how many?

Share this post


Link to post
Share on other sites

I\'m new to this, but here goes: how can I place text at some point in 3D space, like the pink indicator for other spacecraft?

Share this post


Link to post
Share on other sites
I\'m new to this, but here goes: how can I place text at some point in 3D space, like the pink indicator for other spacecraft?
That\'s how it\'s done in Laser plugin:

  void drawGUI() {
Vector3 p = Camera.main.WorldToScreenPoint( some_point_in_3D );
if( p.z >= 0 ) { // it\'s before the camera, not behind it
p.y = Camera.main.pixelHeight - p.y;
// now draw some text at 'p' point
}
}

Share this post


Link to post
Share on other sites

Looking through my output log, seems the plugin parser is trying to load stuff from subdirectories under Plugins. If you stuck your project folders in there, probably a good idea to move them out now.

Share this post


Link to post
Share on other sites

Found interesting data while trying to drain Kerbin\'s oceans, and fix the lag maybe.

-FlightGlobals.fetch.bodies will give you an array of celestial bodies, of which one is named 'Kerbin' and one is 'Sun'

-Iterating that array for 'Kerbin' will give you it\'s CelestialBody

-PlanetQuadTreeController CelestialBody.terrainController from one of those cb\'s yeilds null

-However, PQS CelestialBody.pqsController is NOT null, have to play with this further

-Also, CelestialBody.referenceBody called on Kerbin\'s cb will give you the 'Sun', might be helpful if r4m0n gets around to making MechJeb allow reverse hierarchy injection burns.

Share this post


Link to post
Share on other sites

Ok, I got Mu\'s 'generic reaction engine' example set up and (mostly) working (with dual fuel use/storage also), but there\'s something that\'s bugging me still.


[KSPField]
public string thrustVectorTransformName;

thrustTransform = part.FindModelTransform(thrustVectorTransformName);

if (thrustTransform != null && part.Rigidbody != null)
{
part.Rigidbody.AddForceAtPosition(-thrustTransform.forward * currentThrust, thrustTransform.position);
}

That\'s not what it looks like in my version, but there\'s potentially something there I can\'t figure, as I don\'t touch modeling 'art' stuff if I can avoid it.

thrustVectorTransformName is supposed to be a string denoting 'something' that\'s got with

part.FindModelTransform(thrustVectorTransformName)

I assume this is done either to confuse us, or to take into account mirroring/rotated parts with the VAB changes.

I want to know exactly what this string value is supposed to be set to, or what the relevant code object is so I can pull it thataway. I have a strong suspicion it\'s something defined in the model heirarchy, but I just don\'t understand such things.

Once I get some kind of readout on the tank contents, I\'ll put up the whole thing in this forum section for anyone who wants a concrete example of how to get the new module and resource stuff working.

Share this post


Link to post
Share on other sites

Not sure if this has been asked already but I did have a quick search.

What is the best way to get the distance between two vessels? Namely the vessel a modified part is attached to (currently being flown) and any other vessel in the world. I assume it would be using Vessel.findWorldCenterOfMass(); and doing some calculations on the coords.

On a related note, what are the coords relative to?

Thanks.

Share this post


Link to post
Share on other sites
Not sure if this has been asked already but I did have a quick search.

What is the best way to get the distance between two vessels? Namely the vessel a modified part is attached to (currently being flown) and any other vessel in the world. I assume it would be using Vessel.findWorldCenterOfMass(); and doing some calculations on the coords.

On a related note, what are the coords relative to?

Thanks.

Yes, exactly.

float distance = ( vessel1.findWorldCenterOfMass() - vessel2.findWorldCenterOfMass() ).magnitude;

World coordinates are measured relative to 'scene origin', some arbitrary point in space which constantly changes during the flight (Harv references it as 'floating origin'). That shouldn\'t bother you either; just don\'t store those coordinates, get newest ones in each frame instead.

Share this post


Link to post
Share on other sites

Not sure if this helps, but there\'s also a static FlightGlobals.Vessels which should hold a List<Vessel> that you can get anywhere. Might also be easier to grab FlightGlobals.Vessels[0].rootPart.transform.position, and compare those values, once you find which one is your vessel. Just mentioned it, as those are all from statics, so you can pull the values from anywhere.

Share this post


Link to post
Share on other sites

It seems that under the new regime, >model/obj_gimbal< is a string that gives me a working solution to my earlier problem:

Ok, I got Mu\'s 'generic reaction engine' example set up and (mostly) working (with dual fuel use/storage also), but there\'s something that\'s bugging me still.


[KSPField]
public string thrustVectorTransformName;

thrustTransform = part.FindModelTransform(thrustVectorTransformName);

if (thrustTransform != null && part.Rigidbody != null)
{
part.Rigidbody.AddForceAtPosition(-thrustTransform.forward * currentThrust, thrustTransform.position);
}

That\'s not what it looks like in my version, but there\'s potentially something there I can\'t figure, as I don\'t touch modeling 'art' stuff if I can avoid it.

thrustVectorTransformName is supposed to be a string denoting 'something' that\'s got with

part.FindModelTransform(thrustVectorTransformName)

I assume this is done either to confuse us, or to take into account mirroring/rotated parts with the VAB changes.

I want to know exactly what this string value is supposed to be set to, or what the relevant code object is so I can pull it thataway. I have a strong suspicion it\'s something defined in the model heirarchy, but I just don\'t understand such things.

Once I get some kind of readout on the tank contents, I\'ll put up the whole thing in this forum section for anyone who wants a concrete example of how to get the new module and resource stuff working.

Whatever gets returned from part.FindModelTransform('model/obj_gimbal') not only is not null, but it actually works in my code for making the thing fly straight. What\'s very interesting about this, is that I\'m using C7\'s structural fuselage with that code. When exactly did fuselages get a obj_gimbal?

It IS null, I just commented out my debug spammer. Now I have to figure out a valid string to pass into part.FindModelTransform, as I\'m trying to test Mu\'s ModuleEngineRocketLiquid that\'s in the KSP assembly, and his version doesn\'t have a fail fallback setup like mine does.

Anyone have a good string to pass into a C7 fuselage to get the main transform?

Share this post


Link to post
Share on other sites

Fun with Part Stage values:

After testing, came to some conclusions about part stage values:

For <Part>:

stages are 0 based ascending, comand pod starts in stage 0.

inverseStage = the stage the part appears in the actual stage GUI(ie, final stage after all adjustments).

inStageIndex = the index value of a part within a stage. Zero based.(ie if part is the third part in the fifth stage: inverseStage = 4 & inStageIndex = 2)

originalStage = which stage the part was added to originally by the game. Zero based.

defaultInverseStage = appears the same as above, unclear difference.

manualStageOffset = what it says on the tin.

Share this post


Link to post
Share on other sites

inverseStage = the stage the part appears in the actual stage GUI(ie, final stage after all adjustments).

originalStage = which stage the part was added to originally by the game. Zero based.

defaultInverseStage = appears the same as above, unclear difference.

I haven\'t checked these values in flight but as far as in the editor

inverseStage = Usually is the stage that it appears in in the gui, however if you move all parts out of a stage and remove that empty stage this is no longer accurate. The game still thinks that empty stage exists even though it doesn\'t show up on the GUI. This may be a bug and is an issue i\'m still trying to solve for my engineer plugin.

defaultInverseStage = The stage where the game puts a part when you add it to a ship while in the editor at least.

originalStage = seams to always be 0 in the editor possibly just not used there.

inStageIndex = I\'ve seen negative values for this not sure what to make of it

there are some more stage related values than what you listed they don\'t always make cense to me in the editor and may only have meaning in the flight scene

childStageOffset

stageOffset

stageAfter

stageBefore

Share this post


Link to post
Share on other sites

Fun with Gimbals:

For some reason, I have both .mu files, and .dae stuff in my LiquidEngine2 Part folder, not sure if I put them there, or Squad did.

In any event, trying to grab hold of the gimbal transform, this is what I encountered:

-Using the model.mu files:

The following all fail, except the very last one, part.FindModelTransform('solid_rocket');


GimbalTransform = part.transform.FindChild('model').FindChild('obj_gimbal');
if (GimbalTransform == null)
{
Debug.Log('KIS fail0');
GimbalTransform = part.transform.Find('model/obj_gimbal');
if (GimbalTransform == null)
{
Debug.Log('KIS fail1');
GimbalTransform = part.FindModelTransform('obj_gimbal');
if (GimbalTransform == null)
{
Debug.Log('KIS fail2');
GimbalTransform = part.transform.Find('solid_rocket');
if (GimbalTransform == null)
{
Debug.Log('KIS fail3');
GimbalTransform = part.transform.FindChild('solid_rocket');
if (GimbalTransform == null)
{
Debug.Log('KIS fail4');
GimbalTransform = part.FindModelTransform('solid_rocket');
}
}
}
}
}

How did I get 'solid_rocket'? I derived from LiquidEngine, and asked it nicely to tell me what 'fallbackGimbalName' in LiquidEngine was.

-Now using the mystery liquidEngine2.DAE files I had:

The first three attempts all succeed in acquiring the gimbal transform.

The last three all fail.

Conclusion:

'obj_gimbal' has been replaced with 'solid_rocket' in the LiquidEngine2 at least. The .name of the Transform assigned to the gimbal object also reports as 'solid_rocket', so I assume that\'s a fairly safe bet.

Also, FindModelTransform called on a Part instance seems to be the preferred method of obtaining this thing, as it was the only function which successfully acquired the gimbal transform from the model.mu files, and also retrieved 'obj_gimbal' from the liquidEngine2.DAE without bothering with 'model'.

As always, expect someone to come correct me shortly.

Share this post


Link to post
Share on other sites

Hey all! I\'ve been working on plugin that I am trying to make so that vertically mounted engines could be automatically controlled to hover at a set altitude. However, I am having some trouble in doing this. I have 90% of the code in place and the only thing that I am actually missing is the formula to calculate it. I\'ve been trying several different methods and as time is progressing they\'re becoming less rational.

I\'ve got vertical speed and altitude already plugged in. Am I going to need to calculate mass/gravity and thrust also? The primary restraint is to have it work on any ship with enough thrust and vertically mounted engines. Please reply here or PM me. I\'d appreciate the help and credit will go right where it\'s due.

Share this post


Link to post
Share on other sites
Am I going to need to calculate mass/gravity and thrust also?

That sounds like the best way to do it. It\'s not too hard to compute the mass and thrust of your ship and the gravitational force acting on it. Check out the calculation of maxThrustAccel and localg here: http://svn.mumech.com/KSP/trunk/MuMechLib/VesselState.cs . Here maxThrustAccel is the maximum acceleration that can be produced by the currently active engines, and localg is the acceleration due to gravity.

Then if you thrust straight up, you\'ll accelerate upward at a rate given by (maxThrustAccel - localg). So I would pick a target vertical speed as a function of altitude, something like

target vertical speed = ((target altitude) - (current altitude))/(10 seconds).

This will cause you to try to descend if you\'re above your target and ascend if you\'re below your target. If you manage to follow this vertical speed profile, you\'ll gradually come to a hover at the target altitude. But of course we don\'t control our vertical speed, we control our vertical acceleration. To get your vertical speed to match the target vertical speed you might try something like

target vertical acceleration = ((target vertical speed) - (current vertical speed))/(2 seconds)

This will cause you to try to accelerate if your speed is below your target and decelerate if your speed is above your target. Now, your actual acceleration is determined by your throttle setting (a number between 0 [min throttle] and 1 [max throttle]):

vertical acceleration = throttle * maxThrustAccel - localg

And you can solve this equation for 'throttle' to figure out what throttle you need to achieve a target vertical acceleration.

I haven\'t actually tried this algorithm, so no guarantees that it works, but it\'s what I\'d try first.

Share this post


Link to post
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.