Cephei

The official unoffical "help a fellow plugin developer" thread

Recommended Posts

11 minutes ago, severedsolo said:

So, I'm writing my first mod, and my C# knowledge is.. shaky to say the least, so bear with me.

What I am basically trying to do, is set it so that when a player returns to the Space Centre, if it detects more Dead crew members than it did last time, it takes some rep away from the player. I know I could set up an Event Handler in the flight scene for this, but so far, everything it needs to do happens in the space centre, so I'd like to keep it that way if at all possible.

I know the code works, because when I load up to the Space Centre from the main menu, the rep is deducted properly. However, when returning to the Space Centre, the rep isn't deducted but the number of dead Kerbals is updated (and outputted to the text file where I'm storing this stuff at the moment).

I'm guessing what is happening is that the game is calling the first Update() before it's loaded the crew list, so it's not finding them. What's weird though is the number of dead Kerbals is being updated properly (which I wouldn't expect to happen if it hadn't finished loading, and it would pick it up on the next pass). Thinking this was my problem, I tried using WaitForSeconds to make sure everything had loaded, but no joy.

This is the relevant bits of my code (apologies for the terrible forum formatting) - I've pruned some bits from Budget() which are working fine, and not relevant to the problem:

So I guess I have two questions:

1) What am I doing wrong? Why is it only doing it on a new save load and not a scene change? It's probably a really obvious rookie mistake.

2) Is there a better way of doing this?

 

Bit hard to tell with just that snippit.
But you seem to be over-doing it. And I think a GameEvent is exactly what you want.
All you need is a MonoBehaviour class using KSPAddOn to have it start at MainMenu (or SpaceCenter) scene. Tell Unity not to destroy it between scenes.
Register for the GameEvent.onCrewKilled  and then put your code in that method.
so it would look something like this:
 

[KSPAddon(KSPAddon.Startup.SpaceCentre, true)]
public class DeadKerbalPenaliser : MonoBehaviour
{
   public void Awake()
   {
       DontDestroyOnLoad(this);
	   GameEvents.onCrewKilled.Add(onCrewKilled);
   }
    
   public void OnDestroy()
   {
        GameEvents.onCrewKilled.Remove(onCrewKilled);
   }

   public void onCrewKilled(EventData<EventReport> evtdata)
   {
        // Put your code in here.
        // evtdata.sender will contain the Name of the kerbal that just died.
   }
}

   

 

Edited by JPLRepo
  • Like 1

Share this post


Link to post
Share on other sites

Since some variable need to be saved/loaded with the save I would use a KSPScenario  instead but it works that same.

  • Like 2

Share this post


Link to post
Share on other sites

Thanks @JPLRepo that worked perfectly. Had to fiddle a little bit with the EventReport to get it to work, but Visual Studio told me how to fix that.

Share this post


Link to post
Share on other sites
1 minute ago, severedsolo said:

Thanks @JPLRepo that worked perfectly. Had to fiddle a little bit with the EventReport to get it to work, but Visual Studio told me how to fix that.

NP. As sarbian said. If you want to persist any data in the save file though, change it to use a KSPScenario then you can use OnLoad and OnSave for that.

Share this post


Link to post
Share on other sites
15 hours ago, JPLRepo said:
On 8/29/2016 at 1:30 PM, ShotgunNinja said:

I was wondering if somebody know how to extend the maximum zoom allowed in tracking view and map mode.

You could try CameraManager.GetCurrentCamera() and manipulate the near/far clipping panes and the field of view.

Thanks, I found a solution. Writing here as it may be helpful to others. The max camera distance is stored in PlanetariumCamera.fetch.maxDistance, and the zoom speed in PlanetariumCamera.fetch.zoomScaleFactor. Is possible to set an arbitrarily high max camera distance, but at some point the background cubemap start to flicker.

Share this post


Link to post
Share on other sites

I am trying to set a vessel's situation back to what it previously was,  I am tracking this in a variable and can see in debug the values are stored correctly. Issue is when I restore the state from LANDED back to SPLASHED the very next OnFixedUpdate() on a *Different* part module resets this back to LANDED.  I was stepping through the debug with F11 and watched the values flip. 

You can see the full code here
Sample Code

 [KSPField(isPersistant = true, guiActive = false)]
  Vessel.Situations previousState;

private void RememberPreviousState()
	{
     if (!Parked & vessel.situation != Vessel.Situations.LANDED)
   		{
     	previousState = vessel.situation;                           
   		}	        
}

private void RestoreVesselState()
    {
      vessel.situation = previousState;
    }

Is there some other way to set the vessel situation that is persistent?

Edited by gomker
grammer

Share this post


Link to post
Share on other sites

@gomker Without actually moving the vessel to an area that would match that situation? I don't think you can do anything about that, the vessel itself is setting that value, not any part module.

Share this post


Link to post
Share on other sites

@DMagic that would seem to be the case from what I observe in debug.  I am very new to KSP API and am just now learning what everything does. The original mod was designed to Park AirShips , I am improving the code to better handle large boats in the water as they tend to launch into space from the water on physics reload (the only other fix is to use FAR, whish is not something most users want to do if they are just designing boats)

What is interesting is that you can switch from SPLASHED to LANDED without issue and this will be persistent. You can even "Park" a flying vessel in the Air and it hangs there suspended in the air.

private void ParkVessel()
{
            RememberPreviousState();
			ParkPosition = vessel.GetWorldPos3D();
			ParkVelocity = vessel.GetSrfVelocity();
            setVesselStill();
            vessel.SetPosition(ParkPosition);
            vessel.situation = Vessel.Situations.LANDED;
            vessel.Landed = true;
    			
}

Going back to SPLASHED , even if the vessel is touching water , will flip back to LANDED

Edited by gomker
mention fix

Share this post


Link to post
Share on other sites

@DMagic  I love how talking it out sometimes solves the problem. I had a duh moment looking at the code I pasted and realized something.

 vessel.Landed = true was being set however, not back to false.   

           vessel.situation = previousState;
            if (vessel.situation != Vessel.Situations.LANDED) { vessel.Landed = false; }

This fixed it.

Thanks

Share this post


Link to post
Share on other sites

Does anyone know anything about how planets are drawn in the map view? I wondered what it would take to draw also their SOI, either as an alpha-ed sphere or a 'point cloud' on it's surface.

Share this post


Link to post
Share on other sites

Hi,

I'm trying to render something in-flight like a slightly transparent half-sphere, to be used like a checkpoint nearby the player vessel. I've got longitude/latitude via

FlightGlobals.ActiveVessel.latitude
FlightGlobals.ActiveVessel.longitude

and am generating latitude/longitude positions nearby that I'd like to render the half-sphere on. Can anyone teach me / point me in the right way on how to accomplish this? I have almost no knowledge with how to render stuff in-flight, and would appreciate any guidance. Cheers!

Edited by theSpeare

Share this post


Link to post
Share on other sites
9 hours ago, theSpeare said:

Hi,

I'm trying to render something in-flight like a slightly transparent half-sphere, to be used like a checkpoint nearby the player vessel. I've got longitude/latitude via


FlightGlobals.ActiveVessel.latitude
FlightGlobals.ActiveVessel.longitude

and am generating latitude/longitude positions nearby that I'd like to render the half-sphere on. Can anyone teach me / point me in the right way on how to accomplish this? I have almost no knowledge with how to render stuff in-flight, and would appreciate any guidance. Cheers!

You could potentially Instantiate one of Unity's primitives (Sphere, for example) to do this; you'd also need to convert the latitude and longitude to Vector3 coordinates.

EDIT: Have a look at this comment, and its quote.

Looking at that, it might be possible to use PartLoader to add a custom part (of your own choosing) to said new vessel, and work from there.

Also, have a look here:

 

Edited by udk_lethal_d0se
Added further info.

Share this post


Link to post
Share on other sites

Cheers. I got the script working on the 2nd link you posted, trying to do some classic trial-and-error tinkering to learn more about how everything works. Instantiating a primitive sphere works, however it has its default attributes, such as a collider (which I don't want, as I'd like to use it more as a waypoint). I'm messing around with some of the components to see if I can make any sense out of it.

Thanks for the help!'

EDIT: Wonderful! I managed to disable the SphereCollider component in the GameObject. Now to fiddle with material to get it transparent; new to this rendering stuff so this wil ltake awhile

Edited by theSpeare

Share this post


Link to post
Share on other sites
2 minutes ago, theSpeare said:

Cheers. I got the script working on the 2nd link you posted, trying to do some classic trial-and-error tinkering to learn more about how everything works. Instantiating a primitive sphere works, however it has its default attributes, such as a collider (which I don't want, as I'd like to use it more as a waypoint). I'm messing around with some of the components to see if I can make any sense out of it.

Thanks for the help!

The collider can be easily removed with the following:

Destroy(gameObject.GetComponent("ComponentName"));

Where gameObject is reference of the instantiated object.

Edited by udk_lethal_d0se

Share this post


Link to post
Share on other sites

Is there much difference between that and

sphere.GetComponent<SphereCollider>().enabled = false;

Should I just destroy it for cleanliness since I'm not using it anyway?

Share this post


Link to post
Share on other sites
1 minute ago, theSpeare said:

Is there much difference between that and


sphere.GetComponent<SphereCollider>().enabled = false;

Should I just destroy it for cleanliness since I'm not using it anyway?

Not really, just as common sense dictates. Disabling it will keep it on the gameObject, whereas Destroying it removes it completely.

If you don't need a collider, I'd just destroy it.

Edited by udk_lethal_d0se

Share this post


Link to post
Share on other sites

Cheers. One last question, how would I go about converting my longitude/latitude values to something my transform.position can use?

Share this post


Link to post
Share on other sites
2 minutes ago, theSpeare said:

Cheers. One last question, how would I go about converting my longitude/latitude values to something my transform.position can use?

No problem.

That's something I've not played about with so I'm unsure of, though looking through the code on the second link I gave you, I found the following:

gameObject.transform.position = FlightGlobals.ActiveVessel.GetWorldPos3D();

So give that a go.

Edited by udk_lethal_d0se

Share this post


Link to post
Share on other sites

On that thread the poster explained that GetWorldPos3D is a position related to the sun, whereas I just need to render in-flight. I have arbitrary longitude latitude values (that I have generated some distance away from the vessel). I'd like to set the sphere transform position onto those longitude/latitude values. Is there something like getLocalCoordinates(longitude, latitude);

Share this post


Link to post
Share on other sites
1 minute ago, theSpeare said:

On that thread the poster explained that GetWorldPos3D is a position related to the sun, whereas I just need to render in-flight. I have arbitrary longitude latitude values (that I have generated some distance away from the vessel). I'd like to set the sphere transform position onto those longitude/latitude values. Is there something like getLocalCoordinates(longitude, latitude);

Apologies, I didn't see that, have you tried:

vessel.transform.position

Scrap that, I've re-read your response. I gather you're wanting to spawn the object away from the vessel in flight rather than at its position?

Edited by udk_lethal_d0se

Share this post


Link to post
Share on other sites

Affirmative. I have a random "spot" generate somewhere near and around the vessel that the player needs to drive to. The spot will be marked by a big, transparent half-sphere. I have the "spot" location defined by longitude latitude values, like vessel.longitude and vessel.latitude.

Share this post


Link to post
Share on other sites
Just now, theSpeare said:

Affirmative. I have a random "spot" generate somewhere near and around the vessel that the player needs to drive to. The spot will be marked by a big, transparent half-sphere. I have the "spot" location defined by longitude latitude values, like vessel.longitude and vessel.latitude.

Gotcha, found this on another thread whilst doing a bit of research for you; not sure if it's what you're after.

v.mainBody.GetWorldSurfacePosition(lat,long,alt);

 

Share this post


Link to post
Share on other sites

Absolutely beautiful. Thank you so much for your help! I was searching for the wrong thing (facepalm). Now to experiment with MeshRenderer. Best wishes, friend.

  • Like 1

Share this post


Link to post
Share on other sites
51 minutes ago, theSpeare said:

Absolutely beautiful. Thank you so much for your help! I was searching for the wrong thing (facepalm). Now to experiment with MeshRenderer. Best wishes, friend.

Glad I could help.  Some other things you could do (with MeshRenderer, ironically) to save creation and load of a external texture for your waypoint/marker is create a texture and material in your script then assign them during runtime.

All the best.

Edited by udk_lethal_d0se

Share this post


Link to post
Share on other sites

Hi guys, got a couple Qs about file I/O. 
Is there a method that returns the root path of the KSP instance the plugin is running in, or what's the best way to locate and read a file (ie a config file) in the mod's folder?  
Is there a standard way of detecting OS and handling OS specific file paths?
Thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now