• Joining the dots... The Mission System


    TriggerAu

    Obviously one of the core components of the Making History Expansion is the Missions themselves. Here you can read some information and get some insight (I hope) about building missions and how the MissionSystem manages these behind the scenes.

    This blog did end up a bit long, but it hopefully is all interesting

    What makes a Mission?
    In a nutshell (love that term) a mission is a series of nodes and connections where the player starts at the origin and can follow the paths from node to node until they hit an ending. For the programmatically inclined this is, in essence, a Finite State Machine (or FSM).

    ...warning dev type words ahead…
    In the mission system we do something a little different to a traditional FSM in that we don’t store every transition in the persistence. We added some logic to the nodes so that a node can be flagged as a “catch all” - which means that the mission can transition to this node from any other node. This means we can store more information in a mission file without needing to store every transition individually, and yet still unpack it to be used like an FSM in the game itself.

    So in FSM parlance the Nodes are a state and Connectors are the transitions. The game then has a parsing engine that keeps track of each mission and handles the update loops that are used to progress each mission between nodes. And the Active Node is the active state.

    It’s at the core of how a mission is played once its put together, and below well get into some of these details.

    AnnotatedImage.png
    What is the MissionSystem?
    The MissionSystem is that parsing engine I mentioned just before, It is the main class that manages missions and technically it’s what’s called a Scenario module in KSP. It loads the mission components from a save and then handles processing them and tracking where the mission is up to, when it should change nodes and when to trigger actions. Other Scenario modules in KSP include the ContractSystem, the FundingSystem, CommNetScenario, hopefully your seeing a pattern here - all things that run as components of a game and are used to load and save persistent data - then handle it during game play.

    Travelling between Nodes
    So let’s keep that terminology (of an FSM) in mind as we progress a bit further. At any point in our mission there is always a single Active Node (like states in an FSM) - it’s like highlander in that “there can be only one”.

    The MissionSystem then needs to check whether it is time to move to a new node from this one. To do this the mission system sequentially checks the nodes that the ActiveNode is connected to - this includes the nodes directly connected and any catch all nodes.

    How does the mission system know when it’s time to change nodes? Each node can have a number of modules attached to it and these help it to understand when that transition should happen as well as anything to do after the active node changes:

    The checks for when to change node are handled by the TestModule: 

    • A TestModule is a class that defines logic that is tested and returns True when the test passes.
      • Each Node can have one or more TestGroups, and each TestGroup contains TestModules. 
      • Once all the TestModules in any TestGroup return True that node will activate and the missions Active Node changes. 
      • If a Node has no TestGroups/Modules it will be true immediately
    • The actions that occur when a node activates are handled by the ActionModule:
      • Each node can have one or more ActionModules attached.
      • These “Fire” when the node activates - but this doesn’t mean you can’t use programming structure like co-routines to have these fire immediately and perform long running actions.

    Now that we’ve seen the Nodes and Connectors we need the third leg of our milking stool - the Active Node. The MissionSystem looks at the active node in each update loop and checks all of the nodes that it can move to. This means any node that has a connection from the active node and any catch all nodes.

    Other Bits and Pieces
    But what about these other things I see in the Builder? what is a docked node? how do I see whats a catch all node? Well as they say a picture is worth a thousand words (although with localization that number is probably rounded) so here’s some points of things I’ve found helpful and interesting:

    The Start Node:
    Hopefully the name gives it away, but in any case this is the Active Node when a mission first starts. The mission system always starts here and then tests the connected nodes. 

    Spawnable nodes can be docked to the Start Node (only these types of nodes and no others). The first spawn vessel node docked to the start node is the starting vessel for the mission

    DockedStartNode.png
    Docked Nodes: 
    This is a special kind of connection in that the docked node will be tested once only when the parent node (the one it is docked to) is activated. It’s a great construct to help you do things like give various scoring adjustments when a node is activated, or change the path of a mission at a specific point in time.

    So let me give you an example of that one:

    DockedNodes.png
    Assuming that the Go to node shown as 1 is connected to the active node, then when “My Other Vessel” reaches that location:

    • The GoTo Node will become the active node. 
    • The system will then check if the MET is less than 2h, if it is that node becomes active and no other docked nodes are tested
    • If not then the MET < 3h30m is tested, if thats true then  that node becomes active and so one
    • If any of the docked nodes is true then the connected action nodes will fire immediately adjusting the score
    • then the player needs to get to 5000m above sea level to proceed further.


    Catch All Nodes:
    These are nodes that have no specific connection to their input pin. They will be tested regardless of which node is the Active Node.

    From our original annotated image you can see the catch all node there - a Vessel destroyed - which means that if at any time in the mission “Trigger’s Vessel” is destroyed then that node will activate.

    AnnotatedImage.png

    Connection Test Orders:
    How do you know what order the MissionSystem will check which node is next? For docked nodes it should (hopefully) be visually obvious - its the order they are docked, but when there are multiple connections the order can be found (and adjusted) in the node Options in the Settings Action Pane (the SAP - in the top right of the Builder)

    We’ll combine this idea with the next ones...

    Some other Node things:
    Activate Once Only - This setting is on by default, to help prevent infinite loops, but with careful work you can disable this to use some rudimentary loops in missions.
    Always True Nodes - These nodes can be used for logic structures to make things move along
    Always False Nodes - You can use these to mislead your players - yeah I said it - to change what they think the goal may be.

    ExplodyLoop.png
    This one needs explanation I know - I’ve color coded the paths to help. Let’s say you want to direct a player to EVA from one vessel and then get into the Mk1Pod in a nearby vessel. But, you want to add some pressure by blowing solar panels off the vessel until they get there (dont ask me why, maybe your that kind of kerbal). Heres how this solution for that works:

    • Your player gets to Node A by EVAing a kerbal 
    • The mission moves immediately to Node B (cause its always true) and we have also set it to be able to activate multiple times so we can loop back to it.
    • From B it tests the nodes according to the order configured in Node B via its Node Connections Order (as below)
      ConnectionOrder.png
    • So it tests if the Crew boarded the target part, then tests if its been 120 secs since we EVA’d, and so on..
    • Let’s assume we reach the 31 second mark.. The mission then moves to node C (via the blue line) and then explodes one of the solar panels off the vessel
    • It then activates Node B again and starts testing again.

    So every thirty seconds we blow a panel off the vessel until either a) they reach and board the Mk1 pod, or b) they take too long and we find something else nasty to do.


    The End
    I know this one has been a bit long, but hopefully I’ve given you some insight and information into some of the workings and possibilities with the Making History Expansion and Missions. Catch you next time.

     

     

     

    Edited by TriggerAu

    • Like 20


    User Feedback

    Recommended Comments

    Could´ve used that a couple years ago when i learned all about state machines at university :D This is a great example.

    Also makes the mission builder a lot more versatile :) The more i play with it the more i like it

    • Like 1

    Share this comment


    Link to comment
    Share on other sites

    Explaining how the docked nodes work makes it possible to form an "else", I think, which is something I've been wanting.  (As in "invert whatever this other test is" without having to explicitly re-write a new test that happens to be the opposing condition.)

    Would this work:  I make an "always true" node that's the header, with two nodes docked underneath it - the first one is the "if" test node (altitude test, location test, whatever), and the second one is another "always true" node.  Thus it only falls through to the second node, the"always true" node, if the first node fails.  That "always true" node becomes the "else".

     

    • Like 1

    Share this comment


    Link to comment
    Share on other sites
    2 hours ago, Steven Mading said:

    Explaining how the docked nodes work makes it possible to form an "else", I think, which is something I've been wanting.  (As in "invert whatever this other test is" without having to explicitly re-write a new test that happens to be the opposing condition.)

    Would this work:  I make an "always true" node that's the header, with two nodes docked underneath it - the first one is the "if" test node (altitude test, location test, whatever), and the second one is another "always true" node.  Thus it only falls through to the second node, the"always true" node, if the first node fails.  That "always true" node becomes the "else".

     

    yep, but you could also do it without the always true docked node.

    As it only tests when the parent node is activated it would reach the true node, test the docked node and then progress down that path if its true, else it will follow the out connector from the parent node.

    Ill draw it up in game tonight when Im home

    Share this comment


    Link to comment
    Share on other sites

    Wait, if it's truly an FSM with only one active node at a time, doesn't that mean that activating a "Catch All Node" should break the program and prevent it from continuing, because it can't fork the path into two simultaneously active nodes?  But the main pathway does seem to resume afterward.  How?  Let's say you have a catch-all-node, that starts a chain of 2 other nodes, and then the path just stops without any mission end node or any explicit path linking back to the main program.

    It appears to return back to the main pathway after finishing that chain of 2 nodes, continuing from right where it got interrupted, as if it was returning from a subroutine.  How does it remember where to go back to?  Wouldn't a true FSM forget that?  If the Catch-all-node behaves like a subroutine that returns to where it got called from, that wasn't made clear by the UI text explaining things.

     

    Share this comment


    Link to comment
    Share on other sites

    @TriggerAu ... It would have been nice to allow a player to execute a mission normally and have it concurrently "recorded" as a mission file for post editing.

    This might have required the player to indicate that the mission was to be recorded prior to the start of the mission - a small price to pay/play.

    Can you consider this? Or at least reflect on the complexities considering your current mission architecture schema?

    NOTE: I have not yet dived into the mission editing environment, so if this is already available then please either insult me or ignore me - either one is acceptable. :wink:

     

     

    Edited by Wallygator

    Share this comment


    Link to comment
    Share on other sites
    On 3/22/2018 at 8:57 AM, TriggerAu said:

    yep, but you could also do it without the always true docked node.

    As it only tests when the parent node is activated it would reach the true node, test the docked node and then progress down that path if its true, else it will follow the out connector from the parent node.

    Ill draw it up in game tonight when Im home

    Heres what it would look like for testing LF >100 else

    image.png

     

    17 hours ago, Steven Mading said:

    Wait, if it's truly an FSM with only one active node at a time, doesn't that mean that activating a "Catch All Node" should break the program and prevent it from continuing, because it can't fork the path into two simultaneously active nodes?  But the main pathway does seem to resume afterward.  How?  Let's say you have a catch-all-node, that starts a chain of 2 other nodes, and then the path just stops without any mission end node or any explicit path linking back to the main program.

    It appears to return back to the main pathway after finishing that chain of 2 nodes, continuing from right where it got interrupted, as if it was returning from a subroutine.  How does it remember where to go back to?  Wouldn't a true FSM forget that?  If the Catch-all-node behaves like a subroutine that returns to where it got called from, that wasn't made clear by the UI text explaining things.

     

    The active node wont come back to the other "path" from a catch all unless there is a connection. You can think of a "catch all" node as a Node that has connections from every other node in the mission (except for itself and the spawn nodes docked to the start node)

    If you have a plan like this and destroy the vessel before getting to orbit then the player will get the CRASHED dialog but the mission will be stuck there

    image.png

     

    hint if you run the validator it will tell you that the node has no end setting and no output!

    image.png

     

    11 hours ago, Wallygator said:

    @TriggerAu ... It would have been nice to allow a player to execute a mission normally and have it concurrently "recorded" as a mission file for post editing.

    This might have required the player to indicate that the mission was to be recorded prior to the start of the mission - a small price to pay/play.

    Can you consider this? Or at least reflect on the complexities considering your current mission architecture schema?

    NOTE: I have not yet dived into the mission editing environment, so if this is already available then please either insult me or ignore me - either one is acceptable. :wink:

    Is a cool idea, and one that I do recall being mentioned in the early days, but we went down the road of visual programming/flow chart after plenty of discussions.

    The complexities (to use your term :P ) that I recall from the discussions about that approach were in two parts. The first being that you need to set up the capture of objectives and details for the mission - lets say landing on the Mun at a certain spot - so the creator would need to complete the mission and interact with a recorder along the way that garbs various configurable values. Using the landing point as a specific example if they then didn't land exactly where they wanted to set the target then we'd also need an editing interface to adjust the values after the recording. In essence the editing interface is the Mission Builder, and we added enough (we think) visualization in there to be able to.

    The second being the time taken and process - if you have a really complex mission you would probably plan that out somewhere to then play it to record. Which is effectively what you can do with the Mission Builder. You plan it out using objectives and then use the Test function to fly the mission. If you get half way through and want to tweak it you jump back from test mode to the builder make some tweaks and then resume the mission testing from a checkpoint (or form the start if you want) to save the creator time.

    Not saying its not an idea we wouldn't ever come back to (cause it is pretty cool) or that a modder couldn't make a recorder either (don't quote me on that one though as that wasnt a modding idea I had considered till I wrote this sentence!)

     

    Share this comment


    Link to comment
    Share on other sites
    3 hours ago, TriggerAu said:

    Not saying its not an idea we wouldn't ever come back to (cause it is pretty cool) or that a modder couldn't make a recorder either (don't quote me on that one though as that wasnt a modding idea I had considered till I wrote this sentence!)

    I just quoted you.  Make it so! :wink:

     

    • Like 1

    Share this comment


    Link to comment
    Share on other sites

    Thank you!

    As you add more Nodes, in/out pin paths overlap and tracing the flow gets harder.  I would like to see some kind of highlighting for the node connection lines of the selected node. Like the animated arrows used on fuel flow lines, for example.  Overlay some kind of animation ("dancing ants") on the lines, so that complex mission designers can clearly see what feeds into and goes out from the selected node. And/Or - consider adding a cross-hatch pattern to node borders of nodes connected to the selected node, with one style used for nodes-as-input, and (perhaps) another pattern for nodes-as-output. (Patterns are helpful for users with color perception issues.)  

    • Like 1

    Share this comment


    Link to comment
    Share on other sites
    3 hours ago, basic.syntax said:

    Thank you!

    As you add more Nodes, in/out pin paths overlap and tracing the flow gets harder.  I would like to see some kind of highlighting for the node connection lines of the selected node. Like the animated arrows used on fuel flow lines, for example.  Overlay some kind of animation ("dancing ants") on the lines, so that complex mission designers can clearly see what feeds into and goes out from the selected node. And/Or - consider adding a cross-hatch pattern to node borders of nodes connected to the selected node, with one style used for nodes-as-input, and (perhaps) another pattern for nodes-as-output. (Patterns are helpful for users with color perception issues.)  

    Thats a cool visualization, will add that to the feedback list we have if thats cool

    • Like 1

    Share this comment


    Link to comment
    Share on other sites

    @TriggerAu  additionally, I find the visual method of "vertical bracketing" mission objectives in the top level mission screens to be somewhat confusing.  Rather than using nested brackets, perhaps you might allow the player to select (toggle between) a simplified horizontal "path" or "dependency" view that clearly displays the mission flow.  Not all players will begin KSP with a fundamental understanding of implied branching. And a player should not be forced to go into an EDIT screen to fully understand the flow of a mission.

    Don't get me wrong here - what you have done is fantastic - I'm concerned with enhancing the accessibility to players who may initially have totally different perceptual queues - unless the game requires a specific set of perceptual skills to begin with. (left vs right brain thinkers?)

    Perhaps this is an issue you have already deeply thought about. If so, then forget it.

    BACKGROUND NOTE:  I found it initially confusing probably because I stopped programming about 30 years ago. So, it did take a bit of time (for me about 5 minutes which for some folks might be too much of a mountain to cross) to actually figure it out comfortably.  So, hence my immediate concern for folks (not me) who may have NEVER coded or who do not think in similar modes.

    Edited by Wallygator

    Share this comment


    Link to comment
    Share on other sites

    Always looking for improvements @Wallygator . If you don't mind could you give me an example for what you mean by a simplified horizontal path, would be good to see an alternative visualization idea - obviously cant promise well change it, but be good to see as we dont want to stick to a specific method just because thats what came out

    • Like 1

    Share this comment


    Link to comment
    Share on other sites
    19 hours ago, TriggerAu said:

    Always looking for improvements @Wallygator . If you don't mind could you give me an example for what you mean by a simplified horizontal path, would be good to see an alternative visualization idea - obviously cant promise well change it, but be good to see as we dont want to stick to a specific method just because thats what came out

    Let me think on this one a bit...

    Share this comment


    Link to comment
    Share on other sites
    On 25/03/2018 at 8:40 PM, Wallygator said:

     

    On 24/03/2018 at 11:48 PM, TriggerAu said:

    Always looking for improvements @Wallygator . If you don't mind could you give me an example for what you mean by a simplified horizontal path, would be good to see an alternative visualization idea - obviously cant promise well change it, but be good to see as we dont want to stick to a specific method just because thats what came out

    Let me think on this one a bit..

     

    @TriggerAu

    Now that I've poked around a bit in the mission builder, I'm confused... because there is a clear horizontal schema between nodes when a mission is being built... but this transitions into a vertical and bracketed schema when one is viewing/trying to execute a mission.

    I personally (others might disagree) would naturally expect a common visual model that is shared between the two interfaces - albeit the execution view might be much more simplified vs the builder view.

    Was there a specific requirement that dictated this "90 degree flipping" or even a specific need for a "completely different representation" of the mission?

    To me, this is a confusing UX.  Sorry if I'm the only one bringing this up (seems like I am - OK not sorry :wink: )

    Thoughts?

    Edited by Wallygator
    forgot an 'ing'

    Share this comment


    Link to comment
    Share on other sites
    11 hours ago, Wallygator said:

    @TriggerAu

    Now that I've poked around a bit in the mission builder, I'm confused... because there is a clear horizontal schema between nodes when a mission is being built... but this transitions into a vertical and bracketed schema when one is viewing/trying to execute a mission.

    I personally (others might disagree) would naturally expect a common visual model that is shared between the two interfaces - albeit the execution view might be much more simplified vs the builder view.

    Was there a specific requirement that dictated this "90 degree flipping" or even a specific need for a "completely different representation" of the mission?

    To me, this is a confusing UX.  Sorry if I'm the only one bringing this up (seems like I am - OK not sorry :wink: )

    Thoughts?

    I guess that is probably related to the basis for the design/architecture. The "Apps" in KSP all work with vertical lists, and that is a better UX for a long list of items/checklist - thus the app/objective layouts consistent with the other apps

    The Builder is based loosely on the R&D scene and other tools of a similar nature which have that node and line flow. You can make a mission flow down the canvas as well as across, but perhaps you mean how the pins are on the left/right of the node.. It might be interesting to see what it might look like to remove the  pins so the lines flow in any direction directly, or also build out an graphical execution view but it wasnt in scope at the time. Will add some feedback to our list and see if it makes an impression

    Share this comment


    Link to comment
    Share on other sites
    On 09/04/2018 at 12:32 AM, TriggerAu said:

    Will add some feedback to our list and see if it makes an impression

    Nice. Thanks for considering it.

    Share this comment


    Link to comment
    Share on other sites

    You know, when I first heard about this thing, I thought it was going to be a contract builder for use in career mode.

    Oh well...

    Share this comment


    Link to comment
    Share on other sites

    If a node that checks if you are low on fuel is a "Catch All" node that is also allowed to repeat, how does it progress to the next node when the condition that triggered it would continue to persist. For instance, say the next node is to tell you that you are low on fuel and then the 3rd to fill your tank with liquid fuel. As soon as control jumps to the message, you are still low on fuel and it should jump to the fuel check as a Catch All again. How does it ever move on?

    Is there any way we can suspend jumping to any catch all nodes until another specified node is reached? Can't they make a "continue" node to say prevent all "catch all" nodes from triggering until this "continue" node is reached so we can guarantee the execution of all the nodes after it?

    Share this comment


    Link to comment
    Share on other sites
    On 5/4/2018 at 4:05 PM, jclovis3 said:

    If a node that checks if you are low on fuel is a "Catch All" node that is also allowed to repeat, how does it progress to the next node when the condition that triggered it would continue to persist. For instance, say the next node is to tell you that you are low on fuel and then the 3rd to fill your tank with liquid fuel. As soon as control jumps to the message, you are still low on fuel and it should jump to the fuel check as a Catch All again. How does it ever move on?

    Is there any way we can suspend jumping to any catch all nodes until another specified node is reached? Can't they make a "continue" node to say prevent all "catch all" nodes from triggering until this "continue" node is reached so we can guarantee the execution of all the nodes after it?

    if you have a catch all which allows repeats and uses a non-event driven test like fuel level - it will get in a loop yeah, it cant progress. in places where Ive needed stuff like that I dont use a catch all, but have multiple nodes conncted to the fuel level one - but that may not suit every occasion.

    We dont have a "disable/enable" node currently - but thats a pretty cool idea

    Share this comment


    Link to comment
    Share on other sites

    Are there any plan to allow this wonderful tool to be used by people making contract packs for the Career Mode ? While the community has put it blood , sweat and tears behind such efforts we have always struggled without an official system in place.

    Share this comment


    Link to comment
    Share on other sites


    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now