Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

Ok, this is likely something stupid I'm missing, but I can't seem to get Onsave() to function. I'm trying the below code:

...

When I try to compile, I get 'Kerbanomics.Kerbanomics.OnSave(ConfigNode)': no suitable method found to override' in the error log. Like I said, I'm sure it's something stupid, I've just been at this for a couple hours with no progress.

MonoBehaviour has no method called OnSave(ConfigNode) for you to override.

If you're trying to save things into the persistent file, the best way is to inherit from ScenarioModule instead of MonoBehaviour and replace the KSPAddon attribute with a KSPScenario attribute that specifies which scenes your scenario should run in. Then you can override OnLoad/OnSave to handle your persistent data.

Link to comment
Share on other sites

MonoBehaviour has no method called OnSave(ConfigNode) for you to override.

If you're trying to save things into the persistent file, the best way is to inherit from ScenarioModule instead of MonoBehaviour and replace the KSPAddon attribute with a KSPScenario attribute that specifies which scenes your scenario should run in. Then you can override OnLoad/OnSave to handle your persistent data.

See, I said it was something stupid I was missing. Didn't even think of that. All I actually want to do is to fire off a function when the game is saved. My plugin uses it's own persistent files, and I'd like them to save when the game does. I tried both GameEvents.onGameStateSave and GameEvents.onGameStateSaved to no effect.

Is using OnSave() the best way to fire that off? Or should I be trying to get the GameEvents code working?

Link to comment
Share on other sites

All I actually want to do is to fire off a function when the game is saved. My plugin uses it's own persistent files, and I'd like them to save when the game does.

Usually this results in some ugly hacking. How do you handle quickloads? Multiple saves? ScenarioModule is the way to go here, then you can just keep it all together. Do you have a particular reason for separation?

Link to comment
Share on other sites

Usually this results in some ugly hacking. How do you handle quickloads? Multiple saves? ScenarioModule is the way to go here, then you can just keep it all together. Do you have a particular reason for separation?

Nothing in particular, just seemed like it worked. I'll convert it to ScenarioModule and do some testing. Thanks for your help, sir!

Link to comment
Share on other sites

Any idea how to prevent a CelestialBody from rendering in the map/tracking station view?


CelestialBody cb = ...;
cb.scaledBody.renderer.enabled = false;

Causes planets to no longer occlude the sun but their surface texture still appears. For example:

yQGtRaZtTBML.png

Link to comment
Share on other sites

Hi,

I'm trying to hack kOS a bit, but I've got no experience in KSP modding or even C# (I do know C/C++ though), so I'm asking for a little help setting up the environment.

I've installed MonoDevelop, opened up the kOS.sln file and added the Assembly-CSharp and UnityEngine References as described on http://wiki.kerbalspaceprogram.com/wiki/Setting_up_MonoDevelop

However, when I try to build kOS (or kOS.Safe), I'm getting the following build error (I also had it before adding the above references):

Building Solution: kOS (Debug)

Building: kOS.Safe (Debug)

Build started 12/29/2014 6:34:25 PM.
__________________________________________________
Project "/home/goblin/git/KOS/src/kOS.Safe/kOS.Safe.csproj" (Build target(s)):

Target PrepareForBuild:
Configuration: Debug Platform: AnyCPU

Target GenerateResources:
Tool /usr/bin/resgen2 execution started with arguments: /useSourcePath /compile "Properties/Resources.resx,obj/Debug/kOS.Safe.Properties.Resources.resources"
/usr/lib/mono/4.5/Microsoft.Common.targets: error : Error executing tool '/usr/bin/resgen2': ApplicationName='/usr/bin/resgen2', CommandLine='/useSourcePath /compile "Properties/Resources.resx,obj/Debug/kOS.Safe.Properties.Resources.resources" ', CurrentDirectory='/home/goblin/git/KOS/src/kOS.Safe', Native error= Cannot find the specified file
Task "GenerateResource" execution -- FAILED
Done building target "GenerateResources" in project "/home/goblin/git/KOS/src/kOS.Safe/kOS.Safe.csproj".-- FAILED


---------------------- Done ----------------------

Build: 1 error, 0 warnings

I'm not quite sure what "the specified file" is... Any help on fixing the error would be appreciated.

Link to comment
Share on other sites

Thanks for the reply, but it doesn't seem to be it: I already have "Mono / .NET 3.5" selected in Project options / Build / General / Target framework. I guess it must have already come with kOS.sln or some other file included in the kOS tree.

Also, not sure if that changes things, but I have "Use MSBuild build engine (recommended for this project type)" selected below the framework.

Link to comment
Share on other sites

In that case, maybe check your references list?

The /usr/lib/mono/4.5/Microsoft.Common.targets line implies it is looking for .net 4.5 reference files I think?

Beyond that I can't help as I use Visual Studio as my IDE and not monodevelop.

D.

Link to comment
Share on other sites

Yay, thanks everyone :-)

Indeed /usr/bin/resgen2 was missing, the package mono-devel somehow got removed when I apt-get installed monodevelop. Reinstalling that manually helped.

After that I only needed to change "Opcode.cs" in kOS.Safe.csproj to "OpCode.cs" (apparently someone compiled it on a case-insensitive system) and voilla, compiled with only 14 warnings :-)

Link to comment
Share on other sites

Same question, but no one answered me last time (or I have totally missed it).

If I want to change a part's cost when a button (KSPEvent) is clicked, how do I do that?


[KSPEvent(guiName = "Quality ++", guiActive = false, guiActiveEditor = true)]
public void AddCost()
{
// Doing something useful or not-so-useful..
}

My current way of doing this is using GetModuleCost:


public float GetModuleCost(float defaultCost)
{
// Seems like default cost is always 0..
//this.Log("Default cost: " + defaultCost);
return this.GetExtraCost();
}

But, sadly, that way only works iff I detach the part and re-attach it..

So, my question is, how do I change the cost right away when the button (KSPEvent) is clicked?

And please, don't ignore me this time? Please!?

Edited by 8749236
Link to comment
Share on other sites

So, my question is, how do I change the cost right away when the button (KSPEvent) is clicked?

And please, don't ignore me this time? Please!?

I actually would love to know if this is possible for an upcoming new kOS feature. is this a thing we can do now?

Link to comment
Share on other sites

If I want to change a part's cost when a button (KSPEvent) is clicked, how do I do that?

...

But, sadly, that way only works iff I detach the part and re-attach it..

You almost have it. You forgot to fire GameEvents.onEditorShipModified. That's why the editor isn't updating cost until some other event that triggers a cost recalculation occurs

Link to comment
Share on other sites

You almost have it. You forgot to fire GameEvents.onEditorShipModified. That's why the editor isn't updating cost until some other event that triggers a cost recalculation occurs

Thank you very much! and Diazo as well!

GameEvents.onEditorShipModified is most probably what I was looking for the whole time..

But how do I trigger it? (Not sure what goes into Fire method)

Also, I am curious about IModuleCost, about how it is being used..

Edited by 8749236
I was being rude for not saying thank you..
Link to comment
Share on other sites

GameEvents.onEditorShipModified is most probably what I was looking for the whole time..

But how do I trigger it? (Not sure what goes into Fire method)

GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);

Simple, complete PartModule example:

public class PartQuality : PartModule, IPartCostModifier
{
private float _multiplier = 1f;

[UI_Label(controlEnabled = true)] public string Quality;



[KSPEvent(guiName = "Quality ++", guiActive = false, guiActiveEditor = true)]
public void QualityIncrease() { AdjustMultiplier(0.1f * UnityEngine.Random.Range(0.5f, 1f)); }

[KSPEvent(guiName = "Quality --", guiActive = false, guiActiveEditor = true)]
public void QualityDecrease() { AdjustMultiplier(-0.1f * UnityEngine.Random.Range(0.5f, 1f)); }

private void AdjustMultiplier(float delta)
{
_multiplier = Mathf.Clamp(_multiplier + delta, 0f, 2f);

if (_multiplier > 1.2f)
Quality = "Great";
else if (_multiplier > 0.9f)
Quality = "Average";
else if (_multiplier > 0.7f)
Quality = "Not good";
else if (_multiplier > 0.4f)
Quality = "Hazardous";
else Quality = "Fire QA team";

Quality = string.Format("{0:P2} - {1}", _multiplier, Quality);

GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
}

public float GetModuleCost(float defaultCost)
{
return _multiplier * defaultCost;
}
}

Link to comment
Share on other sites

I do it here to assign a key for my Vertical Velocity Mod:

https://github.com/SirDiazo/TWR1/blob/master/TWR1/TWR1.cs#L376

Hope that's close enough to help,

D.

Alright, thanks!

So I tried your Vertical Velocity mod to see how it works and it didn't catch an actual key most of the time.

It only worked after a few tries of clicking on the "change key" button and pressing a key.

Also shouldn't the check part be inside Update()?

Link to comment
Share on other sites

Hmmm, something must have changed on me, I have not touched that part of the code in forever.

Doing a quick test, it works as expected on my end, I can't even take a guess why it's not working on your end. If you want to troubleshoot, stick a "Debug.Log("Last Keycode: " + Event.current.keyCode.ToString());" just above the "if(TWR1SettingKey)" line and see what KSP sees for keypresses when are trying to assign the key.

As for doing it in OnDraw vs Update, when I googled around I was not able to find a difference between the two in terms of behavior/performance so it was simpler from a code perspective to put it in OnDraw.

D.

Edited by Diazo
Link to comment
Share on other sites

As for doing it in OnDraw vs Update

If the rendering manager is anything like OnGUI (which since it uses Unity's GUI functions, it just about has to be the same), it gets called multiple times per frame (IIRC, it's atleast twice). Update is always once per frame.

Link to comment
Share on other sites

As for doing it in OnDraw vs Update, when I googled around I was not able to find a difference between the two in terms of behavior/performance so it was simpler from a code perspective to put it in OnDraw.

OnDraw is really MonoBehaviour.OnGUI

The difference is that OnGUI might be called multiple times in a frame for each event while Update will be called once per frame. If you want to use Event.current, OnGUI is the right place (Event.current is otherwise null). Otherwise you'd need to use Input which, for this particular problem, is not as straightforward. I'd say you've got it right as-is

Edit: sniped by Crzyrndm ;)

Link to comment
Share on other sites

How to get my plugin to be reloaded?

As I'm developing my plugin, I naturally make changes. How do I get KSP to load the new version of the plugin? Quitting to the main menu doesn't seem to be enough. Quitting and restarting the game entirely works of course, but that takes a long time. Surely, there is a better way? ... right?

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