Cephei

The official unoffical "help a fellow plugin developer" thread

Recommended Posts

3 minutes ago, Deus Zed Machina said:

Visual Studio Community 2017 ver. 15.2 (26430.12) Release

Let's check if you have the proper component then. In your start menu you should have a "Visual Studio Installer". Launch it and press the Modify button in the "Visual Studio Community 2017" section.  In the new windows make sure ".NET desktop development" is checked, and then do in the "Individual components" tab and make sure you have ".NET Framework 3.5 development tools" checked (2 line for me). Then press close. It should add what was missing.

NL3OZP5.png

 

Launch VS, open your solution and check your project config (Project menu, last item  : "xxxxx properties"). Go in the application tab and set it up like that : 

f5xBHym.png

 

 

 

 

 

Share this post


Link to post
Share on other sites
2 hours ago, sarbian said:

Let's check if you have the proper component then. In your start menu you should have a "Visual Studio Installer". Launch it and press the Modify button in the "Visual Studio Community 2017" section.  In the new windows make sure ".NET desktop development" is checked, and then do in the "Individual components" tab and make sure you have ".NET Framework 3.5 development tools" checked (2 line for me). Then press close. It should add what was missing.

[etc.]

I installed the .NET 3.5 tools, but when I open my project's properties, I don't have an "application" tab. Is there some other component I might be missing?

EDIT: I figured it out. I'm using the wrong kind of class library. Whoops :P Now it works just fine!

Edited by Deus Zed Machina

Share this post


Link to post
Share on other sites

Hey. I need help doing the dirty job of killing kerbals. Using ProtoCrewMember.Die() when in the flight scene causes an NRE and doesn't remove the portrait in flight scene, so I've been using this code (PCM is an instance of ProtoCrewMember):

if (PCM.seat != null) PCM.seat.part.RemoveCrewmember(PCM);
PCM.rosterStatus = ProtoCrewMember.RosterStatus.Dead;

However, this doesn't always work well. Sometimes, I have a portrait replaced with white noise; sometimes I still get the NRE or the kerbal even survives. I haven't been able to understand why it has different outcomes (maybe it has something to do with the game's FixedUpdate() cycle or with timewarp). In any case, the deceased kerbals disappear from the roster and are not seen in the Lost tab.

So, how do you kill your kerbals?

Share this post


Link to post
Share on other sites

I have two problems that are basic KSP functions that I can't seem to get to work.

I am trying to load a .cfg node into my script. I have a "SavedValues.cfg" in the root gamedata folder that looks like this.

VALUES{
	pitchP = 10;
	pitchI = 10;
	pitchD = 10;
}

Then I access it from my script, but it throws a null reference exception.

 public void Awake()
        {
            ConfigNode savedValues = ConfigNode.Load("GameData/SavedValues.cfg");
            savedValues = savedValues.GetNode("VALUES");
            pitchPValue = float.Parse(savedValues.GetValue("pitchP"));
            //pitchIValue = float.Parse(savedValues.GetValue("pitchI"));
            //pitchDValue = float.Parse(savedValues.GetValue("pitchD"));
        }

It seems pretty straight forward but I can't seem to figure out why its not working.  Additionally I can't get this to work either. Any help on either of these would be very much appreciated.

GamePersistence.LoadGame("quicksave.sfs", "default", false, true);

 

Share this post


Link to post
Share on other sites
15 hours ago, clown_baby said:

I have two problems that are basic KSP functions that I can't seem to get to work.

I am trying to load a .cfg node into my script. I have a "SavedValues.cfg" in the root gamedata folder that looks like this.


VALUES{
	pitchP = 10;
	pitchI = 10;
	pitchD = 10;
}

Then I access it from my script, but it throws a null reference exception.


 public void Awake()
        {
            ConfigNode savedValues = ConfigNode.Load("GameData/SavedValues.cfg");
            savedValues = savedValues.GetNode("VALUES");
            pitchPValue = float.Parse(savedValues.GetValue("pitchP"));
            //pitchIValue = float.Parse(savedValues.GetValue("pitchI"));
            //pitchDValue = float.Parse(savedValues.GetValue("pitchD"));
        }

It seems pretty straight forward but I can't seem to figure out why its not working.  Additionally I can't get this to work either. Any help on either of these would be very much appreciated.


GamePersistence.LoadGame("quicksave.sfs", "default", false, true);

 

How about removing the semicolons from the config file?

  • Like 1

Share this post


Link to post
Share on other sites

I think ConfigNode.Load requires the absolute file location, not the KSP relative location. 

  • Like 1

Share this post


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

How about removing the semicolons from the config file?

I have tried that as well, then dropping the( savedValues = savedValues.GetNode("VALUES"); ) and getting the root node. no luck though

 

4 hours ago, DMagic said:

I think ConfigNode.Load requires the absolute file location, not the KSP relative location. 

I'll give that a shot, but how would that work if it were to be released as a mod? Everyone would have to put their own file path from wherever the folder is stored on the drive

Share this post


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

I'll give that a shot, but how would that work if it were to be released as a mod? Everyone would have to put their own file path from wherever the folder is stored on the drive

One common strategy is to look up the path to the mod's DLL.

  • Like 1

Share this post


Link to post
Share on other sites
On 6/8/2017 at 4:50 AM, garwel said:

Hey. I need help doing the dirty job of killing kerbals. Using ProtoCrewMember.Die() when in the flight scene causes an NRE and doesn't remove the portrait in flight scene, so I've been using this code (PCM is an instance of ProtoCrewMember):


if (PCM.seat != null) PCM.seat.part.RemoveCrewmember(PCM);
PCM.rosterStatus = ProtoCrewMember.RosterStatus.Dead;

However, this doesn't always work well. Sometimes, I have a portrait replaced with white noise; sometimes I still get the NRE or the kerbal even survives. I haven't been able to understand why it has different outcomes (maybe it has something to do with the game's FixedUpdate() cycle or with timewarp). In any case, the deceased kerbals disappear from the roster and are not seen in the Lost tab.

So, how do you kill your kerbals?

PCM.UnregisterExperienceTraits(part);
PCM.Die();
Vessel.CrewWasModified(vessel);
                
If you intend them to respawn as per game settings. Check HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn
and then call PCM.StartRespawnPeriod()

Where PCM is the instance of the ProtoCrewMember and vessel is the Vessel they are in and part is the Part they are in.

For crew that die it is stock intended their portrait becomes static. If you don't want this then you can call a refresh
on the KerbalPortraitGallery.Instance.StartRefresh(vessel).

 

Of course this all assumes they are in the ActiveVessel.
If you are still getting NREs please supply more info on the NRE.

  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, clown_baby said:

I'll give that a shot, but how would that work if it were to be released as a mod? Everyone would have to put their own file path from wherever the folder is stored on the drive

KSPUtil.ApplicationRootPath + "/GameData"

 

Share this post


Link to post
Share on other sites
17 hours ago, JPLRepo said:

PCM.UnregisterExperienceTraits(part);
PCM.Die();
Vessel.CrewWasModified(vessel);
                
If you intend them to respawn as per game settings. Check HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn
and then call PCM.StartRespawnPeriod()

Where PCM is the instance of the ProtoCrewMember and vessel is the Vessel they are in and part is the Part they are in.

For crew that die it is stock intended their portrait becomes static. If you don't want this then you can call a refresh
on the KerbalPortraitGallery.Instance.StartRefresh(vessel).

 

Of course this all assumes they are in the ActiveVessel.
If you are still getting NREs please supply more info on the NRE.

Thanks, will try this. The problem is, it also has to happen to unloaded kerbals (including from KSC and Tracking Station scenes). This is where I had most problems.

Edited by garwel

Share this post


Link to post
Share on other sites

I'm sorry to keep nagging about this but I just can't get it to work.

On 6/10/2017 at 8:38 AM, DMagic said:

I think ConfigNode.Load requires the absolute file location, not the KSP relative location. 

I tried just hard coding the full address into  ConfigNode.Load() but still no luck. I don't get a null ref exception on the  savedValues =ConfigNode.Load() call, but as soon as I try to access anything via savedValues one gets thrown.

17 hours ago, sarbian said:

KSPUtil.ApplicationRootPath + "/GameData"

 

This returns the KSP_Data folder path

Share this post


Link to post
Share on other sites

@clown_baby This is how I've always done it and it works for me: https://github.com/DMagic1/KSP_Better_Maneuvering/blob/master/Source/BetterManeuvering/ManeuverPersistence.cs#L91

I'm no sure if all of that Path.Combine, Path.DirectoryName stuff is actually needed (or converting the \ to /), but it works, so I've just used the same method every time.

Share this post


Link to post
Share on other sites
21 hours ago, JPLRepo said:

PCM.UnregisterExperienceTraits(part);
PCM.Die();
Vessel.CrewWasModified(vessel);
                
If you intend them to respawn as per game settings. Check HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn
and then call PCM.StartRespawnPeriod()

Where PCM is the instance of the ProtoCrewMember and vessel is the Vessel they are in and part is the Part they are in.

This code appears to work for a kerbal on board ActiveVessel. But when I try it on a kerbal on EVA (I skip the first line because part is null) while being focused on a nearby vessel, he doesn't disappear or anything. Trying then to switch to that kerbal causes an NRE:

NullReferenceException: Object reference not set to an instance of an object
  at KerbalRoster.ValidateAssignments (.Game st) [0x00000] in <filename unknown>:0 
  at Game.Updated () [0x00000] in <filename unknown>:0 
  at GamePersistence.SaveGame (System.String saveFileName, System.String saveFolder, SaveMode saveMode) [0x00000] in <filename unknown>:0 
  at KSP.UI.Screens.AltimeterSliderButtons.returnToSpaceCenter () [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.UnityEvent.Invoke () [0x00000] in <filename unknown>:0 
  at UnityEngine.UI.Button.Press () [0x00000] in <filename unknown>:0 
  at UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) [0x00000] in <filename unknown>:0 
  at UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) [0x00000] in <filename unknown>:0 
  at UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) [0x00000] in <filename unknown>:0 
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMousePress(MouseButtonEventData)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent(Int32)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent()
UnityEngine.EventSystems.StandaloneInputModule:Process()
UnityEngine.EventSystems.EventSystem:Update()

 

Share this post


Link to post
Share on other sites
21 hours ago, DMagic said:

@clown_baby This is how I've always done it and it works for me: https://github.com/DMagic1/KSP_Better_Maneuvering/blob/master/Source/BetterManeuvering/ManeuverPersistence.cs#L91

I'm no sure if all of that Path.Combine, Path.DirectoryName stuff is actually needed (or converting the \ to /), but it works, so I've just used the same method every time.

So I have tried this and every other way to get the correct path as a string. I'm starting to think that isn't the problem however. If the path were wrong I assume I would get a null ref exception when i use:

fullPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "SavedValues.cfg").Replace("\\", "/");
ConfigNode savedValues = ConfigNode.Load(fullPath);

But I don't. I'm starting to think I am just accessing the node incorrectly. So again here is my .cfg file.

VALUES
{
	pitchP = 10;
	pitchI = 10;
	pitchD = 10;
}

So i get the root node of the cfg using the code above, then get the VALUES node with this, which is when the first null ref gets thrown.

 if (savedValues.HasNode("VALUES"))
{
	savedValues = savedValues.GetNode("VALUES");
}

Then I should be able to access the values in the node via.

pitchIValue = float.Parse(savedValues.GetValue("pitchI"));

Is this not the correct way to get info from the nodes?

Share this post


Link to post
Share on other sites
14 minutes ago, clown_baby said:

So again here is my .cfg file.

And you still have ";" at the end of your lines. It is not a C# file.

Share this post


Link to post
Share on other sites
On 6/10/2017 at 3:39 AM, garwel said:

How about removing the semicolons from the config file?

 

2 minutes ago, sarbian said:

And you still have ";" at the end of your lines. It is not a C# file.

Oh sorry I totally missed that suggestion the first time. Doesnt fix the problem though

Share this post


Link to post
Share on other sites

So I actually fixed it. I copied an existing cfg file and changed the name/values which got it to load.  When I created my "SavedValues.cfg" I must have saved it as a text file.  I knew it was something stupid I did.

Thanks for the help everyone.

Edited by clown_baby

Share this post


Link to post
Share on other sites
On 6/12/2017 at 4:36 AM, garwel said:

This code appears to work for a kerbal on board ActiveVessel. But when I try it on a kerbal on EVA (I skip the first line because part is null) while being focused on a nearby vessel, he doesn't disappear or anything. Trying then to switch to that kerbal causes an NRE:


NullReferenceException: Object reference not set to an instance of an object
  at KerbalRoster.ValidateAssignments (.Game st) [0x00000] in <filename unknown>:0 
  at Game.Updated () [0x00000] in <filename unknown>:0 
  at GamePersistence.SaveGame (System.String saveFileName, System.String saveFolder, SaveMode saveMode) [0x00000] in <filename unknown>:0 
  at KSP.UI.Screens.AltimeterSliderButtons.returnToSpaceCenter () [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at UnityEngine.Events.UnityEvent.Invoke () [0x00000] in <filename unknown>:0 
  at UnityEngine.UI.Button.Press () [0x00000] in <filename unknown>:0 
  at UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) [0x00000] in <filename unknown>:0 
  at UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) [0x00000] in <filename unknown>:0 
  at UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) [0x00000] in <filename unknown>:0 
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMousePress(MouseButtonEventData)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent(Int32)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent()
UnityEngine.EventSystems.StandaloneInputModule:Process()
UnityEngine.EventSystems.EventSystem:Update()

 

A kerbal on EVA.. You didn't mention that.
In that case you have to kill the Vessel as well. You can't switch to a vessel that is an EVA Kerbal if the Kerbal is dead. If they die on EVA in stock then the vessel must also be killed and disappear. Stock does not support that use case.

Share this post


Link to post
Share on other sites

 I'm not a programmer, but I have a question.  'Hope I'm in the right place.

 If I open a .craft file as a text file I see a line like this for most parts

modMass = 0

 I was hoping this will change the effect gravity has on that part.

 How do I find out what this variable really does, if changing it has any effect, and what acceptable ranges are valid?

Share this post


Link to post
Share on other sites

If memory serves correctly this is the scaler that something like tweakscale can use to change the mass of a given part's instance- thus why you'll find this parameter in a .craft file or a .sfs but not in the basic .cfg that defines the part.   Whether it's additive or multiplicative I don't remember!    To figure it out, i'd just start fiddling with it!  Write down your craft's mass, write down a given part's mass, then change that part's modmass and reload to see if the mass of the craft went up by the amount you added or if the mass of the craft increased by the mass of that part TIMES the modmass  scaler. 

 

I wish there was great documentation to point you towards but...  that's what KSP modmakers have always had to do - trial and error.

 

That said, you question was specific-  you want to change the effect of gravity ONLY?  Not actually change the mass of the part?  You want OTHER accelerations to continue to act unaffected?  That's a tough one that might take a bit more explaining before we come up with an answer for you...

  • Like 1

Share this post


Link to post
Share on other sites

I was wondering if anyone has seen this behavior before when using FlightGlobals.ForceSetActiveVessel. The throttle settings seem to be overriding the settings of the vessel I switch to. When using the  [ ] Brackets to switch this does not occur.

  Vessel A (Active) = 0% Throttle
  Vessel B (Inactive) = 100% Throttle

  FlightGlobals.ForceSetActiveVessel(Vessel B)

  Vessel A (Inactive) = 0% Throttle
  Vessel B (Active) = 0% Throttle 

Share this post


Link to post
Share on other sites

I did a simple test with an internal module I've been tinkering with, and caused all kinds of mayhem. The module is simple. It finds a prop transform for a screen model and an empty gameObject, then adds a camera component to the empty gameObject and adds a renderTexture to the screen model. The camera then has its targetTexture assigned to the renderTexture. That's it. 

The game loads fine but when I load the IVA on the pad the main cam is rotated 90 degrees on the x axis or sometimes is flung into deep space before the game crashes. I'm guessing it has something to do with layers and tags. I'm sure there's some camera voodoo I'm unaware of. @linuxgurugamer would probably know what the best practices are.

 

public class UtilisDisplay : InternalModule
	{
		[KSPField]
		public string dTransform = "dTransform"; 

		[KSPField]
		public string cameraName = "utilisCamera";

		[KSPField]
		public int dPixelWidth = 512;

		[KSPField]
		public int dPixelHeight = 256;

		private Camera cameraFeed;

		private Transform cTransform;

		private RenderTexture displayTexture;

		private Material displayMaterial;

		public override void OnAwake()
		{
			if(HighLogic.LoadedSceneIsFlight)
			{
				UtilisTools.Log(this, "Start!");

				displayTexture = new RenderTexture(dPixelWidth, dPixelHeight, 24, RenderTextureFormat.ARGB32);

				displayMaterial = internalProp.FindModelTransform(dTransform).GetComponent<Renderer>().material;

				cTransform = internalProp.internalModel.FindModelTransform(cameraName);

				cTransform.gameObject.AddComponent<Camera>();

				UtilisTools.Log(this, "Camera created");

				cameraFeed = cTransform.gameObject.GetComponent<Camera>();

				cameraFeed.fieldOfView = 110;

				cameraFeed.transform.parent = cTransform;

				cameraFeed.transform.localPosition = Vector3.zero;

				cameraFeed.transform.localEulerAngles = Vector3.zero;

				displayMaterial.mainTexture = displayTexture;
			}
		}
	}

The log is spamming "Look rotation viewing vector is zero"

Share this post


Link to post
Share on other sites

Sounds like you need to set a vector, probably getting an internal divide by zero

Best to look at some of the camera mods to see what you may have missed.

  • Like 1

Share this post


Link to post
Share on other sites

Quick question. I want to setup a UI_FloatEdit with values from the config file. When attempting to pass another field as the arguments for minValue, or maxValue, I get the following error:

An object reference is required for the non-static field, method, or property

At the moment, the only way it compiles is if I hard code the values:

[KSPField(isPersistant = true, guiName = "Length", guiFormat = "F3", guiUnits = "m"),
         UI_FloatEdit(scene = UI_Scene.Editor, minValue = 0.25f, incrementLarge = 2.0f, incrementSmall = 0.25f, incrementSlide = 0.001f)]
        public float tankLength = 1.0f;

What is the proper way to make this work?

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