Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

@Malah, I think you can change the status of a ship in the tracking station with vessel.DiscoveryInfo.SetLevel(DiscoveryLevels.xxx);

I don't think it will disable the "Recover" button in flight, though.

Thanks Lilleman, but i want to disable "Recover" button in flight ;) (i've try your solution and as you say, that doesn't work in flight).

I've try to use ScreenSafeUIButton.Lock (); as we can see it in the private void at VesselRecoveryButton.setUnlock() but it seem that doesn't work as this.

Edited by Malah
Link to comment
Share on other sites

OnVesselRecoveryRequested happens during the flight scene when you push the green recovery button. OnVesselRecovered happens after the R&D center does all of its processing on the vessel's science and part values.

OnVesselRecoveryProcessing is what you want. The problem is that this is also when the R&D center does its thing (the crew stuff might happen elsewhere, but I'm pretty sure the MissionRecoveryDialog must pass through the R&D center at some point); I'm not sure that there is any way to force your code to run before the R&D center's code, so it will be tricky to get your stuff to be counted in the mission recovery dialog.

You can, of course, reset the frozen Kerbals' status manually so that they will be available for the next mission, but they probably won't show up in the dialog, and you would have to manually add in rep for successfully recovering them (you might also need to watch out for losing rep when you set your Kerbals to "dead").

Edit: The crew recovery stuff probably happens in the Reputation scenario module, which is also where you can manually add in more rep.

Thanks this is very helpful. I don't mind manually changing the kerbal status and adding reputation (and them not showing in the dialog, at least to start with). My big sticking point at the moment is how to read the KSPfield in the partmodule when i'm working with a protovessel rather than a vessel. If I can get the field from the part, I feel like I can adjust the other stuff myself.

Link to comment
Share on other sites

Thanks this is very helpful. I don't mind manually changing the kerbal status and adding reputation (and them not showing in the dialog, at least to start with). My big sticking point at the moment is how to read the KSPfield in the partmodule when i'm working with a protovessel rather than a vessel. If I can get the field from the part, I feel like I can adjust the other stuff myself.

ProtoVessel => ProtoPartSnapshot => ProtoPartModuleSnapshot => ConfigNode = ProtoPartModuleSnapshot.moduleValues => ConfigNode.GetValue("nameOfYourField")

Link to comment
Share on other sites

ProtoVessel => ProtoPartSnapshot => ProtoPartModuleSnapshot => ConfigNode = ProtoPartModuleSnapshot.moduleValues => ConfigNode.GetValue("nameOfYourField")

The freaking confignode, of course. Now to iterate my added event and maybe prevent some kerbals from getting mulched by the recovery team.

Edit:

Pk8EZLI.png

Bob is thankful of you for helping keep him from the mulcher.

Ended up using onvesselrecovered for this, although I think onVesselRecoveryProcessing would work as well and I may move it to that event later. In case it'll help anyone down the road here's the bit that does the job. (is it weird that I feel a twinge of a strange emotion showing code I wrote to the internet for the first time?)

        
public void onVesselRecovered(ProtoVessel vessel)
{
List<ProtoPartSnapshot> partList = vessel.protoPartSnapshots;
foreach (ProtoPartSnapshot a in partList)
{
List<ProtoPartModuleSnapshot> modules = a.modules;
foreach (ProtoPartModuleSnapshot module in modules)
{


if (module.moduleName == "DeepFreezer")
{
ConfigNode node = module.moduleValues;
string FrozenCrew = node.GetValue("FrozenCrew");
ThawFrozenCrew(FrozenCrew);
}
}
}
}
public void ThawFrozenCrew(String FrozenCrew)
{
List<String> StoredCrew = FrozenCrew.Split(',').ToList();
foreach (string frozenkerbal in StoredCrew)
{
foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) //There's probably a more efficient way to find Protocrewmember from the CrewRoster
{
if (kerbal.name == frozenkerbal)
{
kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Available;
ScreenMessages.PostScreenMessage(kerbal.name + " was found in and thawed out.", 5.0f, ScreenMessageStyle.UPPER_CENTER);
}
}
}
}

Edited by scottpaladin
Link to comment
Share on other sites

Speaking of ProtoParts and ProtoCrewMembers, can they be used to spawn Kerbals?

For now, I'm looking for a Kerbal in EVA to clone at game start. It's working, but it's a very dirty way to do this.

I saw in the API documentation that a Kerbal was a vessel with a single part, so I tried saving the protovessel of one of them in a confignode, to modify and load him later. But it doesn't work, I must be missing something.

I don't need my clones to appear in the Tracking station or to be controllable, just spawn some around the KSC for now.

What I tried:


//Saving the confignode
ConfigNode cfgn = new ConfigNode("NewKerb");
vessel.protoVessel.Save(cfgn);[I]//vessel is my original kerbal in EVA. This function return "Input is null" in the log[/I]
cfgn.Save("GameData/GSL/Prot.txt");
***a bunch of stuff here because I had to reset the Orbit parameters manually***


//Load the confignode
ProtoVessel pv = new ProtoVessel(cfgn, FlightDriver.FlightStateCache);
pv.position = vessel.transform.position + new Vector3(1,1,1);//spawn the little guy close enough
pv.Load(FlightDriver.FlightStateCache.flightState);

It seems like a lot of parameters are missing from my confignode file (I can post it here if it can help).

Also, it's a bad idea to spawn a dozen Kerbals without a vessel, apparently

Edit: My bad, I found the solution. I was kinda close actually:


ConfigNode cfgn = new ConfigNode();
vessel.BackupVessel().Save(cfgn);
cfgn.Save("GameData/GSL/Prot.txt");

ProtoVessel pv = new ProtoVessel(cfgn,HighLogic.CurrentGame);
pv.position = vessel.transform.position + new Vector3(1,1,1);
pv.Load(HighLogic.CurrentGame.flightState);

I just needed to use BackupVessel instead of protoVessel, I don't really know if replacing the FlightDriver by the HighLogic made a difference...

Anyway, now I'm dealing with an easier question: How are vessel IDs generated?

Edited by Lilleman
Link to comment
Share on other sites

Thanks Lilleman, but i want to disable "Recover" button in flight ;) (i've try your solution and as you say, that doesn't work in flight).

I've try to use ScreenSafeUIButton.Lock (); as we can see it in the private void at VesselRecoveryButton.setUnlock() but it seem that doesn't work as this.

Hello, i have found how to use it :

private VesselRecoveryButton recoverybutton = null;
recoverybutton = (VesselRecoveryButton) GameObject.FindObjectOfType(typeof(VesselRecoveryButton));
recoverybutton.ssuiButton.Lock();

Link to comment
Share on other sites

Anyway, now I'm dealing with an easier question: How are vessel IDs generated?

These are of type GUID when I look at them in the object browser in visual stuido so I've been treating them as random hex string assigned when a vessel is created.

I need to do some more tests, but at the moment I think this includes when a vessel undocks as well.

Vessel A docks to Vessel B, combined vessel has GUID of Vessel B. Undock and Vessel B keeps its GUID but Vessel A has been 'created' new and so now has GUID C.

I still need to do some more tests (I'm trying to find some kind of identifier so that after vessel A undocks, I can tell it is the same vessel from before the two vessels docked together) but that is my current understanding.

D.

Link to comment
Share on other sites

Have you tried to use the "tag" field of a part? Let's say you put a different tag on each command pod that must be part of a separate ship, they may be keeped even after a docking/undocking.

I've solved my problem. To get a new Guid, I needed to call... Wait for it... Guid.newGuid();...

Yep, that was that simple, I really overthought this one... Sorry for my previous posts, they were kind of useless...

Link to comment
Share on other sites

Have you tried to use the "tag" field of a part? Let's say you put a different tag on each command pod that must be part of a separate ship, they may be keeped even after a docking/undocking.

That is what I am trying to find, but have not been able to. Coming into this I would have expected that each part would have some sort of unique Identifier I could use to track this, but it seems that is not the case.

I could add a partModule to save said tag, but the entire point of the rewrite that necessitated this question was to not use partModules in any way as I no longer trust them to save data in 0.24.x (See my Actions groups thread for why I am doing this.)

D.

Link to comment
Share on other sites

That is what I am trying to find, but have not been able to. Coming into this I would have expected that each part would have some sort of unique Identifier I could use to track this, but it seems that is not the case.

Aren't Part.flightIds persistent across games? If that doesn't work, there's always the ugly yet usable Part.customPartData

Link to comment
Share on other sites

Aren't Part.flightIds persistent across games? If that doesn't work, there's always the ugly yet usable Part.customPartData

part.FlightIds are persistent I believe, but that would still leave me unable to tell the difference between parts of the same type on the same flight.

Now that make me think of it, that may actually work as what I'm trying to track is the flight, not the part. Hmmm....

On the part.customPartData, what is this actually used for? I have never seen it as anything except an empty string. As it is generated by KSP, I would rather not use it as it is also open for other mods to access and I don't want to start a conflict by using it when another mod the player may have installed is using it also.

D.

Link to comment
Share on other sites

part.FlightIds are persistent I believe, but that would still leave me unable to tell the difference between parts of the same type on the same flight.

Each part should have a unique one; I used them in a mod I wrote for myself that made targets (docking nodes in particular) persistent

On the part.customPartData, what is this actually used for? I have never seen it as anything except an empty string.

It's just a persistent string each part has. I don't know of any mod that's used it so far but if you need to store part-relevant data without messing with them, it's an option. It can also be handy to store information per-part while in the editor since those parts don't get ids as I recall

Link to comment
Share on other sites

Each part should have a unique one; I used them in a mod I wrote for myself that made targets (docking nodes in particular) persistent

Okay, now I am really confused.

Opening the persistent.sfs file, each part has two fields that could work as unique identifiers:

uid = 2353531706
mid = 2070367717

uid imports into the game as Part.uid, however it is not persistent, or perhaps I should say not consistent. From a discussion with Ippo and McOffSky here Part.uid changes somehow and is not actually unique. (I was able to get 3 different Kerbal X test ships with the same uid on their root part in game.) It may be that it is persistent for a single save load which explains how your docking port targeting mod works as expected but it is certainly not persistent across multiple game sessions.

Now, I have never been able to find the 'mid' from the persistent.sfs file in the Part class in Visual Studio before, but I've never looked at the FlightId property you just mentioned. However, looking at the persistent.sfs file, the mid field on each part on a vessel is the same, not different so that should not be the case.

However, there is a Vessel.missionID field in KSP that does not seem to have an entry under the Vessel in the persistent.sfs file, I wonder if the Part.mid of the root part of the vessel is how the Vessel.missionID is populated?

The other question that does not answer though is where is Part.FlightID saved?

I'm on a mobile and can't actually test anything at the moment, but I'll see if I can run some tests tonight when I get home.

D.

Edited by Diazo
Link to comment
Share on other sites

uid imports into the game as Part.uid, however it is not persistent, or perhaps I should say not consistent.

It looks like flightID is uid (I mean the value in sfs is same as flightid, I didn't compare flightID to uid) and 'ref' in sfs is equivalent to the root part's flightID. But I don't get the same results as your tests.

Part.mid looks to be somewhat similar to the vessel id but you might be able to make it work. Where an undocking vessel receives a brand new id, the parts of that vessel all keep the same mid values as the parent vessel. They'll be overwritten if they dock with a different parent though

Edited by xEvilReeperx
Link to comment
Share on other sites

flightID in code is uid in the persistence file? So where does uid in code come from?

If that is the case, I need to go back to square one and check this again. I was working on the premise that the uid in the .sfs file was the same as the part.uid in code so if that is not the case I am way off base.

At this point I'll run those tests when I get home and post my results.

D.

Link to comment
Share on other sites

That's a good question! They're definitely different. How bizarre:

PART

{

name = probeCoreCube

uid = 1582019048

mid = 1339010955

[... snip]

Results in

[LOG 12:04:05.518] DebugTools, FlightId = 1582019048
[LOG 12:04:05.519] DebugTools, mid = 1339010955
[LOG 12:04:05.520] DebugTools, id = -2127700883 // was checking Vessel.id hashCode to see if it matches anything
[LOG 12:04:05.520] DebugTools, uid = 4294732514

And there's absolutely nothing in the sfs that has "4294732514"

Link to comment
Share on other sites

That agrees with my test.

Key:

SFS.Vessel.ref = persistent.sfs file, Vessel node, 'ref' value

CODE.Part.uid = In visual studio, Part Class, 'uid' field

Test Results:

SFS.Vessel.ref = SFS.Part.mid at least at flight start. Not sure where to find this in code, I think it is CODE.Vessel.referenceTransformID so if you "Control From Here" on a different part, SFS.Vessel.ref would change to the SFS.Part.mid of the part you control from here on. (Not actually tested.) edit: tested and confirmed. CODE.Vessel.referenceTransformID is the CODE.Part.FlightID of the part you 'control from here' on.

SFS.Vessel.pid = CODE.Vessel.id.ToString() CODE.Vessel.ID is a GUID which has hyphens in it. These hyphens are not present in the .sfs file so I believe the ToString() operation is performed when a save happens.

SFS.Part.uid = CODE.Part.FlightID //this is unique to each part on the vessel as far as I can tell

SFS.Part.mid = CODE.Part.MissionID //this is the same for each part on the same vessel, but different for different vessels. I do not know yet what docking does to this, will have to devise a test after dinner. This seems to be set on spawn and does not change. Launch a vessel, split it in two with a decoupler, both vessels still have the same CODE.Part.MissionID

CODE.Part.uid does not exist in the SFS file and changes when you switch away and back to the vessel.

D.

Edited by Diazo
Link to comment
Share on other sites

I know it has been asked before but why the hell is System.IO.Path.Combine giving me problems with a MissingMethodException.

I have the using directive set correct, and as it was said on page 26 it is nolonger a forbidden namespace.

Debug.LogError(string.Format("{0}| system.io.combine configfile = {1}", Constants.logPrefix, System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Constants.settingFilePath, Constants.settingFileName)));

Gives me always the Report "MissingMethodException: Method not found: 'System.IO.Path.Combine'."

How can that be? what do I miss?

Link to comment
Share on other sites

Make sure your project targets .NET 3.5 (it's in the project options in VS). Does that method exist in .NET 3.5?

Ok, I will try that.

Does that really make such a big difference?

System.IO.path.combine is quite essential.

EDIT: changed the .net Framework from 4.5 to 3.5 and now it works.

I was using an override that was not part of 3.5 so he could not find it.

Thanks The_Duck

Edited by Alewx
Link to comment
Share on other sites

  • 3 weeks later...

So I'm trying to make a plugin for this forum thread: http://forum.kerbalspaceprogram.com/threads/94346-1-Button-Bill

I have a few questions:

1) How to you add one of the dialog boxes (like the ones you change fuel levels with in VAB) that come up when you click a part to my custom PartModule? (So I can set stuff up while in VAB)

2) Which class controls keyboard inputs, and how do I call the method to send inputs when you click a button?

3) How do I make variables from my PartModule save to the sfs file?

PS. Is there a way to view the code of the original command module?

Edited by Thunderous Echo
Link to comment
Share on other sites

So I'm trying to make a plugin for this forum thread: http://forum.kerbalspaceprogram.com/threads/94346-1-Button-Bill

I have a few questions:

1) How to you add one of the dialog boxes (like the ones you change fuel levels with in VAB) that come up when you click a part to my custom PartModule? (So I can set stuff up while in VAB)

2) Which class controls keyboard inputs, and how do I call the method to send inputs when you click a button?

3) How do I make variables from my PartModule save to the sfs file?

PS. Is there a way to view the code of the original command module?

Take a look at TAC Examples ( https://github.com/taraniselsu/TacExamples )

1) KSPEvent and KSPField - https://github.com/taraniselsu/TacExamples/blob/master/03-PartRightClicking/Source/PartRightClick.cs and https://github.com/taraniselsu/TacExamples/blob/master/05-KspFields/Source/KspFieldsModule.cs

2) As far as I know keyboard input is controlled by Unity and you cannot fake this input. You should be able to bind to those functions from your code, using keyboard as proxy is not good idea. Have a look at documentaction (http://anatid.github.io/XML-Documentation-for-the-KSP-API/annotated.html), this should help.

3) In your part module:


public override void OnLoad(ConfigNode node)
{
if (node.GetValue("cid") != null)
{
this.cid = node.GetValue("cid");
}
}


public override void OnSave(ConfigNode node)
{
if (node.GetValue("cid") == null)
{
if (string.IsNullOrEmpty(this.cid))
{
this.cid = this.part.ConstructID;
}
node.AddValue("cid", this.cid);
}


}

Edited by McOffsky
Link to comment
Share on other sites

I will quote Coldplay now, play music in your head on your own: "...nobody said it was eeeeeasy!" :P

ModuleCommand is Squad script and I think it's not public. If I understand your plugin correctly you just need to find parts with that module on active ship. You will get that with code below. And you can use Module Manager to attach your code to stock parts.


foreach (Part p in vessel.Parts)
{
foreach (PartModule pm in p.Modules)
{
if (pm.moduleName.Contains(n))
{
list.Add(pm);
}
}
}

Edited by McOffsky
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...