Devlog

Village Notes #3: Yarn events

A technical design note about using Yarn to drive Eldervik events.

Hello everyone.

This one is a little more technical than the first two village notes.

Not because I suddenly want the devlog to become a code diary, but because some parts of Eldervik only make sense if I show a bit of the machinery behind them.

Events are one of those parts.

In a farming game, an event can look very simple from the outside. You walk into the farm. Halvar is waiting. The camera moves. He says a few lines. Maybe he walks to the field. Then the player gets control again.

That is the player version.

The developer version is more annoying.

Who starts the event? Where should the actors stand? Who owns the camera? Can the player move? What if player two triggers it? What if the host is not the player who should see it? What happens if dialogue waits for an actor who never arrives?

So I wanted a system where events are not hard-coded cutscenes buried in code.

The current shape is this:

A game event is a JSON definition plus a Yarn node.

Yarn is a small scripting language for branching dialogue. Eldervik uses Yarn Spinner for that, so dialogue can live in text files instead of being written directly in code.

The JSON says what the event is.

Something like: this event starts on the farm, it uses this Yarn entry node, it has Halvar standing at this tile, and it should only happen once.

The Yarn node says what happens.

Dialogue, camera focus, actor movement, waiting, meeting a citizen, giving an item, completing the event. Those things can live close to the written scene, instead of being spread around in engine code.

For example the farm intro has a shape like this:

<<set_time 2200>>
<<camera_follow PlayerCharacter>>
<<face_actor PlayerCharacter Up>>
<<move_actor PlayerCharacter 13 23 Up>>
....
elv_astrid: There you are. #line:yarn.core.arrival_at_harbour.arrival_at_harbour.elv_astrid.001
<<complete_event>>

Yarn is not only text here. It is also a small event director. I do not want every small scene to become a new pile of custom code. If Signe teaches fishing, the important part should be the scene: where she stands, what she says, when the player gets the rod, and when the game gives control back.

The code should provide good functions that are easy to use.

  • Move actor.

  • Wait for actor.

  • Focus camera.

  • Give item.

  • Complete event.

Then the scene can use them.

Co-op makes it more interesting.

If player two walks into the harbour and gets Signe’s fishing intro, that should be player two’s moment. The host should not suddenly steal the scene. Player one should not receive the fishing rod by mistake. The wrong camera should not lock.

So events have different shapes:

  • Some are local. They happen on this machine, for this player.

  • Some are shared. Everyone should see the same village moment.

  • Some are personal. One player gets the event, even if the host is the one running the authority.

For multiplayer, the rule is that the host owns event progress. Clients can show the scene and send continue or option requests, but they do not decide the result on their own.

That means the host says: this line is next, this option was chosen, this wait is finished, this event is complete.

The clients render that.

That is the goal anyway ;)