Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

You just want some of your events ([KSPEvents]) to also be available through action groups?

Create a [KSPAction("name")] and have it call your KSPEvent method, or make separate code for it.

Well... yes. But now I'm not clear on the difference between Actions and Events then: can you point me to any resource about their difference?

Link to comment
Share on other sites

Well... yes. But now I'm not clear on the difference between Actions and Events then: can you point me to any resource about their difference?

The difference is just that, KSPActions are for action groups, KSPEvents are for right-click events.

KSPActions only really have one parameter, the name (I've never really seen anyone use the second, KSPActionGroup, parameter). KSPEvents, on the other hand, have a lot, the various Active parameters, the name, unfocused range, etc...

Also note that you can control these paramaters with:

Events["event method name"]

and

Actions["action method name"]

and that you can set Actions[""].active to true or false this way (which will either show or not show the action group in the VAB)

Link to comment
Share on other sites

Just will chime in to confirm that the KSPAction.ActionGroups property is where the actiongroups an action is assigned to is stored.

I have only worked with existing actions other people have made, but I would assume that when you define an action, if you use the KSPAction(string,ActionGroup) overload, you are setting the default actiongroup for that action. Useful for something like a custom landing leg if you can't extend the ModuleLandingLeg partModule for some reason and want to add your ToggleLeg action to the Gear actiongroup automatically. (If you extend ModuleLandingLeg, that comes with the ToggleLeg action already added to the gear action group.)

If someone actually tests this please confirm, but I know for sure the KSPAction.ActionGroups property is where an action's assigned actiongroups are stored.

D.

Link to comment
Share on other sites

I have a bit of code that selectively destroys child parts when called:


foreach (Part p in this.part.children)
{
if (p.Resources.Contains("SolidFuel"))
{
p.Die();
}
}

It works... but I get the following error message in my debug log:

[Exception]: InvalidOperationException: Collection was modified; enumeration operation may not execute.

After doing a bit of research, it seems I'm maybe not supposed to remove an object in the middle of a foreach loop. I don't know a different way to loop through the child parts. This is probably very simple, but I can't seem to find any good examples, and lists still confuse me a bit.

Any advice? Thanks!

Link to comment
Share on other sites

I have a bit of code that selectively destroys child parts when called:


foreach (Part p in this.part.children)
{
if (p.Resources.Contains("SolidFuel"))
{
p.Die();
}
}

It works... but I get the following error message in my debug log:

After doing a bit of research, it seems I'm maybe not supposed to remove an object in the middle of a foreach loop. I don't know a different way to loop through the child parts. This is probably very simple, but I can't seem to find any good examples, and lists still confuse me a bit.

Any advice? Thanks!

I'm using a GoTo command to escape the loop.

If you want to make sure every part with SolidFuel is destroyed (restarting the loop after you escape):


BreakOut:
foreach (Part p in this.part.children)
{
if (p.Resources.Contains("SolidFuel"))
{
p.Die();
goto BreakOut;
}
}

If you want to only destroy the first part with SolidFuel found, move the BreakOut: line after the foreach statement.

You will need to test to see when "this.part.children" is being updated. You may have to move the BreakOut: line after your for each loop and only destroy a single part per update pass because KSP needs to update the part list before you can run the foreach again.

In my own code, I'm using this on a list of my own creation so I can make sure it is updated after I escape the foreach loop and before I restart the foreach loop.

D.

Edited by Diazo
Link to comment
Share on other sites

I'm using a GoTo command to escape the loop.

Ew

Just don't modify the collection while you're iterating through it. Here are two more ways:

var deathList = new List<Part>();

foreach (Part p in this.part.children)
if (p.Resources.Contains("SolidFuel"))
deathList.Add(p);

foreach (var p in deathList)
p.Die();

for (int i = 0; i < this.part.children.Count; )
if (this.part.Resources.Contains("SolidFuel"))
{
this.part.children[i].Die();
}
else ++i;

Link to comment
Share on other sites


foreach (var p in deathList)
p.Die();

This works? I thought that counted as modifying the collection as you cycled through it.

Why I went to the GoTo method.

D.

Edited by Diazo
[code] does not work in [quote]
Link to comment
Share on other sites

This works? I thought that counted as modifying the collection as you cycled through it.

deathList isn't modified, so the IEnumerator represented by p doesn't get invalidated. At least, that's my understanding. All of my experience with C# is from modding KSP

Link to comment
Share on other sites

A collection is only considered to have been modified after an element is added/removed from it. I'm not sure what replacing an element without changing the collection size is considered though.

EDIT: For List<T>, replacing an element qualifies as modifying it.

Edited by Echo 8 ÉRÀ
Link to comment
Share on other sites

Got an interesting problem. With Infernal Robotics I have a group manager that populates and removes parts from the manager when parts are added or removed. Everything is fine until a user presses control-z or control-y. The group manager gets bugged because onpartattach/etc doesn't get called using this method. Only thing that I have found so far is EditorLogic.fetch.UndoRedo() that returns true when either of those commands are done. Question is how can I capture this and know what part is getting removed/added?

Link to comment
Share on other sites

Hmmm.

I just checked and my action group mod also suffers from this.

When a part is deleted and then restored via Ctrl-Z, any actions assigned are lost.

A quick 5 minute investigation reveals that it looks like the part is actually deleted and then when Ctrl-Z is pressed, a new part is "replaced" instead. Even if you move a part and then move it back via Ctrl-Z, the Part.constructID changes.

I did this by watching the Part.constructID string. I placed a solar panel on a control pod, deleted the solar panel, and then replaced it via Ctrl-Z and the Part.constructID was different.

I also noted that the base game action group assignments (so not my action group mod, the ones built into the game) do not save either.

My assumption at this point is that the way KSP's undo function works is that it saves part name and the location only, it does not save the actual part, so any data assigned to that part does not come back on Ctrl-Z. That is the only reason I can think of that actiongroup assignments are lost. If the part itself was saved somehow, the actiongroup assignments would save also as that is part of the base game.

Even if it does not work quite like that, the fact that the base game actiongroup assignments are lost means to me that there is nothing in the base game to help out here and we are looking at building something from scratch that caches the information we want to save somehow.

Having said that, I am at a total loss on how to actually program something like that.

D.

edit: What about something like:

On part detach -> Cache data we want to save, including parts floating under cursor //anytime I can imagine the Ctrl-Z being used, it is after a part detach event, so cache the data for parts that just got detached.

On ctrl-z -> Readd our data via part type matching. //Note that this method will add data back from all parts of the same type to all parts of the same type. Using my action groups mod, if 3 solar panels, each with a different action assigned (deploy/retract/toggle) are deleted and reattached with Ctrl-Z, all 3 panels will have all 3 actions.

Check on parts floating under cursor changing, if they are different, clear our cache of data so it does not grow each time we detach something.

Not workable as is, but the best I can come up with so far.

Edited by Diazo
Link to comment
Share on other sites

is there a place where I can see list of ParModules, things like ModuleAnimateGeneric, ModuleEngine, etc... that are in the newer versions of KSP? so far the ones I can find on the Wiki and Antid's XML list are much older, from 0.15 or so... referencing KSP's Assembly-C# and UnityEngine dlls don't seem to show me anything I can recognize as modules either.

Edited by nli2work
Link to comment
Share on other sites

is there a place where I can see list of ParModules, things like ModuleAnimateGeneric, ModuleEngine, etc... that are in the newer versions of KSP? so far the ones I can find on the Wiki and Antid's XML list are much older, from 0.15 or so... referencing KSP's Assembly-C# and UnityEngine dlls don't seem to show me anything I can recognize as modules either.

In Visual Studio, if you go to the object browser you can see all the Module classes. Does not have descriptions of any sort, but things are generally named appropriate to what they do.

D.

Link to comment
Share on other sites

Is it possible to code a plugin in java? I'm more familiar with it than C#, and I have no clue on any other languages than basic. I know it'd be bad form, but I'm intending to test if something is even possible before trying to bash my head against C# again so I can distribute.

Link to comment
Share on other sites

Disclaimer: Have not actually tried using Java.

Having said that, all the Unity Script reference docs include both C# and Java so I would certainly expect that you could program in Java.

Not knowing Java at all, I would not have a clue on how to go about it, but as long as you can reference the .dlls needed in {KSP_Install}\KSP_Data\Managed and are able to output your code as a .dll, I would expect it to work.

How to do that I would have to leave to you, I've never used Java at all.

See below

D.

Edited by Diazo
Link to comment
Share on other sites

The Unity scripting documentation talks about Javascript, which does have a .Net implementation.

It looks like this is correct, poking around on Unity's site, it looks like there are 3 supported programming languages: C#, Javascript, and Boo.

So I guess the answer is that no, Java will not work for KSP mods.

D.

Link to comment
Share on other sites

Is there anything I need to do to have a persistent scenario module?

I tried making an empty one that just logs when it enters a function, but onload and onsave are never called.

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