Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

Looks like Vessel has a new DiscoveryInfo property. That might be your way in

I was just a bit too slow to edit my own response. :sticktongue: I saw that all vessels have the new "Discovery" section in the persistent file with the "size" value that seems to match the asteroid class (though it seems to default to 2 for non-asteroid vessels).

This seems to work for finding the value of asteroid you're docked to, and I have another simple method of getting to the vessel data of a nearby asteroid.


KnowledgeItem<UntrackedObjectClass> sizeItem = FlightGlobals.ActiveVessel.DiscoveryInfo.size;
string size = sizeItem.Value;

That spits out A, B, C, etc..., then I can convert that back to "Class A" and so on. The DiscoveryInfo.GetSizeClassDescription() method gives you the long description shown in the tracking center, GetSizeClassSizes() gives you "C (medium)" and so on. There may be a more direct way of getting at the value, but that seems to work well enough.

The only thing I'm not sure of is whether that "size" value is affected by your actual vessel. The asteroid I'm docked to now is size=2, which should be Class C. I need to find a different class asteroid and dock to it to see which vessel's size number carries over.

Edit: Well drat. The spacecraft's "size" value seems to override the asteroid vessel's value, and it seems to be persistent, so once you've docked once it will always be seen as a Class C asteroid. Looks like it's back to using mass to figure it out.

Edited by DMagic
Link to comment
Share on other sites

Alright, I'm trying to assign an action on a part to a Custom action group and the following code is not doing what I expect.

In order to set my action groups, I need to first make sure the action in question is not assigned to any action groups.

The following code should make sure an action is not assigned to any of the Custom action groups.

However, it is unassigning it from all action groups, so RCS are not enabled when you press the R key, landing gear does not toggle when you hit the G key, etc.

KSPActs[1] = KSPActionGroup.Custom01;
KSPActs[2] = KSPActionGroup.Custom02;
KSPActs[3] = KSPActionGroup.Custom03;
KSPActs[4] = KSPActionGroup.Custom04;
KSPActs[5] = KSPActionGroup.Custom05;
KSPActs[6] = KSPActionGroup.Custom06;
KSPActs[7] = KSPActionGroup.Custom07;
KSPActs[8] = KSPActionGroup.Custom08;
KSPActs[9] = KSPActionGroup.Custom09;
KSPActs[10] = KSPActionGroup.Custom10;


foreach (BaseAction clrAct in partAllActions)
{
for (int i = 1; i <= 10; i = i + 1)
{
clrAct.actionGroup = clrAct.actionGroup &= KSPActs[i]; //actiongrouptest
}
}

This code is supposed to go to each action and clear only Custom1 through Custom10.

An action stores its assigned actions groups in baseaction.actionGroup

.actionGroup is an enum of bools, hence the bitwise &=

I'm pretty sure I've just got my bitwise syntax wrong, but I've spend a couple hours on this and I'm coming up blank.

Anyone have any ideas?

D.

Link to comment
Share on other sites

You are clearing all but custom groups. I think this might be what you want:


var allCustomGroups = KSPActionGroup.Custom01 | KSPActionGroup.Custom02 | KSPActionGroup.Custom03 | ...;
for(...){
ag = ag & ~allCustomGroups;
}

Link to comment
Share on other sites

I'm writing my first mod, and it needs to be able to load and save data (equivalent to a list of structures/objects) from a file. I've noticed a number of mods using ConfigNodes for this, and tried to duplicate what they did. Specifically, I based my code off of RemoteTech2, which has a fairly elegant approach using the ConfigNode.CreateConfigFromObject() and ConfigNode.LoadObjectFromConfig() functions.

The problem? Any attempt to write an object to a ConfigNode leads to an infinite recursion, and eventually a stack overflow.

Here's a minimum example that reproduces the problem:

using System;
using System.Reflection;
using UnityEngine;

[KSPAddon(KSPAddon.Startup.MainMenu, false)]
public class TestDriver : MonoBehaviour {
public void Start() {
StorableObject x = new StorableObject();
Debug.Log("configNodeTest: attempting save");
x.Save();
Debug.Log("configNodeTest: test complete");
}
}

public class StorableObject {
public void Save() {
ConfigNode allData = ConfigNode.CreateConfigFromObject(this);
allData.Save("temp.foo");
Debug.Log("configNodeTest: settings saved");
}

[Persistent] private double foo = 42.0;
}

And here's what the output log looks like:

configNodeTest: attempting save

(Filename: C:/BuildAgent/work/d3d49558e4d408f4/artifacts/StandalonePlayerGenerated/UnityEngineDebug.cpp Line: 53)

StackOverflowException: The requested operation caused a stack overflow.
at ConfigNode.CreateConfigFromObject (System.Object obj, Int32 pass) [0x00000] in <filename unknown>:0

at ConfigNode.CreateConfigFromObject (System.Object obj, Int32 pass) [0x00000] in <filename unknown>:0

at ConfigNode.CreateConfigFromObject (System.Object obj, Int32 pass) [0x00000] in <filename unknown>:0

at ConfigNode.CreateConfigFromObject (System.Object obj, Int32 pass) [0x00000] in <filename unknown>:0

...

There are 2001 lines of this, appropriately enough. :D

But seriously, I feel like I'm missing something basic here. I've seen ConfigNode.CreateConfigFromObject() used in exactly this context before, so why can't I get it to work?

Link to comment
Share on other sites

Use the overloaded version of that method that also takes a ConfigNode. This one just doesn't work and RT2 had the same problem.

...

I Am Not Amused

Thanks for the help, though. It never occurred to me that those two overloads would behave any differently, I assumed they were just there to support different coding styles.

By the way, I've been using Anatid's reference to the KSP API. I knew it was out of date, of course, but this is the first time I've run into an unexpected omission. Is there some more up-to-date documentation somewhere?

Edited by Starstrider42
Link to comment
Share on other sites

Alright, does anyone know of anyway to hook into how Squad selects parts on a vessel in flight that I could just hook into when a player clicks?

Or, what is the best way to select parts in flight? I'm currently using a raycast from the camera position to the mouse position, but this has the issue that animated parts don't always recognize their correct positions (extended solar panels only get selected if you click on the storage box, not the extended panels) and smaller parts seem to sink into larger parts (a thermometer on a large fuel tank can't seem to be selected).

Is there another alternative I've missed? Squad seems to manage this reliably and I'd like to replicate that.

D.

Link to comment
Share on other sites

As I'm not a fan of making threads for every whim that goes through my mind, here's another question from me.

I have this cool idea for a mod - a new building in the Space Center called "The Simulator" wherein you can load any ship and it will find itself floating in empty space; you can then add other ships if desired and use the Simulator to test out your RCS, delta-V, etc.

But I haven't a clue if this is even possible. Is it? Or are buildings, null orbits, or any other core feature a dev-only sort of thing?

Link to comment
Share on other sites

Hi,

Another ConfigNode question, this time something a little more unorthodox. I'm experimenting to see if you can store objects (complete with inheritance information) using a ConfigNode, but so far I've come up empty-handed.

Example:

public class StorableObject {
public void Save() {
ConfigNode allData = new ConfigNode();
ConfigNode.CreateConfigFromObject(this, allData);
allData.Save("temp.foo");
}

[Persistent] private double foo = 42.0;
[Persistent] private IMultirole bar = new SubclassB();
}

public interface IMultirole {}

public class SubclassA : IMultirole {
[Persistent] private int x = 42;
[Persistent] private bool y = false;
[Persistent] private string z = "Goodbye World";
}

public class SubclassB : IMultirole {
[Persistent] private double u = 3.8;
[Persistent] private char v = 'x';
}

Output:

foo = 42
bar
{
u = 3.8
v = x
}

The right data did, technically, get saved to the config file, but there's no machine-readable indication that bar needs to be initialized as an object of SubclassB. Is there a way to set up saving/loading something like this, or should I stick to non-inherited types when messing with ConfigNodes?

Thanks!

Edited by Starstrider42
Link to comment
Share on other sites

Yes, you should stick to simplest possible solution. ConfigNodes are the same... a simple and slow tool to serialize stuff. I bet in the same time you where trying to figure out inheritance you could have written the serialization logic yourself at least three times using nothing but AddNode, GetNode, GetValue & SetValue.

Btw: One somewhat "simpler" way would be to make its own hidden field for each subclass and use a property to return the one that isn't null. But make sure to clear all fields on reload...

Edited by Faark
Link to comment
Share on other sites

Hi, Another ConfigNode question, this time something a little more unorthodox. I'm experimenting to see if you can store objects (complete with inheritance information) using a ConfigNode, but so far I've come up empty-handed

....

As Faark noted it can be complex. I have done it myself for a few things thougfh so feel free to look at the KSPARP Code and this might have some extra info for you - http://forum.kerbalspaceprogram.com/entries/1265-An-Adventure-in-Plugin-Coding-7-Thanks-for-the-Persistence

Link to comment
Share on other sites

Hey all, I'm still pretty new to Unity an C# but have a scripting backgroud, so I'm fumbling my way through this. Anyway, I'm trying to put together a camera shake plug-in that, well... shakes the camera in IVA under various situations. I got the basics working but I've hit a few snags after searching around and was wondering if anyone could help me out. A few things I'm looking for...

  • Is there a way to tell when a decoupler on the vessel has fired / detached and at what force?
  • Maybe related to the above, is there a way to find / list the default events of stock parts? I was thinking I could wait for the default decoupler event (I'm assuming there is one) to fire but I haven't been able to figure out what it is.
  • Is there a way to determine when active engines are out of fuel? Currently my camera shake continues when an active engine is out of fuel but the throttle is up.
  • Is there a way to determine the current thrust of an active engine? I'd like to scale shake based on how hard the engines are currently going, not just the throttle like I'm doing now.
  • Is there a way to determine when a vessel has landed rough and been damaged or parts have fallen off? Currently I'm doing checks against FlightGlobals.ActiveVessel.LandedOrSplashed for a shake when landing, but that doesn't account for harder landings or impacts. Maybe there's a better way to account for terrain or water contact?
  • Currenty my shake alters InternalCamera.Instance.camera.transform.localPosition, but the world outside of the vessel remains static (the shake only affects the camera inside the vessel), is there a way to affect the entire screen while in IVA?

Thanks in advance!

Link to comment
Share on other sites

Hey all, I'm still pretty new to Unity an C# but have a scripting backgroud, so I'm fumbling my way through this. Anyway, I'm trying to put together a camera shake plug-in that, well... shakes the camera in IVA under various situations. I got the basics working but I've hit a few snags after searching around and was wondering if anyone could help me out. A few things I'm looking for...

  • Is there a way to tell when a decoupler on the vessel has fired / detached and at what force?
  • Maybe related to the above, is there a way to find / list the default events of stock parts? I was thinking I could wait for the default decoupler event (I'm assuming there is one) to fire but I haven't been able to figure out what it is.
  • Is there a way to determine when active engines are out of fuel? Currently my camera shake continues when an active engine is out of fuel but the throttle is up.
  • Is there a way to determine the current thrust of an active engine? I'd like to scale shake based on how hard the engines are currently going, not just the throttle like I'm doing now.
  • Is there a way to determine when a vessel has landed rough and been damaged or parts have fallen off? Currently I'm doing checks against FlightGlobals.ActiveVessel.LandedOrSplashed for a shake when landing, but that doesn't account for harder landings or impacts. Maybe there's a better way to account for terrain or water contact?
  • Currenty my shake alters InternalCamera.Instance.camera.transform.localPosition, but the world outside of the vessel remains static (the shake only affects the camera inside the vessel), is there a way to affect the entire screen while in IVA?

Thanks in advance!

Have you tried checking for the acceleration on your ship/part? That could address most of the things on your list (decoupler, both engine issues, touchdown).

Link to comment
Share on other sites

Is there a way to determine when a vessel has landed rough and been damaged or parts have fallen off? Currently I'm doing checks against FlightGlobals.ActiveVessel.LandedOrSplashed for a shake when landing, but that doesn't account for harder landings or impacts. Maybe there's a better way to account for terrain or water contact?

You might try one or more of the onCrash, onCrashSplashdown, or onCollision events in GameEvents. I can't tell you which is most suitable since I've never used any of them but it looks like a place to start

Is there a way to tell when a decoupler on the vessel has fired / detached and at what force?

GameEvents.onStageSeparation should work. You can probably use the parameter you're supplied with to get the ModuleDecouple on the part that fired the event, which has a public ejectionForce value

[*]Is there a way to determine when active engines are out of fuel? Currently my camera shake continues when an active engine is out of fuel but the throttle is up.

[*]Is there a way to determine the current thrust of an active engine? I'd like to scale shake based on how hard the engines are currently going, not just the throttle like I'm doing now.

Finding engine parts and getting the relevant ModuleEngines would probably solve both these issues. At the least, I see some promising possibilities: isOperational, normalizedOutput, normalizedThrustOutput that might do what you want.

And just in case you haven't seen them, I'd like to point out the Vessel.FindPartModuleImplementing<T> and Part.FindModulesImplementing<T> functions which should make your life much easier

Link to comment
Share on other sites

Weird, just discovered that parts with ModuleLandingGear always consider .GroundContact to be false, even when on the runway.

Anyway, I thought about adding more camera sway / movement to the IVA camera mod I made, but I can't seem to figure out how to calculate perceived G forces. I dug around and someone mentioned subtracting the FlightGlobals.getGeeForceAtPosition from the vessel's acceleration, but I don't understand what the vessel's acceleration value is spitting out in the first place. Basically, I want to push the camera using centripetal force / determine the angle the Gees are pushing... has anyone tried anything like this or might know what to look for? I was hoping this was already done in game and I wouldn't have to do a bunch of math to solve it. :P

Link to comment
Share on other sites

It sounds like you want to move the IVA camera position in the opposite direction to the acceleration vector. Should just be a matter of scaling the vector appropriately and subtracting it from the camera position though the acceleration vector may be defined in a different coordinate space (reference frame) to the camera position so you may have to convert/transform the vector first...

Link to comment
Share on other sites

Does anyone here understand how you're supposed to use Unity's TextMesh object? It's supposed to make floating letters in space, but I don't understand it well enough to figure out what I'm doing wrong, and Unity's own documentation gives really terrible examples that never show you how to set anything up (they always assume you've already got everything constructed properly and set up and then only show crude examples with no explanation).

Where I am already is that I have a LineRenderer object called _line.

It renders and appears correctly. I want to make a TextMesh to label the line and I can never get it to show anything on the screen and I don't know why - is it because the coordinates are way off and its off in the distance? Is it because it's too small? Is it because it's transparent on account of having no proper texture? I don't know, and the output_log.txt shows no complaints.

This is, in a nutshell, what I'm trying to do:


// assume _line is already a working LineRenderer at this point:

GameObject _labelObj = new GameObject("Text");

MeshRenderer _labelRend = _labelObj.AddComponent<MeshRenderer>();
TextMesh _labelMesh = _labelRend.AddComponent<TextMesh>();

// Put the text label at the foot of the vector arrow for now: (_line is the LineRenderer):
// I will move it to a better position later after I manage to make it appear at all so I can
// see what I'm doing:
_labelMesh.transform.localPosition = _line.transform.localPosition;

_labelMesh.font = new Font("Arial");
_labelRend.renderer.material = ((Font)Resources.GetBuiltinResource( typeof(Font), "Arial.ttf")).material;

_labelMesh.text = "Some example Text";

_labelRend.rendererer.enabled = true;

_labelRend.color = Color( 1.0, 0.0, 1.0 ); // purple.

This is what I have from piecing together other examples I've found in internet searches. It doesn't work.

Alternately, if you don't know this but you do know of a mod that uses floating letters in space and can tell me the name of it, I might be able to find its source code somewhere like github and have a look myself at what it did.

Link to comment
Share on other sites

Does anyone here understand how you're supposed to use Unity's TextMesh object? It's supposed to make floating letters in space, but I don't understand it well enough to figure out what I'm doing wrong, and Unity's own documentation gives really terrible examples that never show you how to set anything up (they always assume you've already got everything constructed properly and set up and then only show crude examples with no explanation).

My advice would be to ignore it and use a textured plane or GUIText if you want good results. With that said, I don't see where you set the GO's layer anywhere so the MapView camera doesn't render it

testText = new GameObject("testText", typeof(MeshRenderer));
var text = testText.AddComponent<TextMesh>();

Font ArialFont = (Font)Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");

testText.renderer.sharedMaterial = ArialFont.material;
text.font = ArialFont;
text.fontSize = 12;
text.text = "Hello, world!";
text.color = XKCDColors.Amber;

testText.layer = 10;
ScaledSpace.AddScaledSpaceTransform(testText.transform);

8zcjH.jpg

Link to comment
Share on other sites

My advice would be to ignore it and use a textured plane or GUIText if you want good results. With that said, I don't see where you set the GO's layer anywhere so the MapView camera doesn't render it

testText = new GameObject("testText", typeof(MeshRenderer));
var text = testText.AddComponent<TextMesh>();

Font ArialFont = (Font)Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");

testText.renderer.sharedMaterial = ArialFont.material;
text.font = ArialFont;
text.fontSize = 12;
text.text = "Hello, world!";
text.color = XKCDColors.Amber;

testText.layer = 10;
ScaledSpace.AddScaledSpaceTransform(testText.transform);

http://puu.sh/8zcjH.jpg

Thanks. I'll give that a try. As for the GO layer, it's set elsewhere in the update code that checks constantly to see if you're in map mode and if so it changes a few things. It is done eventually, just not there.

I think the important thing I missed was this:

ScaledSpace.AddScaledSpaceTransform(testText.transform);

so it was probably rendering it *somewhere else* other than in front of the camera.

Edited by Steven Mading
Link to comment
Share on other sites

I think the important thing I missed was this:

ScaledSpace.AddScaledSpaceTransform(testText.transform);

so it was probably rendering it *somewhere else* other than in front of the camera.

No, that doesn't affect quite affect position. The text will still appear without it but it'll jitter around

Link to comment
Share on other sites

No, that doesn't affect quite affect position. The text will still appear without it but it'll jitter around

Thanks for all your help. I've almost got it done, with one remaining problem: layers.

If I draw the arrow on layer 10 it shows on the map but not the flight view.

If I draw the arrow on layer 0 it shows up on the flight view but not the map view.

I can flip between these layers by detecting whether or not I'm in map view. That's working fine.

The problem is that layer 0 seems to have a cutoff distance. KSP doesn't want you to display anything more than about 1.5 million meters away on layer 0. Obviously it's able to show stuff farther away than that in some fashion, because the flight camera lets you see the distant Mun from Kerbin orbit, so there's got to be some sort of layer where it allows it. But I don't know which layer it is. I've tried everything from layer 0 to layer 20 and haven't hit one that works yet.

(I was putting my label text on the vector arrow at its midpoint, and then making the scale of the text depend on the distance from the camera, so that when the letters are thousands of kilometers away, they're still visible because they're drawn several kilometers high. that worked great, until I hit this magic cutoff point and the letters just disappear entirely at that distance no matter how big they are.)

What I have there so far is workable, I just have to tell users "If your vectors are really big you'll have to switch to map view to see them properly because they'll just go a limited distance and then get truncated in flight view".

Edited by Steven Mading
Link to comment
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.

×
×
  • Create New...