Teddy the butcher sure is adorable, but there’s
not much use for NPCs if you can’t interact with them, so this week I implemented a dialogue
system that will allow NPCs to talk to you, and you can also respond back to them.
Howdy, and welcome to Game Endeavor. Where I post weekly devlogs for my
game Zoe and the Cursed Dreamer. I’m making a game where the NPCs that
you encounter play a major role in the development of the game. You’ll be interacting
with them regularly and getting to know them on a personal level. And if you want, helping
them solve their problems as they try to figure out what they want for themselves.
In order for me to create this kind of interaction with the NPCs, I needed to create
an interface that allows you (the player) to interact with them. Which means I need a dialogue
system where the NPCs can talk to the player, and the player can respond back. But there
are so many things to consider with such a dialogue system. How flexible do I want it to be?
Do I want to allow for branching paths? How will I handle tasks such as Teddy the Butcher giving
the player a handful of cookies, or removing items and coins from the player’s inventory to
pay for a special service? I’m going to need a rather powerful system if I want to make this game
how I envision it. Without a solid dialogue system then my game would feel bland and leave the player
without much of a way to interact with the game. So I got to work putting together the
foundation for my dialogue system. Now if you’ve been watching these devlogs
so far, then you may have noticed that there are some text boxes in my previous videos.
These were just a ruse, they were never real. I mean, they exist, but they’re just a shell of
the actual system. In fact, I was manually passing in the dialogue for each of these clips, recording
the video, and then moving on to the next one. I need a more flexible way of handling the
dialogue. Something that doesn’t require most of my NPC code to consist of NPC greetings.
I want to separate the dialogue script into its own file and let the NPC tell the game which
file it should use to perform the dialogue scene. For this I decided to go with json files.
Godot is able to read in a json file and automatically import it as a dictionary, which
allows me to easily access and read the data. I can use this to store what the NPC says
to the player, but also extra information for each section such as who is speaking,
their expression when they’re saying it, and what should happen in the game when they say
it. I have defined all of these variables myself and assigned their function through the code.
The speaker’s id lets me set a couple things about the NPC that is currently speaking, this being
their name and their portrait, which informs the player about who is speaking. This information is
stored in a database that is global to the game, so interestingly enough I could change the
values here and it would be permanent, so long as I reapplied the data when loading the game.
For example, in the livestream when we drew these portraits, we established that the butcher’s
name is Theodore, but everyone calls him Teddy. This is just an example, but I could set his
name as Theodore when he is first introduced, and then change it to Teddy after he explains this.
The portraits are also stored here as well into a dictionary, which allows me to label each one to
easily find later. In the json file I can assign a specific portrait to play at the start of the
text, which will display the NPCs current mood. This game will have a relationship system where
your actions and what you say to the NPCs will affect their disposition towards you. With this I
could make it so that they greet you differently depending on their mood by showing a different
portrait. Teddy will always greet you eagerly though, because he is the embodiment of everything
sweet and innocent. He could never be mad at you. I had a little bit of a meltdown over
the text reveal though. Long long ago, probably long than I have a project for, I created
the text reveal that I have been using up until now. It’s not pretty, and honestly it didn’t
even work all of the time, and worst of all it could only be used on a regular label, but
it was mine, I made it, and I was proud of it. However I knew it was bad, and that it
needed replacing, so I decided to watch some other Godot YouTubers to see if they
had gotten around to implementing this yet. So the first one I watch is Emilio, and he
just suckerpunches me right in the back of the head with this `percent_visible` variable.
Like, what is this?! How long has it been here? And why am I just now finding out about it?
It’s literally the first and second variable in the inspector, and it’s as simple as dragging
a slider to the right. I mean, yeah I can’t expect the player to drag a slider in the game to reveal
the text, but it’s a step in the right direction. So armed with this newfound sacred knowledge, I
set out to recreate my text reveal logic in a way that actually works properly. And it’s really just
as simple as creating a tween that interpolates this value between 0 and 1. The only thing to
consider here is the timing, because if I have a piece of text that’s 5 words long and another one
that’s a whole paragraph, and I set them both to reveal in the same duration, then the shorter
sentence is going to feel noticeably slower. To get a consistent time, all I needed to do
was divide the number of text characters by the number of characters that I want to reveal
per second. I can get the number of characters by saying text.length() because text is the
plain text without any BBCode tags. I’m using 45 characters per second at the moment, but I
haven’t set out to start tweaking this value yet. The best part about this new text reveal
system is that I can now use this with RichTextLabels without any issues, which
opens up the possibilities for me to use BBCode to spice up my text. By default, Godot
provides several BBCode effects out of the box like shaking and colorful text. But even better,
they give you the option to create your own BBCode effects which I look forward to doing.
Not only can the NPCs talk to the player, but the player will have the option to respond
back to them in certain situations. For this I’ve created a special dialogue box that allows
the NPC to state their question or statement. And once the text has revealed, the player can then
choose different options to advance the dialogue. Within these answers, I can create special actions
such as which dialogue node we should progress to next, or even actions we should take when this
response is selected. For example, say the player is trying to haggle for a quest reward. They
could choose a lower price that is guaranteed to succeed, or they can try for a more difficult
option that requires a certain skill level. Both options advance to the same dialogue node, but
they have different actions resulting from them. These command sentences are what power the
dialogues interaction with the world. This can be used to advance the progress for a quest,
give the player items or coins, or even adjust the disposition of the character you’re talking to.
These commands hook into a CommandHandler that I’ve created for this. Currently I just
have some very basic commands implemented, but there’s also an interesting one
that lets me set variables via commands. These aren’t proper variables that get added to
the engine, but they get stored as values in a dictionary that I can reference in the game.
For example, once the player has talked to an NPC for the first time, I can set a variable
that remembers that the NPC has been talked to. This is one of the more interesting features
in this dialogue system that opens up a lot of potential for the game. If you’re talking
to an NPC in the game and you say a particular thing to them. I can create a variable to
remember that response and reference it later on to create an effect that is caused by
that response. Maybe you mention to the witch that you like cookies and milk, and later on
one day when you’re sleeping she breaks into your house and places a few of them in your socks
and a jug of milk in your bed beside you. There’s a lot of fun that could be had with this.
In this week’s livestream, we made some portraits with the community so that I would
have some visual eye candy for this devlog. I still have a lot of practice to do when it comes
to portraits, but I’m getting there. Previously I had drawn all of two pixel art portraits in my
life, and they’re both recent ones of the witch. As you can see, with a bit of perseverance and
determination, you can make something at least half decent in the end. I’m still not happy
with this one of the witch. She doesn’t look like how I imagine her, but I’m getting better
and that’s the important bit that I’m after. I’m pretty happy with how Teddy the Butcher came
out though. There are still some tweaks that need to be made, but for the most part he looks about
how I want him to. The community was a massive help while creating these portraits. They made
many suggestions which helped me figure out how I wanted to draw the characters. Without them
these wouldn’t have turned out nearly as good. As soon as I finished the stream, I was
greeted with an amazing piece of fanart from someone that also drew portraits of the
characters along with me. They even drew ears on both characters and I don’t even want to
know what kind of black magic was involved in this task. They also went through the effort
of creating various expressions and animations for the characters. Like the witch when one of
her spells backfires and blows up in her face. I stream here on YouTube every Tuesday, so if
you want to join the community in helping us design and make this game, then be sure to join
the sub-club and ding-a-ling that bell to get notifications. I spent much of this week working
on the story for this game, which means pretty soon we will be designing the first dungeon and
its boss, so I look forward to seeing you there.