Your First Choice

VNgen actions can do much more than just place visual elements on the screen! Many actions are also interactive, giving players a voice of their own.

VNgen includes actions for creating single-selection menus, aptly named options. By themselves, options only provide an interface for the user to select from a list of items. But by combining options with other functions like vngen_goto and a little custom logic, it is possible to achieve just about any response to user input you desire, including branching narratives, quick-time events (QTEs), and more.

In the previous section, we created a dialog by introducing new code step-by-step. This time, we'll take a look at a complete VNgen option sequence first, then break it down.

Examine the option sequence below:

Example

if (vngen_event()) {
if (vngen_option("options", 960, 540, 1, 1, snd_hover, snd_select)) {
vngen_option_create("option_good", "I'm doing great!", spr_option, spr_option_hover, spr_option_select, 0, 0, -1, fnt_Arial, c_white, trans_slide_right, 1);
vngen_option_create("option_bad", "Well...", spr_option, spr_option_hover, spr_option_select, 0, 100, -2, fnt_Arial, c_white, trans_slide_right, 1);
}
switch (vngen_get_option()) {
case "option_good": vngen_goto("event_good"); break;
case "option_bad": vngen_goto("event_bad"); break;
}
}
if (vngen_event("event_good")) {
vngen_text_replace("text", "John Doe", "I'm doing great!", inherit, inherit, 2);
}
if (vngen_event()) {
vngen_script_execute(vngen_goto, "event_complete");
}
if (vngen_event("event_bad")) {
vngen_text_replace("text", "John Doe", "Not so great, I'm afraid...", inherit, inherit, 2);
}
if (vngen_event("event_complete")) {
vngen_text_replace("text", "Jane Doe", "I see.", inherit, inherit, 2);
}

It might seem complex at first, but take it event-by-event and you should find you're already familiar with most of the process!

A complete dialog option sequence consists of three phases:

  1. Obtaining user input (the choice)
  2. Responding to user input (the condition)
  3. Providing user feedback (the result)

You may notice these phases resemble the phases of a Quantum action as outlined in Intro to qScript. Indeed, you can think of options as a single action spread across multiple events.

Let's break down each step in detail.

The Choice

The vngen_option script is an action which behaves like a sub-event. It does not replace vngen_event and must be nested inside an event just like any other action. At the same time, however, it possesses its own sub-actions which cannot be run outside the context of vngen_option. Think of a group of options as a single unit--because that's exactly how VNgen sees it!

Here we have an options menu with two options to choose from:

Example

if (vngen_event()) {
if (vngen_option("options", 960, 540, 1, 1, snd_hover, snd_select)) {
vngen_option_create("option_good", "I'm doing great!", spr_option, spr_option_hover, spr_option_select, 0, 0, -1, fnt_Arial, c_white, trans_slide_right, 1);
vngen_option_create("option_bad", "Well...", spr_option, spr_option_hover, spr_option_select, 0, 100, -2, fnt_Arial, c_white, trans_slide_right, 1);
}
}

To simply display a menu, this is all the code we need: one instance of vngen_option as the parent, and one or more instances of vngen_option_create as the child. Although each option has its own unique properties, some are also shared with other options as a group.

For example, note that both scripts have their own ID. The vngen_option ID identifies the whole group, and can be used to retrieve the selected option later. That option is identified by the vngen_option_create ID, used to distinguish which option from the group the user selected.

Other arguments similarly complement each other between scripts. The first two arguments following the vngen_option ID specify the X and Y position to display the whole group on the screen, with the X and Y values in vngen_option_create being relative to the group's coordinates. The next two values of vngen_option set delays before and after child options are created, but each child instance of vngen_option_create can also set its own transition and duration. Finally, the two sound effects supplied to vngen_option are played when an individual option is hovered or selected.

As you can see, vngen_option and vngen_option_create really are inseparably linked!

tip

For details on the other properties of these scripts, be sure to check out the full reference guide. In the meantime, you will notice they share a lot in common with text actions you've already learned!

The Condition

As mentioned previously, once the user has input their choice, the selected option's ID will be stored in memory for future use. No other action is taken automatically, which is by design. It's up to you to use user input however you see fit. The possibilities are practically endless, but the most common way to take action in response to selected option data is through conditional statements such as if or switch.

Example

switch (vngen_get_option()) {
case "option_good": vngen_goto("event_good"); break;
case "option_bad": vngen_goto("event_bad"); break;
}

For those not familiar, a switch statement is simply a series of if statements strung together in a single group. One condition is tested against multiple cases, and whichever case is found to be true is executed until the break statement is reached.

In this scenario, we use the vngen_get_option script to retrieve the ID of the most recently-selected option and jump to different Quantum events depending on which was selected. (Note how the cases here match the IDs of the options created in the first phase).

By default, the most recent selection will remain in memory until another options menu is created, so there's no need to specify the option group ID in this example. However, to protect against endlessly executing the switch statement, vngen_get_option will clear the selection from memory upon running. This behavior can be disabled (see the full reference guide for details), but is generally preferable to guarantee that whatever the result, it will only be triggered once.

note

vngen_get_option is a very special script. While it is not a Quantum action, it does share some behaviors so that it can be used like one. Unlike actions, however, vngen_get_option can be run anywhere in your game--both inside and outside of Quantum events!

For our switch statement, there are only two possibilities: either the user selected "option_good" or "option_bad". These options will run vngen_goto and jump to the event labeled "event_good" or "event_bad", respectively. But again, this is just one common use-case for options. Options can be used to trigger literally any code, even much later in your project. By adding an option group ID to vngen_get_option, you can retrieve any previous selection the user has made, any time!

The Result

Of course, using options to trigger vngen_goto means we must have somewhere for the user to go to! As previously mentioned in Intro to qScript, events can optionally possess labels to make navigating them more memorable. In this case, we can place our "event_good" and "event_bad" labels on events somewhere in the current object or an entirely different one, and our example choice will take us there. The contents of these events will vary, giving feedback to the user that their choice had an impact. This is a tangible result.

Example

if (vngen_event("event_good")) {
vngen_text_replace("text", "John Doe", "I'm doing great!", inherit, inherit, 2);
}
if (vngen_event("event_bad")) {
vngen_text_replace("text", "John Doe", "Not so great, I'm afraid...", inherit, inherit, 2);
}
if (vngen_event()) {
vngen_text_replace("text", "Jane Doe", "I see.", inherit, inherit, 2);
}

However, at this stage, you may notice there's a problem: in the example above, what happens when "event_good" is complete and the user progresses into "event_bad"? Won't they see the contents of both choice results?

By default, yes, but this is clearly not correct. Each choice is intended to display one line of unique text before converging on the last event in the example. Fortunately, this problem is easily solved by adding another event in-between our two choice results:

Example

if (vngen_event("event_good")) {
vngen_text_replace("text", "John Doe", "I'm doing great!", inherit, inherit, 2);
}
if (vngen_event()) {
vngen_script_execute(vngen_goto, "event_complete");
}
if (vngen_event("event_bad")) {
vngen_text_replace("text", "John Doe", "Not so great, I'm afraid...", inherit, inherit, 2);
}
if (vngen_event("event_complete")) {
vngen_text_replace("text", "Jane Doe", "I see.", inherit, inherit, 2);
}

Notice the new event after "event_good" uses vngen_goto to jump right past "event_bad". This allows the second choice result to be skipped if the first is chosen.

However, we can't simply run vngen_goto in an event by itself since it is not an action. Instead, we must 'wrap' it in vngen_script_execute, which takes non-action scripts and executes them in the context of Quantum events. We can also make things easier by assigning the label "event_complete" to the event where our options converge, so we know exactly where to tell vngen_goto to go to.

And of course, this is only scratching the surface. By following these same techniques, it is possible to create deep dialog sequences and wildly branching narratives, plus entire game menu interfaces and more!