Making a Point and Click Adventure in Arcweave and Godot — Part 2: Starting a Dialogue

How the Arcweave plugin for Godot finds the right response for every player action

Giannis G. Georgiou
7 min readFeb 20, 2023

--

In the previous part of this series, we talked about our first efforts to create a game written in Arcweave and developed in Godot, as well as our thinking process that formed the plugin facilitating this integration.

In this post, we will see how we dealt with fetching the starting element for a dialogue sequence.

It all starts somewhere

From our early prototype, we wanted to find a system for the game engine to look for each dialogue’s starting point. We deliberately created two dialogue trees, one with a dragon (mentioned in the previous article) and one with a necromancer, and looked for ways the engine would pick one or the other.

You can’t beat a silly encounter with a necromancer.

An Arcweave project provides an overall starting element, but this is useless for genres not incorporating the choose-your-path logic. In an open world game or a point and click adventure, there is no specific flow; instead, the player interacts with game world objects in any possible order.

In our point and click adventure, when the player clicks on items or characters, the mouse menu opens offering 3 options: EXAMINE, HANDLE, and TALK.

The game’s mouse menu in action.

For the game to know which dialogue element it is supposed to call, we needed a way to associate the action (e.g. EXAMINE) with the object clicked (e.g. GRAND PIANO).

Iterating element titles

The first idea that came to mind was to use the element title as some identity the game engine can look for. For the above dialogue with Bob the Necromancer, the engine was supposed to iterate the Arcweave project’s elements, looking for the one titled necromancerDialogue.dialogueStart.

The starting element with the always cumbersome title was not to be rendered; only to signify the dialogue’s beginning. (Plus, some other silly things, like feeding the game engine in advance with the speakers and backdrop assets at play, something we fortunately got rid of a little bit later.)

If there were to be more dialogues, the engine would look for their respective starting elements, again by reading through their titles.

In the Godot script, for the sake of testing, we passed the element’s title as a constant.

When working on the point and click adventure, we started with the same logic. We had an element for every verb/object combination, with titles following a strict protocol, like amstrad.examine, amstrad.handle, etc.

Behold the Annual Gathering of Cumbersome Element Titles.

This system worked, but it always felt like a workaround; like missing a simpler and more sustainable solution.

Using components

We knew we had to move on from the above method.

It was fragile and unforgiving: all it took to break was a typo in an element’s title and the engine would miss an entire dialogue tree and throw an error.

It also worked against Arcweave’s visual approach: the writer had to look for words in titles, instead of something more eye-catching.

Moreover, we had made no use of Arcweave’s components, a flexible item with a million household uses. And it was indeed components that offered an easy and intuitive solution to the problem.

Verb and object components

Getting back to the EXAMINE GRAND PIANO example, all we needed was to create a component for the action verb EXAMINE and another one for the object PIANO. The starting element for the specific action would be the one having both components as its attachments.

Yep, elements still have titles, but the game engine ignores them. All it cares about is which components elements have attached to them.

In fact, we created a component for each action verb (EXAMINE, HANDLE, WALK, and TALK) and one for each item / character that the player can interact with. Moreover, we gave all components some standard attributes: type and objectName, so the engine knows what kind of component they are.

For example:

The Element class

The Arcweave plugin includes classes for the main Arcweave items: elements, boards, and components. Each of them gives us easy access to its members.

An element grants us access to its own members: its ID, title, theme, outputs, components, attributes, and cover. And, of course, its content, a result of evaluations performed under the hood by the plugin.

Therefore, accessing an element’s attached components is easy, using the object.property syntax:

var my_components : Array = my_element.components

Iterating elements and their components

After each player action (e.g. EXAMINE GRAND PIANO), the game iterates through the Arcweave project’s elements, looking for the one having 2 attached components: the action verb component (type actionVerb—here: EXAMINE) and the item one (type item—here: PIANO). (If it finds more than 1, it throws a "writer error," so the dev can inform the Arcweave writer to go and fix that, in their project.)

An example where a “writer error” is thrown; some cases require only one element to exist, like the starting element for a specific action. Otherwise, where would the dialogue start? This function includes the problematic element IDs in the error message, for the writer to locate and fix in the Arcweave project.
It helps to differentiate errors and warnings to be dealt by the dev and those to be dealt by the Arcweave writer.

Once found, this element is set as current and the dialogue begins for the EXAMINE PIANO command.

Generic components

There are cases where you want the adventure game to give generic replies like: “This doesn’t seem to work,” “I don’t see anything special about that,” etc.

There are always replies that the writer can miss. We still want the game to reply something even if the writer has not provided a reply for a specific combination (a failed one, obviously), like USE AMSTRAD 6128 WITH GRAND PIANO.

To achieve this, we created a “generic” component, to use as a wildcard:

Then, we program the game’s routine to first look for the specific reply requested — in this example, USE AMSTRAD 6128 WITH GRAND PIANO — and if it finds none, to then look for and return the reply for USE AMSTRAD 6128 WITH GENERIC and USE GRAND PIANO WITH GENERIC, whichever comes first.

If none of those is found either, the game returns the most general reply possible, the one for USE GENERIC WITH GENERIC, a random outcome among “Mmm… Nope,” “Nawh…” and “This doesn’t seem to work.”

Elements diverting to various generic replies. Note: the “FOLLOW RANDOM OUTPUT” component does what its name says and will be mentioned later in the article series.

Optimising the iteration

The Player Actions board

For every player action, the game iterates all the project’s elements, until it finds the right one to start the dialogue from. For a short game, this does not make much of a difference, but for large games it may create a noticeable lag.

We can optimise this process, if we keep all the starting elements in one board and iterate those, instead of all. As many of the screenshots above show, those starting elements point to jumpers; they are the only elements there, since the actual dialogue trees exist in different boards. This can certainly minimise the number of iterations.

Our short game has about 400 elements in total. The “Player Actions” board only has 78.

The Board class

As already mentioned, the Arcweave plugin has a Board class, to facilitate accessing board properties. The class grants us access to a board’s ID, custom ID, name, elements, connections, notes, jumpers, and branches. We call any of them using the object.property syntax, for example:

var custom_id : String = my_board.customId

By assigning a custom Board ID like PLAYER_ACTIONS to the Player Actions board, the game can easily fetch it and iterate its elements for the right one.

This function checks for the PLAYER_ACTIONS board and throws a writer error if the Arcweave project does not have it.

So, this was our quest for the starting element and its journey of iteration from title text to visual components.

In the 3rd part of this series, we will discuss how our plugin gets game state and logic across from Arcweave to Godot.

Until then, you can find our plugin for Godot at its repository (with documentation) or the Godot Asset Library.

Play our point and click adventure demo Regrets on its itch.io page and download its source from its own repository.

For a simpler demo, why not try our Play Mode at Godot, which implements Arcweave’s play mode in a simple Godot project.

Finally, watch our Arcweave Integrations Series on YouTube, for a taste of how the plugin works.

And, of course, always… Let the games begin!

Giannis is a writer and story consultant focusing on subjects of narrative structure, theory, and technique. He is narrative director in Arcweave.

--

--

Giannis G. Georgiou

Excited about telling stories through various media. Filmmaker and Developer Apprentice—teaching myself to code and sharing the XP.