Jump to content

PartModule - I'm confused.


Recommended Posts

Perhaps I'm not understanding correctly but I was under the assumption that when the partmodule class was used that it was only called when that part was found on the active vessel. According to my log file, it's being called on any vessel within 2km of the vessel with the part.

For example: I have an aircraft landed on a vessel. The vessel has a partmodule called MPSub with 2 values. If I go straight to the aircraft, it's finding the partmodule and the values and applying them to the aircraft. I'm confused. Why?


public class MPSub : PartModule
{
[KSPField]
public bool manageIntakes = false;

[KSPField]
public bool manageThrottle = false;

bool intakesOpen = true;
bool hasSplashed = false;
bool checkOnce = false;

public override void OnStart(StartState state)
{
MPLog.Writelog("[Maritime Pack] Sub Found");
if (manageIntakes)
{
MPLog.Writelog("[Maritime Pack] Intakes Enabled");
}
if (manageThrottle)
{
MPLog.Writelog("[Maritime Pack] Engines Enabled");
}
}
}

Link to comment
Share on other sites

No, as PartModule is used for any part in any vessel (engine, wheel, tank, asteroid, even kerbal on EVA), the class is called for every vessel that are within physic range, or else they can not be act upon( or even loaded). If you want your plug-in to be activate only for the active vessel, you need to call the bool IsActiveVessel.

Edited by Hary R
Link to comment
Share on other sites

No, as PartModule is used for any part in any vessel (engine, wheel, tank, asteroid, even kerbal on EVA), the class is called for every vessel that are within physic range, or else they can not be act upon( or even loaded). If you want your plug-in to be activate only for the active vessel, you need to call the bool IsActiveVessel.

So if I read you correctly, it should be this:


public override void OnStart(StartState state)
{
if (!vessel.isActiveVessel)
{
return;
}
MPLog.Writelog("[Maritime Pack] Sub Found");
if (manageIntakes)
{
MPLog.Writelog("[Maritime Pack] Intakes Enabled");
}
if (manageThrottle)
{
MPLog.Writelog("[Maritime Pack] Engines Enabled");
}
}

Which brings up another question. If OnStart is only run once and the part isn't on the active vessel, which method should be used to recheck the partmodule should the user switch to that vessel? OnAwake or OnActive?

Or, do I just detect the partmodule settings in OnStart and then check the isActiveVessel in OnUpdate?

Rather confusing how this works.

Edited by Fengist
Link to comment
Share on other sites

You should only have code in OnStart that needs to happen for every vessel, that way you don't run into any issues. In OnUpdate, there can be code that only happens for the active vessel, and code that happens for every vessel, like this:


public override void OnStart(StartState state)
{
//onstart code
}
public override void OnUpdate()
{
// whatever code you need to run on every vessel

if (!vessel.isActiveVessel) {
return;
}

// whatever code you need to run on only the active vessel
}

There's also the GameEvents class, where you can listen for events to see if the active vessel changes, like this:

GameEvents example:


[KSPAddon(KSPAddon.Startup.Flight, false)]
public class GameEventSubscriber : MonoBehaviour
{
void Start()
{
//this event is the onHideUI event (activated when F2 is pressed to hide the UI)
GameEvents.onHideUI.Add (OnHideUI);
}
void OnDestroy()
{
//this part is important too!
GameEvents.onHideUI.Remove(OnHideUI);
}




void OnHideUI()
{
Debug.Log("OnHideUI");
}
}

Edited by MrHappyFace
Link to comment
Share on other sites

I think what I'm seeing is this then:

I need to locate all the key/value pairs in the partmodule OnStart. That'll find all of them from any vessel in range. If I come in range of another vessel, it'll run OnStart again. From there, in my OnUpdate or FixedUpdate, I need to use the isActiveVessel to determine if that partmodule is on the current vessel or one nearby.

And wow, hadn't looked at GameEvents before. Lots of triggers in there.

Thanks.

Link to comment
Share on other sites

If I come in range of another vessel, it'll run OnStart again.

This line isn't the clearest but be careful because you do need to be careful keeping track of which part (and partModules) are loaded.

A different copy of your PartModule loads for each part it is attached to. If you have 2 vessels with your partModule on them, one being the active vessel and one being out of range, the OnStart() will run in the partModule on the active vessel when you load into it when switching from space center to flight.

As you approach the second vessel, at about 2km, that vessel will load into the flight scene and the OnStart() in the partModule on the second vessel will run, the OnStart() on your active vessel will not run a second time.

Note that this means most of the time when you are writing code for a partModule, you should use this.vessel instead of FlightGlobals.ActiveVessel. The this.vessel reference will look at the vessel your partModule is attached to, FlightGlobals.ActiveVessel will always look at the currently active vessel even if the partModule in question is on a different, nearby, vessel.

D.

Edited by Diazo
Link to comment
Share on other sites

This line isn't the clearest but be careful because you do need to be careful keeping track of which part (and partModules) are loaded.

A different copy of your PartModule loads for each part it is attached to. If you have 2 vessels with your partModule on them, one being the active vessel and one being out of range, the OnStart() will run in the partModule on the active vessel when you load into it when switching from space center to flight.

As you approach the second vessel, at about 2km, that vessel will load into the flight scene and the OnStart() in the partModule on the second vessel will run, the OnStart() on your active vessel will not run a second time.

Note that this means most of the time when you are writing code for a partModule, you should use this.vessel instead of FlightGlobals.ActiveVessel. The this.vessel reference will look at the vessel your partModule is attached to, FlightGlobals.ActiveVessel will always look at the currently active vessel even if the partModule in question is on a different, nearby, vessel.

D.

Thanks!

The way you describe the OnStart is pretty much what I was seeing happen. Though it didn't actually work, I was attempting to shut the throttle down on my sub once it went over 2m altitude to keep it from flying. As I tried to land a VTOL on it, it shut that throttle down too once I got close... which is why this thread is here.

I think I understand the difference now between this. and flightglobals. They'd both have the same effect on the active vessel but this. would apply to any vessel in range with that partmodule.

I've seen this. used in other instances, like in monobehavours and to be honest, it's pretty confusing exactly what it's referencing.

Link to comment
Share on other sites

You are slightly off on how this. works.

In C#, this. refers to the object you are currently running within. So when you use this.vessel inside your partModule code, you are referencing the partModule.vessel object. Note it is only on the partModule executing the code, not all loaded partModules as you say in the previous post.

Now, on the behavior you are seeing where the VTOL's engines are getting shut down, I can think of two things:

1) Both vessels are referencing the same throttle (probably the main throttle controlled by shift/ctrl?) so when the Sub's throttle shuts down, it carries over the VTOL.

2) The throttle control code is running on both vessels. So at the VTOL approaches the sub, it's flight conditions trigger the throttle control code and it shuts the VTOL's throttle down.

Would need to see some code to see what is going on though.

D.

Link to comment
Share on other sites

You are slightly off on how this. works.

In C#, this. refers to the object you are currently running within. So when you use this.vessel inside your partModule code, you are referencing the partModule.vessel object. Note it is only on the partModule executing the code, not all loaded partModules as you say in the previous post.

Now, on the behavior you are seeing where the VTOL's engines are getting shut down, I can think of two things:

1) Both vessels are referencing the same throttle (probably the main throttle controlled by shift/ctrl?) so when the Sub's throttle shuts down, it carries over the VTOL.

2) The throttle control code is running on both vessels. So at the VTOL approaches the sub, it's flight conditions trigger the throttle control code and it shuts the VTOL's throttle down.

Would need to see some code to see what is going on though.

D.

Harry R's post helped me fix it. I wasn't using this.isActiveVessel so it was shutting down the throttle on every vessel close by. Or rather, it was setting the visible throttle to 0 but you could still throttle up, which I don't fully understand.

Here's the code I'm using now which seems to work.


if (manageThrottle && vessel.isActiveVessel && this.vessel.mainBody.ocean)
{
if (this.vessel.altitude > 2.0)
{
FlightInputHandler.state.mainThrottle = 0.0f;
MPLog.Writelog("[Maritime Pack] Engines Disabled @ altitude " + this.vessel.altitude);
}
}

manageThrottle is a partModule setting.

I initially tried to go through each engine part and shut them down individually but, I'm using Firespitter's electric engine mod to propel this thing and it isn't recognized as a ModuleEngine.

Link to comment
Share on other sites

I recently ran into this fixing a bug and found isactivevessel not always accurate depending on where you are checking. I.e.:onstart. I found checking this.vessel.id == flightglobals.activevessel.id worked much better and always accurate

Link to comment
Share on other sites

Alright, it looks like you have it working but there are two things I'm going to point out:

The actual throttle for a vessel is: this.vessel.ctrlState.mainThrottle (this is a partModule). It is just for the FlightGlobals.ActiveVessel, the FlightInputHandler.stat.mainThrottle value you are using has priority and overrides it.

Your current code will only control FlightGlobals.ActiveVessel, if you use vessel.ctrlStat.mainThrottle you can use your code on nearby vessels that don't have focus.

The other thing I will point out is that while FireSpitter's engine doesn't use the ModuleEngine partModule, it almost certainly inherits from it, so you can use the isAssignable method to check if it does.

D.

Link to comment
Share on other sites

I recently ran into this fixing a bug and found isactivevessel not always accurate depending on where you are checking. I.e.:onstart. I found checking this.vessel.id == flightglobals.activevessel.id worked much better and always accurate

Humm... I'll have to look over my code. I think I looked at putting isactivevessel in my onstart and it just didn't seem right. But thanks. I released my plugin with my new parts pack so I should know in the near future if I screwed that up.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

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