Jump to content

Trigger a part's action from code?


Recommended Posts

edit: Answer from the end of the thread added in.

Alight, here is the absolute basic way to trigger a part's action. Note pretty much everything is hardcoded to make the example simpler and uses simple for-each loops to make it clear what is going on. You will want to customize to work with whatever mod you are writing.

A big shout-out to Faark for the help with this.


public void Update()
{
foreach (Part p in FlightGlobals.ActiveVessel.Parts) //start cycling through parts on the active vessel
{
if (p.name == "solarPanels1") //find the solarPanel1 part
{
foreach (PartModule pm in p.Modules) //start cycling through partmodules on the solarPanel1
{
if (pm.moduleName == "ModuleDeployableSolarPanel") //find the 'ModuleDeployableSolarPanel' partmodule
{
BaseActionList bal = new BaseActionList(p, pm); //create a BaseActionList bal with the available actions on the part. p being our current part, pm being our current partmodule
if (bal.Count > 0) //oops, left over from earlier testing, the ModuleDeployableSolarPanel always has 3 actions
{
foreach (BaseAction ba in bal) //start cycling through baseActions in the BaseActionList
{
if (Trigger && ba.guiName == "Extend Panel") //Trigger is a bool set to true via a GUI button on-screen (code not shown)
{
print("Try Extend");
KSPActionParam ap = new KSPActionParam(KSPActionGroup.None, KSPActionType.Deactivate); //an important line, see post
ba.Invoke(ap); //Invoke the "Extend Panel" command (our current ba. variable) with the ActionParameter from the previous line.
Trigger = false; //command executed, set Trigger false for next GUI button click
}
if (Trigger2 && ba.guiName == "Retract Panel") //same as above, for the Retract Panel action
{
print("Try Retract");
KSPActionParam ap = new KSPActionParam(KSPActionGroup.None, KSPActionType.Deactivate);
ba.Invoke(ap);
Trigger2 = false;
}
}
}
}
}
}

}
}

The KSPActionParam is deceptively important. When you make the ap variable to use, you tell it the KSPActionGroup to use. As I'm trigger things manually with code, I never used anything except KSPActionGroup.none.

The KSPActionType is a bit tricky as well. If you are executing a single direction command (such as Extend, or Retract) this actually does not matter. However, a dual direction command (such as Toggle Panels) works off this.

On my test solar panel KSPActionType.Activate on the TogglePanels action would extend the panels and KSPActionType.Deactivate would retract the panels.

Executing the TogglePanels action with KSPActionType.Activate a second time did nothing.

So, here are the basics on activating part actions, hope this helps you out too.

D.

***** Begin original post. *****

Alright. I'm looking for opinions on how different people do things with how they handle commands between parts.

First, some background.

I'm looking into making more action groups available but due to how KSP handles its default groups I'm having to write a separate action group manager that will run in parallel with the default groups.

This means I need to dynamically find what Commands are available from parts on the vessel in order to present them to the player to assign to Action Groups.

I've been using the solarPanel1 that is stock for testing.

There are two promising lists, PartModule.Events and PartModule.Actions.

(Note that Part.Events and Part.Actions are both empty.)

From here on when I say "solarPanel1", read that as me saying "solarPanel1.ModuleSolarPanel".

solarPanel1.Events has "Extend" and "Retract", solarPanel1.Actions has "ExtendPanelAction", "ExtendPanel", and "RetractPanel".

Looking at the solarPanel1 in the VAB, there are 3 Commands available to be assigned to an Action Group, "Toggle", "Extend" and "Retract".

So this looks like the solarPanel1.Actions is what I want to look at but I have not figured out how to issue an Action command yet to see if "ExtendPanelAction" is the same thing as the "Toggle Panel" that shows in the VAB.

I am able to issue Event commands and the "Extend" and "Retract" event do in fact open and close the solar panel.

There is a 3rd possibility as well, there are three methods "solarPanlel.ExtendPanel()", ".RetractPanel()" and ".TogglePanel()" that look exactly like what I need. However, I am at a total loss on how to list the methods available to a partmodule during run time and how to tell which methods are the Command methods that I would show in my action groups mod.

So, for all you mod devs out there, when you add fancy commands to your parts, are you adding an Action or an Event? I am trying to make sure this action group mod is compatible with everyone else's mod right out of the box.

D.

Edited by Diazo
Link to comment
Share on other sites

Actions are what actions groups use, Events are what GUI-stuff uses. The only mentionable difference is that Actions have an additional argument (KSPActionParam), but i guess that's mostly ignored and both use the same code underneath.

Anyway, you appear to miss the actual points about .Events & .Actions. Those do all the heavy work for you. Just enumerate though all of BaseActionList's BaseAction's and use those objects. It offer's name, guiName and an Invoke(KSPActionParam)...

ps: I'm looking forward to see your hopefully used-friendly UI. If you need your own in the first place, it would be nice to also include stock - action groups... and thus make it another "in flight action group manager" as well. Also it would be nice to have UI to call action groups only for a specific part of the vessel, bot "actions only for all parts of a kind" and "group only for part that was launched as X" (should be possible to distinguish them, e.g. via missionId)

Edited by Faark
Link to comment
Share on other sites

BaseActionList? I saw that in the Object Browser but assumed it was a template list type thing similar to how KSPActionGroup is an enum template for the default action groups and did not investigate. Apparently I should have.

And yes, the UI will support both the 10 built in groups and filtering in flight mode so hopefully that includes what you are hoping to see.

Thanks for the tip.

D.

Link to comment
Share on other sites

Pretty much everything that I make with a KSPEvent also gets a KSPAction, the Action usually just points to the Event. If there's ever a situation where both aren't used it's usually the Event that I take out, I can imagine people doing the opposite though.

I suppose one difference is that Events include all of the GUIActiveUnfocused stuff, like EVA events, or select target events, but I'm not sure there's ever a real reason to assign those to action groups.

Link to comment
Share on other sites

Okay, BaseActionList is what I was after.

I have a list of Actions and the GUI friendly name to display, but now how do I trigger one of these Actions?

I'm not stuck yet having only spent 10 minutes on it, but this is not looking as straightforward as I was hoping it would be.

Any help is always appreciated. :)

D.

Link to comment
Share on other sites

You select all BaseActions you want to fire your action group and call their Invoke's. Every PartModule for every part has its own BaseAction, just loop though it how ever you stored your action group and Invoke them. A stupid example might look sth like that:


KSPActionParam ap = new KSPActionParam(KSPActionGroup.None, KSPActionType.Activate);
foreach (var actionBase in FlightGlobals.ActiveVessel.Parts
.Where(p => /*is solar panel i want to toggle*/)
.SelectMany(p => p.FindModulesImplementing<ModuleDeployableSolarPanel>())
.Select(modDepSolarPanel => modDepSolarPanel.Actions[/*name of my action, i guess "ExtendPanelsAction" */]))
{
actionBase.Invoke(ap);
}

Link to comment
Share on other sites

Thank you very much for that Faark, you just saved me more then a few hours of figuring that out.

I've updated the first post with my findings to hopefully allow this thread to be found by the next person who is searching for this info.

D.

Link to comment
Share on other sites

Great to hear it's working as expected. Hope your mod will be very easy to use.

Btw, you don't have to create another instance of BaseActionList. Every Part (though barely used) & especially PartModule already has one of those (.Actions) and creating them seems pretty expensive, so you might want to use the existing ones. (i rly hope KSP don't use reflection every time a vessel is loaded and instead copies the existing list from a prefab)

Link to comment
Share on other sites

Hmmm.

Thank you for that reminder, I'll switch to using PartModule.Actions.

However, Part.Actions is null on the solarPanel1 part. This is in the same update frame as when I'm referencing the ModuleDeployableSolarPanel.Actions so I'm not sure what is going on there.

D.

edit: Interesting....

It looks like Part.Actions is orphaned and not used, I can populate it myself for this. We'll see how this goes.

Edited by Diazo
Link to comment
Share on other sites

Edit: Nevermind, this is a way of declaring actions, you are looking for a way to finding and triggering another parts actions.

I've found an easier way to do this, inside the partmodule

[KSPAction("Deploy", KSPActionGroup.None)]
public void DeployAction(KSPActionParam param) {
this.Deploy ();
}

[KSPEvent(guiActive = true, guiName = "Deploy")]
public void DeployEvent() {
this.Deploy ();
}

public void Deploy() {
//code
}

[KSPAction("Deploy", KSPActionGroup.None)]

goes infront of the function you want to trigger with the parts "Deploy" action (or whatever you want to call it)

[KSPEvent(guiActive = true, guiName = "Deploy")]

goes infront of the rightclick on part menu while in flight.

Edited by mindstalker
Link to comment
Share on other sites

While the code shown works within a mod you are writing where you know the name, for my purposes this line

public void DeployEvent()

breaks things because I don't know the method names.

I have to pull the name of the Actions dynamically in code and I'm under no illusions that the different mod makers followed any sort of pattern for making the partModule.Action.name and the method name that invokes that action consistent.

Even in Squad's parts it is not consistent. My test solar panel has "Extend Panel", "Retract Panel" and "Toggle Panels" as the method names, note that only the Toggle Panels action is plural.

So that leaves me a few more hoops to jump through because I have to build my action list dynamically as compared to a mod that is self contained and the method names are known.

D.

Link to comment
Share on other sites

Even in Squad's parts it is not consistent. My test solar panel has "Extend Panel", "Retract Panel" and "Toggle Panels" as the method names, note that only the Toggle Panels action is plural.

Wow, they really are. I never noticed when setting up my action groups in the VAB^^

Though i don't see a problem with his DeployEvent(...). An UI label like KethanDrillXXL->Deploy should be easy enough to understand. Unless ofc the part creator did sth really crazy... but since you have the same data as KSP has for its action group manager, it would mean this parts action groups are crap anyway, even without your mod.

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