Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

I was hoping to add the "M700 Surface Scanner" into [x] Science! but it doesn't seem to be integrated with the rest of the science system.

Does anyone know if there is any chance of the M700 getting a "ModuleScienceExperiment?" If there is then I'll just wait.

Otherwise - on startup I'd need to be able to read a list of bodies that have been scanned.

And during run-time I'd need an even I can hook to know that a scan has happened.

Does anyone know where this stuff would be? I went though "GameEvents" and couldn't see anything. Maybe I'm just being dumb.

The M700 appears in the UI like a science experiment but when you run it it is more like a contract reward. For example - you get 10 points for scanning Kerbin and 10 for Eeloo - no modifiers. Which is fine but as the M700 is in the science-parts-section I feel that [x] Science! should handle it.

Link to comment
Share on other sites

I was hoping to add the "M700 Surface Scanner" into [x] Science! but it doesn't seem to be integrated with the rest of the science system.

The M700, and the science lab, use a different method for transmitting science. They don't record a ScienceSubject, or provide ScienceData, they just give you science points.

If you want to know if a planet has been scanned try:


ResourceMap.Instance.IsPlanetScanned(body.flightGlobalsIndex);

Link to comment
Share on other sites

SOLVED! For anyone else who runs into this, all you need to do is call DoNotDestroy.DontDestroyOnLoad([GameObject]);

I'm rather new to programming in general so this may be some simple issue with fundamentals, but I'm having the following problem:

I'm making a basic flight warning system, using textures and sounds to alert the user to certain conditions (e.g. low fuel, high temperature, etc).

On Start() I load the textures and sound files in separate modules, e.g.

Start()

{

CraftView.LoadTextures()

NoiseMaker.LoadSounds()

}

The textures work fine, but the sound files only work until I either switch to another vessel or leave flight for the VAB/space center/etc. After this any time I try to play a sound file I just get a null reference exception. I gather that I need to reload the sound files again somehow but if I simply call NoiseMaker.LoadSounds() again on scene change I get a game crippling error where the null references go into overdrive and you get the "blue word/semi underground kraken" type visual bug.

Could someone smarter than me shed some light on what it is I don't understand here?

The basic structure of NoiseMaker.LoadSounds is:

sound_one = GameObjectName.AddComponent<AudioSource>();

sound_one.panLevel = 0;

sound_one.clip = GameDatabase.Instance.GetAudioClip("path/to/sound/file");

sound_one.loop = false;

<repeat for other sounds>

Sample log output:

NullReferenceException

at KAWS.NoiseMaker.RefreshSounds () [0x00000] in <filename unknown>:0

Edited by Niven
Link to comment
Share on other sites

@Niven: A null reference is caused by the sound_one object no longer existing after you switch vessels for some reason.

Are you doing this in a PartModule or a KSPAddon? If it's in a partModule, that is tied to that vessel which may explain what is happening.

The other thing I note is that you say the error is in .RefreshSounds, but there is no other reference to that method in your post so there really isn't enough detail to help you out here.

D.

Link to comment
Share on other sites

I've searched and searched but can't find what I am looking for.

Does anyone know or point me to how I can run an animation in IVA or internal camera view? (not a RPM prop).

Can I assign animations to an internal model mu file and actually run them when in IVA mode or external camera view?

Link to comment
Share on other sites

The problem: pqs co-ordinate settings are in meters. World co-ordinates aren't. I need to convert the latter to the former.

The example: I have a fence with a point on it that I want to connect to another fence with a point on it. I know the world co-ordinates of both fences. I know the relation between the point on a fence and its origin. I know the distance between the points. In order to move one point to the other I have to change the pqs co-ordinates of the first fence. Whilst I can calculate the offset vector as world co-ordinates, I need to convert that to an offset applied to the pqs co-ordinates.

			snapPointRelation = selectedSnapPoint.transform.localPosition;
snapPoint2Relation = selectedSnapPoint2.transform.localPosition;

snapVector = snapPoint2Relation - snapPointRelation;
snapTargetPos = (Vector3)snapTargetInstance.getSetting("RadialPosition") + snapVector;

Doesn't work because snapVector isn't meters.

Link to comment
Share on other sites

pqs co-ordinates.

It's a direction, then. You need to turn that direction into a location, add your offset and then come up with a new direction. I don't know what your snap points represent. If one of them is the localPosition of a PQSCity already on the body, you merely need to add your offset to that and then normalize to come up with a direction.

b219a94333.png


public class PqsFence : MonoBehaviour
{
private GameObject _postPrefab;
private GameObject _fenceSegment;

private IEnumerator Start()
{
yield return new WaitForSeconds(1f);

var cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder); // 2 units high, 1 in diameter
cylinder.transform.localScale = new Vector3(0.1f, 1f, 0.1f); // make it skinny: 2 units high, 0.1 in diameter

_postPrefab = new GameObject("FencePost");
cylinder.transform.parent = _postPrefab.transform;
cylinder.transform.localPosition = new Vector3(0f, 2f * cylinder.transform.localScale.y*0.5f, 0f); // make the bottom of the fence post the point we're manipulating
_postPrefab.SetLayerRecursive(15);
_postPrefab.SetActive(false);


var rectangleSegment = GameObject.CreatePrimitive(PrimitiveType.Cube); // 1x1x1

// make it skinny and extend four meters along +-x direction
rectangleSegment.transform.localScale = new Vector3(4f, 0.1f, 0.1f);

var segments = new[] {rectangleSegment, (GameObject) Instantiate(rectangleSegment)};

_fenceSegment = new GameObject("FenceSegment");

// the top of the fence post is at y=2, so let's place the segments at y=1.8 and y = 0.8
for (int i = 0; i < 2; ++i)
{
segments[i].transform.parent = _fenceSegment.transform;
segments[i].transform.localPosition = new Vector3(0f, 1.8f - i, 0f);
}

_fenceSegment.SetLayerRecursive(15);
_fenceSegment.SetActive(false);


var post = CreatePqsObject(_postPrefab, Vector3.up, Color.red); // place a fence post at the north pole
CreatePqsObject(_fenceSegment, Vector3.up, Color.blue);

for (int i = 0; i < 30; ++i)
{
// easy way: assuming one of your snap points is the position of an object already created
// and positioned:
//var radial = (post.transform.localPosition + new Vector3(4f, 0f, 0f)).normalized;

// slightly less easy: convert radial direction into a world position, then add offset and normalize
// to come up with radial vector
var radial =
((Vector3d) post.repositionRadial*(post.sphere.radius + post.repositionRadiusOffset) +
new Vector3(4f, 0f, 0f)).normalized;

post = CreatePqsObject(_postPrefab, radial, Color.black);
CreatePqsObject(_fenceSegment, radial, Color.green);
}
}


private PQSCity CreatePqsObject(GameObject prefab, Vector3 radial, Color color)
{
var item = (GameObject)Instantiate(prefab);
var pqsCity = item.AddComponent<PQSCity>();


pqsCity.repositionRadial = radial;
pqsCity.repositionToSphereSurface = true;
pqsCity.repositionToSphereSurfaceAddHeight = true;

pqsCity.lod = new[] { new PQSCity.LODRange
{
renderers = item.GetComponentsInChildren<Renderer>().Select(r => r.gameObject).ToArray(),
objects = new []{ item },
visibleRange = 25000f
}};
pqsCity.lod[0].Setup();

// borrowed from KerbalKonstructs
pqsCity.frameDelta = 1;
pqsCity.reorientToSphere = true;
item.gameObject.transform.parent = FlightGlobals.GetHomeBody().transform;
pqsCity.sphere = FlightGlobals.GetHomeBody().pqsController;
pqsCity.order = 100;
pqsCity.modEnabled = true;
pqsCity.OnSetup();
pqsCity.Orientate();
item.SetActive(true);

item.GetComponentsInChildren<Renderer>().ToList().ForEach(r => r.material.color = color);

print("Created new object at " + pqsCity.transform.localPosition);

return pqsCity;
}
}
[KSPAddon(KSPAddon.Startup.Flight, false)]

Link to comment
Share on other sites

        pqsCity.repositionToSphereSurface = true;
pqsCity.repositionToSphereSurfaceAddHeight = true;

That's the issue there. Applying your solution still results in the same 'drift' I was trying to fix. But the above accounts for the curve of the sphere, which KK doesn't by default. Blargh KerbTown legacy.

Thanks for the help sir.

Edited by AlphaAsh
Link to comment
Share on other sites

Vessel Modules. What stock ones are there (other than FlightIntegrator), what should they be used for, and how do you access them (there isn't a public list in the vessel class for them)?

From a quick experiment they get created automatically on flight start (and I'm assuming whenever another vessel is created). If there is an instance per loaded vessel that would be really useful for several things I'm working on, except neither the vessel or the vessel module have a public reference to the other so I'm not sure of the best way to link up (or even if using VesselModule is a good idea).

Link to comment
Share on other sites

As far as I can tell, FlightIntegrator is the only class that currently inherits VesselModule.

And I also agree that any class that inherits VesselModule will get added to the vessel, but it looks like they are using the GameObject hierachy to do so.

So you need to figure out the syntax for "Get all child objects of type VesselModule from parent object(vessel)" which I think is straightfoward, but not something I've ever done.

Hope that helps,

D.

Link to comment
Share on other sites

So you need to figure out the syntax for "Get all child objects of type VesselModule from parent object(vessel)" which I think is straightfoward, but not something I've ever done.

Puttering around in MFI and FAR solved that one

Vessel v = GetComponent<Vessel>(); // from a vessel module
VesselModule vm = vessel.GetComponent<VesselModule>(); // from the vessel reference

Very handy class to have, already wishing I'd investigated this about a month ago >.<

Link to comment
Share on other sites

Ya, I'm looking into it now, would make a lot of things easier for me also.

One thing though, the above code only returns the first VesselModule on a Vessel, you'll want to use VesselModule[] vm = GetComponents<VesselModule>(); (needs a syntax check) to return an array of all VesselModules on a vessel.

D.

Link to comment
Share on other sites

One thing though, the above code only returns the first VesselModule on a Vessel, you'll want to use VesselModule[] vm = GetComponents<VesselModule>(); (needs a syntax check) to return an array of all VesselModules on a vessel.

The assumption there was you'd replace VesselModule with your derived class (of which there will only be one per vessel). A list of vesselModules isn't all that useful, but getting the one I need is :P

Yeah, VesselModules are great. I'm writing ullage (for RF) that way, saves a bunch of computation or dealing with statics.

Would I be correct in saying they only get added to non-debris vessels? I'm not always seeing enough instances to cover every single vessel that I'm launching (or don't think I am atleast, I could just be miscounting)

On another note, is there a way to force an engine into a flameout state (or equivalent) without depriving it of a propellant? (E: nvm, careful use of EngineIgnited should do the trick)

Edited by Crzyrndm
Link to comment
Share on other sites

The assumption there was you'd replace VesselModule with your derived class (of which there will only be one per vessel). A list of vesselModules isn't all that useful, but getting the one I need is :P

I will admit that I only did a quick 5 minute test yesterday, but it looked to me like each Class of type VesselModule, so including those classes that inherit it, was attached to each vessel.

Wait....

In C# terms, does GetComponent check using the TypeOf logic, so the exact class is returned (GetComponent<PartModule> returns only PartModule), or the "typeA is typeB" logic which returns all classes of that type and that inherit that type (GetComponent<PartModule> returns all partModule classes such as ModuleCommand)?

I don't know what the correct terms are in programming speak, but that would need to be tested.

D.

Edited by Diazo
Link to comment
Share on other sites

In C# terms, does GetComponent check using the TypeOf logic, so the exact class is returned (GetComponent<PartModule> returns only PartModule), or the "typeA is typeB" logic which returns all classes of that type and that inherit that type (GetComponent<PartModule> returns all partModule classes such as ModuleCommand)?

GetComponents<BaseClass>() will return all objects of type BaseClass and all those that derive from it. This is true for everything in C#, not something unity specific, derived classes can always be cast back to their base class (I've mostly seen it used for storing multiple different types together eg. part.PartModules)

EDIT

Note that you can't use an interface for the GetComponent type so if you're searching for an interface you will need GetComponents.

eg.

CustomInterface CI = vessel.GetComponents<VesselModule>().FirstOrDefault(vm => (vm as CustomInterface) != null) as CustomInterface;

Edited by Crzyrndm
Link to comment
Share on other sites

Hey ! :D

I have a little question : i have made a custom parachute for my new asset, i pasted all the cfg files from le Mk1 parachute in my asset CFG, my part is in game and when i right click on it i have the parachute options but it doesn't show in my stages so i can't activate it when in a mission. Do i need to link a script into it in Unity ?

Edit : it is working now in stage, but i have another problem >< when i activate it, my FPS drops a bit and the chute itself move a bit (http://puu.sh/iB60j/f508876c5c.jpg we can see it's not in the center of the base)

Edited by Beluwel
Link to comment
Share on other sites

How can I find out what ExperimentSituation a vessel is in?

ScienceUtil.GetExperimentSituation(vessel);

Or you can do it manually based on where the vessel is, but the first option is simpler.

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...