Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

That's a good question. I can get my PartModule to show in there (along with being able to edit some of the text, which you can apply formatting tags to) by implementing IModuleInfo. ModuleGimbal doesn't seem to do this and somehow still appears in there, so there must be another way as well

Link to comment
Share on other sites

I'm trying to use a KSPParticleEmitter to create ambient effects, but I keep getting this exception every frame:

UnityException: Array needs to contain exactly 5 Colors for colorAnimation.

I've tried every variant of declaring the array I can think of, and this exception keeps happening, no matter what I do. help would be appreciated!

Code:


[KSPAddon(KSPAddon.Startup.Flight, false)]
public class LaytheEffectController : MonoBehaviour
{
public GameObject ParticleObj;
KSPParticleEmitter system;
Texture2D particleTex;
public Vessel AV;


float sporeMaxAltitude = 10000.0f;
float velocityScaleByAlt = 10.0f;
float sizeScaleByAlt = 1.0f;


void Start()
{
ParticleObj = new GameObject ("laytheSpores", typeof(KSPParticleEmitter));
ParticleObj = (GameObject)Instantiate (ParticleObj, this.transform.position, this.transform.rotation);


system = ParticleObj.GetComponent<KSPParticleEmitter> ();


system.angularVelocity = 0f;
system.particleRenderMode = ParticleRenderMode.Billboard;
system.shape = KSPParticleEmitter.EmissionShape.Sphere;
system.shape3D = new Vector3 (100f, 100f, 100f);
system.castShadows = true;
system.damping = 0.9f;
system.color = Color.white;
system.colorAnimation = new Color[]{};
system.colorAnimation [0] = new Color (0, 0, 0, 1.0f);
system.colorAnimation [1] = new Color (0, 0, 0, 0.9f);
system.colorAnimation [2] = new Color (0, 0, 0, 0.8f);
system.colorAnimation [3] = new Color (0, 0, 0, 0.7f);
system.colorAnimation [4] = new Color (0, 0, 0, 0.0f);
system.doesAnimateColor = false;
system.maxEmission = 3;
system.maxEnergy = 20f;
system.minEmission = 0;
system.minEnergy = 5f;
system.useWorldSpace = false;


particleTex = Utils.LoadTexture ("jungle_spore.jpg");
Shader emissiveQuadShader = Utils.LoadShader ("Shaders/Compiled-EmissiveQuad.shader");
var emissiveMaterial = new Material (emissiveQuadShader);
emissiveMaterial.SetColor ("_Color", Utils.Color (133, 189, 37));
emissiveMaterial.SetTexture ("_EmissiveMap", particleTex);


system.material = emissiveMaterial;
system.emit = false;
}


void LateUpdate()
{
AV = FlightGlobals.ActiveVessel;


ParticleObj.transform.position = AV.ReferenceTransform.position;


if (AV.mainBody.bodyName == "Laythe" && AV.altitude < sporeMaxAltitude)
{
if (!system.emit)
system.emit = true;


var altitude = (float)AV.altitude;


//faster particles higher up
system.rndVelocity.x = ((altitude - 0.0f) / (sporeMaxAltitude - 0.0f)) * velocityScaleByAlt;
system.rndVelocity.y = ((altitude - 0.0f) / (sporeMaxAltitude - 0.0f)) * velocityScaleByAlt;
system.rndVelocity.z = ((altitude - 0.0f) / (sporeMaxAltitude - 0.0f)) * velocityScaleByAlt;


//bigger particles lower down
system.maxSize = ((altitude - sporeMaxAltitude) / (0.0f - sporeMaxAltitude)) * sizeScaleByAlt;
system.minSize = ((altitude - sporeMaxAltitude) / (0.0f - sporeMaxAltitude)) * sizeScaleByAlt * 0.25f;
}
else
{
system.emit = false;
}
}
}

Link to comment
Share on other sites

First, from Unity's docs at http://docs.unity3d.com/ScriptReference/ParticleAnimator-colorAnimation.html

Currently you cannot directly modify a single index of this array. Instead, you need to grab the entire array, modify it, and assign it back to the Particle Animator.

So as I read that you have to make the array and then do a system.colorAnimation = previouslyBuiltArray; as the code you linked I would call modifying a single index.

Second, as you instantiate the object with the array existing, can you just do a

foreach (Color clr in system.colorAnimation)
{
print("Color Test: " + clr);
}

before trying to modify it and see what exactly it is expecting?

D.

Link to comment
Share on other sites

Real quick and dumb question. Exactly what is the function RequestResource(string ResourceID, double Demand) returning? I know it's a double, but I don't what that value is. Is it the remaining resource value that the craft has? Or is it something else?

Thank you

Link to comment
Share on other sites

I looked at how RPM gets that description to grab action group label names out of it. It appears that they're grabbing it before they leave the VAB via something like -

string description = EditorLogic.fetch.shipDescriptionField.Text;

I'm not sure if there's a way to grab it in flight. I mean, you COULD read and parse the sfs file... but that seems like a lot of overhead for something that should be available as 'this.vessel.obviousnamefordescriptiontext'.

Link to comment
Share on other sites

I don't think you can.

I just checked the .sfs file, there is no description field for a vessel.

Simplest way would be to add a partModule to every part with a ModuleCommand to save the description through, or if you don't want to do it via partModule, look up all the available .craft files in the editor and pull the description across. This would break if the name of the vessel ever changed however.

D.

Link to comment
Share on other sites

Alright, I have the part.forceActivate() method to my code.

However, it is just running without any checks because I could not find where I check if a part is activated or not. I'm probably just looking right over the value I need in the object browser but could anyone point it out for me?

@smaalle: It does not make it truly indestructible, but if you boost the numbers in the part.cfg file, you can make them significantly stronger so they break almost never.

D.

Link to comment
Share on other sites

Is there something like a mouseover event for parts of the loaded vessel in the editor?

I would like to have something trigger if you mouseover a part while pressing a key. I have tried a workaround but tha did not work out as I intended:


... somewhere in monobehaviour Start()...
GameEvents.onPartAttach.Add( OnPartAttach );

public void OnPartAttach( GameEvents.HostTargetAction<Part, Part> eventData )
{
eventData.host.AddOnMouseEnter(OnMouseEnter);
eventData.host.AddOnMouseExit(OnMouseExit );
}

private void OnMouseEnter( Part p )
{
... fancy stuff
}

private void OnMouseExit( Part p )
{
... more fancy stuff
}

Well, this of course only works if you move the mouse over and off a part - but that is hard to combine with key triggers.

What I basically need is a mouseover event what I can combine with keydown checks. My workaround does not work if you keep the mouse over the part and press the key.

Any help appreciated, thanks ahead,

Fjord

Link to comment
Share on other sites

Can you not just use the mouse enter/exit events to set an internal Part reference (on enter set refPart = p, on exit set refPart = null), and then run w/e you need to in in Update() triggered by the key presses?


Part partRef = null;

... somewhere in monobehaviour Start()...
GameEvents.onPartAttach.Add( OnPartAttach );

public void OnPartAttach( GameEvents.HostTargetAction<Part, Part> eventData )
{
eventData.host.AddOnMouseEnter(OnMouseEnter);
eventData.host.AddOnMouseExit(OnMouseExit );
}

private void OnMouseEnter( Part p )
{
partRef = p;
}

private void OnMouseExit( Part p )
{
partRef = null;
}

private void Update()
{
if ( keyPressed() && refPart != null )
{
// do stuff
}
}

Edited by Crzyrndm
Link to comment
Share on other sites

Can you not just use the mouse enter/exit events to set an internal Part reference (on enter set refPart = p, on exit set refPart = null), and then run w/e you need to in in Update() triggered by the key presses?

Ya, that sounds good, thanks for the hint. :)

A small edit:

I've implemented it the way you suggested, however the saved part object was always null within the Update() call.

It worked once I made the saved part object static, but I am not sure why or where it got lost.

Edited by LordFjord
Link to comment
Share on other sites

if(HighLogic.LoadedScene == GameScenes.MissionControl)
{
//your code here
}

That is what you need, or pretty close. I'm writing that from memory so do a syntax check with the object browser.

Hope that helps,

D.

There isn't an actual GameScene for the space center buildings. Mission Control, R&D Center, Admin, and the Astronaut Complex are just UIs plastered on top of the current scene. I think there are GameEvents that trigger whenever you enter and exit these buildings though, so you can try using those.

Link to comment
Share on other sites

There isn't an actual GameScene for the space center buildings. Mission Control, R&D Center, Admin, and the Astronaut Complex are just UIs plastered on top of the current scene. I think there are GameEvents that trigger whenever you enter and exit these buildings though, so you can try using those.

Really? Oops.

Can you tell I've never dealt with anything but the Editor and Flight scenes? :huh:

D.

Link to comment
Share on other sites

There isn't an actual GameScene for the space center buildings. Mission Control, R&D Center, Admin, and the Astronaut Complex are just UIs plastered on top of the current scene. I think there are GameEvents that trigger whenever you enter and exit these buildings though, so you can try using those.

Thanks, the GameEvents worked, but now I got another question:

Is there a way to insert a new line into a string so when KSP draws the string it jumps to a new line whenever it reaches a certain point.

Maybe some kind of special symbol.

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