Cephei

The official unoffical "help a fellow plugin developer" thread

Recommended Posts

I know it's possible, I know parachutes do it. But how to make an engine do it?

Without testing it (all I did was check if it would compile), this is how I would do it:

class RetroRocket : SolidRocket {

// Should probably read this from part.cfg, but I can't be bothered doing
// that here
private float ActivationAltitude = 400.0f;

private bool m_Active = false;

protected override void onPartStart() {

base.onPartStart();
this.ActivatesEvenIfDisconnected = true;

}

protected override bool onPartActivate() {
// Do Nothing
return true;
}

protected override void onPartFixedUpdate() {

if (this.m_Active) {

base.onPartFixedUpdate();

} else if (ActivationAltitude >= this.GetAltitude()) {
this.m_Active = true;
base.onPartActivate();
}

}

protected override void onPartUpdate() {

if (this.m_Active) {

base.onPartUpdate();

}

}


private float GetAltitude() {
// Don't know if this the proper way of getting altitude.
return vessel.GetHeightFromTerrain();
}
}

Then just change SolidRocket to RetroRocket in part.cfg


Is it possible to add buttons to a part's right-click menu at runtime? I'm trying to make a PartModule with part.cfg configurable right-click menu entries.

I could probably get away with hardcoding it (a lot of methods with KSPEvent attribute) and showing/hiding them as necessary, but it'd be nice if I could avoid doing that.

Ok, I've done some investigation and found out you can apply a partmodule to the same part multiple times, so I can just go with that. So my new question is, how do I get the right-click menu entry to update its text when I click on it? Thus far, when I set this.Events["EventName"].guiName to something else, the text doesn't change until I open and close the menu. I guess that might be because it's a field and not a property so KSP doesn't know I've changed it, but there's probably a way to force it to update the GUI since AtmosphericEngine does it.

Edited by Echo 8 ÉRÀ

Share this post


Link to post
Share on other sites

Hmm. I'm downloading MonoDevelop now.


EDIT:

Sorry about the delay. Had to do some work around the home.

That's odd. When I hit build, I get a *.dll (in $(ProjectDir)\bin\Debug\ with a debug build). Can you post your build log (View → Pads → Error List → Build Output)?

Edited by Echo 8 ÉRÀ

Share this post


Link to post
Share on other sites

Can anyone tell me what the heck is wrong with this code?



[KSPField]
private string ActiveState;

public override void OnActive() {
base.OnActive();
Debug.Log("[Module_EE_Test] OnActive()");
}

public override void OnInactive() {
base.OnInactive();
Debug.Log("[Module_EE_Test] OnInactive()");
}

/// <summary>
/// Constructor style setup.
/// Called in the Part\'s Awake method.
/// The model may not be built by this point.
/// </summary>
public override void OnAwake() {
base.OnActive();
Debug.Log("[Module_EE_Test] OnActive()");
}

/// <summary>
/// Called during the Part startup.
/// StartState gives flag values of initial state
/// </summary>
public override void OnStart(StartState state) {
base.OnStart(state);
Debug.Log(string.Format("[Module_EE_Test] OnStart({0})",
Enum.GetName(typeof(StartState), state)));
Debug.Log(string.Format("[Module_EE_Test] ActiveState = \"{0}\"",
ActiveState));
}

/// <summary>
/// Per-frame update
/// Called ONLY when Part is ACTIVE!
/// </summary>
public override void OnUpdate() {
base.OnUpdate();
Debug.Log("[Module_EE_Test] OnUpdate()");
}

/// <summary>
/// Per-physx-frame update
/// Called ONLY when Part is ACTIVE!
/// </summary>
public override void OnFixedUpdate() {
base.OnFixedUpdate();
Debug.Log("[Module_EE_Test] OnFixedUpdate()");
}

/// <summary>
/// Called when PartModule is asked to save its values.
/// Can save additional data here.
/// </summary>
/// <param name='node'>The node to save in to</param>
public override void OnSave(ConfigNode node) {
base.OnSave(node);
Debug.Log("[Module_EE_Test] OnSave([ConfigNode node])");
}

/// <summary>
/// Called when PartModule is asked to load its values.
/// Can load additional data here.
/// </summary>
/// <param name='node'>The node to load from</param>
public override void OnLoad(ConfigNode node) {
base.OnLoad(node);
Debug.Log("[Module_EE_Test] OnLoad([ConfigNode node])");
Debug.Log(string.Format("[Module_EE_Test] ActiveState = \"{0}\"",
ActiveState));
}

}
public sealed class Module_EE_StackIcon: PartModule {


MODULE {
name = Module_EE_StackIcon
ActiveState = Closed
}

It's not supposed to do anything but print a bunch of text to the console, but instead, it makes KSP throw a fit then crash:

In addition to the game crashing when I detached the test part at the end, it seems like value of ActiveState is forgotten sometime between game load and entering the VAB.

Share this post


Link to post
Share on other sites

There's a part module similar to that in my plugin, ModuleKrTestSpam.

If you need the current state in OnLoad, use HighLogic.LoadedScene (or HighLogic.LoadedSceneIsFlight if you only need that one) for that.

Share this post


Link to post
Share on other sites

That's just a test PartModule I cooked up to try to narrow down what's going wrong with my PMs proper, so I can work out why my v1 animation PM works (it's literally a 132-line hackjob, including useless cruft and whitespace, to get my animated cargo bay working), while a much cleaner coded PM that does nothing but change the stackicon when it processes a KSPEvent, crashes half the time and does nothing the rest. The ActiveState field is just a representation of one of the variables from my other PMs.

Test parts like that is how I discovered that IConfigNode KSPFields don't work (its Load and Save methods never gets called), that my partmodules sometimes forget the contents of fields (both marked with KSPField and not) between the call to OnLoad and going into the VAB, even when the code is highly similar between two different partmodules I have in development. Heck, at one point my animation partmodule had a similar freakout to that video depending on whether or not "public override void OnXXXX() { base.OnXXXX(); }" was commented out (can't remember which one it was).

Ack, I'm rambling. Been having a frustrating day trying to work out when something is going wrong because of something I wrote or it's because of bugs in KSP's partmodule infrastructure (like the IConfigNode thing).

Edited by Echo 8 ÉRÀ

Share this post


Link to post
Share on other sites

Lol I'm working on an animation part module too:D it works after a lot of strange failures...

What I found out about KSPField is that bool and int don't really work (especially int, it loads the value from the sfs file as a float and fails converting it to int*facepalm*), and that you should never use isPersistant = false, then it might not even load from the part.cfg.

Share this post


Link to post
Share on other sites
Lol I'm working on an animation part module too:D it works after a lot of strange failures...

Same. I don't even want to clean up the code in the fear that a change will cause it to blow up on me again.

What I found out about KSPField is that bool and int don't really work (especially int, it loads the value from the sfs file as a float and fails converting it to int*facepalm*), and that you should never use isPersistant = false, then it might not even load from the part.cfg.
Discovered that early on. I just use strings and the occasional float now. Though recently, I've mainly worked on getting data from nested confignodes (it works if I don't rely on KSP to do it for me), so most of data is loaded via ConfigNode.GetValue() and converting the string into something else. Edited by Echo 8 ÉRÀ

Share this post


Link to post
Share on other sites

hey, ive created a model and the load screen gets stuck when it tries to load the part, on the debug console i get this message "FormatException: Input String was not in the correct format"

this is driving me insane, any help would be a godsend

Share this post


Link to post
Share on other sites
hey, ive created a model and the load screen gets stuck when it tries to load the part, on the debug console i get this message "FormatException: Input String was not in the correct format"

this is driving me insane, any help would be a godsend

Ok, even though I suspect you're trying to make a bog-standard engine and not something that requires you making a plugin, I'll bite.

I have to point out the obvious: Are all your values in part.cfg in the right format? Like Vector2/3/4 fields have to be 2/3/4 float values separated by a comma and optional whitespace.


Random Aside: If I delete all the empty overrides in my animation partmodule, the End Flight button that appears when you hit escape no longer works :D

Edited by Echo 8 ÉRÀ

Share this post


Link to post
Share on other sites

regarding my earlier post, im making a test cube that functions as a fuel tank. any help on why my part wont load and im getting "FormatException: Input String was not in the correct format" in the debug menu. hopefully this will give you enough info to diagnose my problem.

my file(your going to need 7-zip):

http://www./?8pm2xdy224jf9nt

Share this post


Link to post
Share on other sites

As I guessed, you're asking in the wrong section. You're looking for the Add-on Development subforum.

If I had to guess, it's because you put '.3' instead of '0.3', but I'll leave that for you to test.


Does PartModule.OnSave() even do anything? I can see it gets called, but it seems like it has no effect on a ship's .craft file or the main persistence file.

EDIT: My Bad. I was assuming Node.SetValue creates a value if the key didn't already exist. Excellent, now I can have nice title-cased part.cfg entries while using 'm_' prefixes for private fields.

Edited by Echo 8 ÉRÀ

Share this post


Link to post
Share on other sites

Does anyone know of a way to load custom code that's not a part? I'm trying to find a way to hook something to when the game first starts. I thought about extending the Vessel class, but there doesn't seem to be anything there to make it load a custom class.

Share this post


Link to post
Share on other sites

I believe this will be possible in .17, scenario logic modules will allow code to be tied to a game save.

Share this post


Link to post
Share on other sites
Does anyone know of a way to load custom code that's not a part? I'm trying to find a way to hook something to when the game first starts. I thought about extending the Vessel class, but there doesn't seem to be anything there to make it load a custom class.

Just what are you doing that you need to extend Vessel? If you just need to run some code at startup, create a dummy part, add a static constructor to the class, and you now have a way to run code during the game's loading screen.

Share this post


Link to post
Share on other sites
Just what are you doing that you need to extend Vessel? If you just need to run some code at startup, create a dummy part, add a static constructor to the class, and you now have a way to run code during the game's loading screen.

Does that work? I just assumed it didn't actually call your class until the VAB.

Share this post


Link to post
Share on other sites

Oh it works. In fact, I use a variation of it for my workaround to Unity's idiosyncratic cloning behaviour: PartModuleBase.cs

It may not actually use the method described earlier exactly, but the effect is more or less the same (static constructor being called during game load).

KSP actually creates a prototype part for each Part.cfg during game load, and clones copies of it whenever you add that part in the VAB/SPH. It's that cloning process which had me tearing my hair out trying to work out why my code wasn't working. Curse you Unity Dev Team and your wierd cloning behaviour! It wouldn't be so bad if they used MemberwiseClone() or ICloneable. But no, they had to use some odd magic involving reflection, the SerializableAttribute, and a SerializeField attribute which only works on certain types and silently fails on unsupported ones. :mad:

Edited by Echo 8 ÉRÀ

Share this post


Link to post
Share on other sites

How can I manipulate individual landing legs? For example for ladders I can search the parts tree for RetractableLadder partmodules and either call Extend()/Retract() or SendMessage("Extend")/SendMessage("Retract"), and that works fine. However, for ModuleAnimatorLandingGear, SendMessage("InputGearToggle") doesn't seem to do anything. Or should I somehow manipulate a HLandingLeg directly?

Share this post


Link to post
Share on other sites

Two questions:

1) When creating a custom icon for a part using a plugin for the staging display, what size should I make it? This doesn't say

2) Why does creating a custom icon break backwards compatibility, and can I fix that? In other words, I have a ship with my custom part on it and a blank icon. I edit the code, add the icon, recompile. Now when I load that .craft, the part is gone. I would have to make a new ship in the VAB to use the part.

Share this post


Link to post
Share on other sites

1) Use 64x64, judging by the example file (size of one of the grid squares).

No insight on 2) for now, gotta try that

Share this post


Link to post
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.