Writing a Visual Novel with .utf and .org files
The basics.
Writing with RLDev is incredibly simple so long as you take the required steps. First you’re really gonna want to set up a template. Every line of text in your script will be preceded by a number in between two angle brackets (<0000>) and each presentation of that text in your code will be formatted as #res<0000> followed by a pause. Writing this all out is very tedious, and unless you’re a notepad++ whiz you’ll spend most of your time on this basic formatting.
Luckily you have little old me to save you~ Here is a template. Just scroll to the bottom of the page, copy the raw paste data, and save it as a text file. In Notepad++ you can alt+drag to select an area. Use this with my template to copy the <> numbers and easily paste them before your story script.
Click for example image.
Once you have that done, we can look at how to code.
In most cases you will be using two files to make a seen. A .utf and a .org file that share the same name.
In your seen0001.utf you’ll have your story script:
<0014> \{Kengo}"Wasn't everything you've been doing so far independent\r
\ training in the first place?"
<0015> Kengo rebutted calmly.
<0016> \{Kyousuke}"I see..."
Expand for explanation.
Each line starts with a res tag, a 4 digit number in between a pair of angle brackets. The normal text then continues. The formatting Key uses is as such:
When the protagonist is thinking, plain text follows the res tag.
When a character is speaking, \{Name}
is used, followed by speech marks containing the character’s speech.
When a line break is to be used (you’ll find this through testing) \r is used to signal the line break and then you do the normal enter press to break the line.
Remember to use curly brackets for names. When I started writing scripts I kept using normal brackets and I had to replace all every time.
The .org file is much more complicated, as that’s where the insides of the game are kept. To simplify for this introduction, I’ll go over the core structure.
A series of text looks like this:
#res<0001>
pause
#res<0002>
pause
#res<0003>
pause
#res<0004>
pause
#res<0005>
pause
These are how the res tags from the utf file are used. By typing this line, the game will present the text of the specified res tag.
The most important thing to know after that is @ tagging. @ tags are areas in the script you can jump to at any point in time. You should place one before each scene as such:
@66
#res<0366>
pause
@67
#res<0367>
pause
Once an @ tagged scene is complete, it will naturally proceed onto the next tag unless told not to. You can make a scene jump to a different @ tag at any time with goto @68
The second most important thing to know is Flags. Flags are variables that you can set like a switch. The game will remember if a switch is on or off, and you can change it at any point. This is extra important for modders because you will see flags everywhere in a script. A basic flag looks like this:
intF[100] = 1
Int flags aren’t the only ones you’ll see. A strS flag for example controls images.
Typing strS[1000] = 'BG005'
will set the background to the image BG005.g00 from the G00 folder.
Typing strclear(strS[1000])
will clear the background.
To place your calendar image up in the corner, type strS[1004] = 'Date1.g00'
Beyond that you’ve got the aesthetics.
After a line of text’s pause command, you can place this to have a sprite show up during that line of text:
intF[1362] = 0
intF[1363] = 0
intF[1364] = 0
strS[1001] = 'NONE'
intF[1365] = 0
strS[1002] = 'NONE'
intF[1366] = 0
strS[1003] = 'NONE'
intF[1367] = 0
intF[1374] = intF[1373]
farcall(9030, 0)
intF[1368] = 0
SET_WAIP_WINDOWCLOSE_OFF
SET_GRPCOM_WINDOWCLOSE_OFF
Replace NONE with the name of your sprite’s graphic. The NONE you replace determines the sprite’s position on screen. And yes, you can have multiple sprites on screen by replacing multiple NONEs.
Typing title(#res<0000>)
allows you to set the text of res tag 0000 as the title of the game. It’ll be present on the top of the window.
Typing bgmLoop('BGM01')
will play the track named BGM01 in the BGM folder as music. bgmFadeOut(3000)
will fade the music out at a specified rate. 3000 is a good average number to use.
Typing koePlay(51500016, 0) will play the file z0515_000016.ogg that is kept in the z0515.ovk file in the KOE folder.
To start a seen, you’ll almost always want to start with something similar to this:
#file 'SEEN0514.TXT' <-- Specify file names here
#resource 'SEEN0514.utf'
#kidoku_type 2 <-- Chances are you never want to change this
setrng(intC[0], intC[4], 0)
intC[5] = 0
@1
goto_unless(intC[5] < 5) @2
strS[1900 + intC[5]] = ''
intC[5] += 1
goto @1
@2
#entrypoint 000 // Z00 <-- This is where the script begins
intF[EXAMPLE] = 0 <-- Specify any flags here
strS[1004] = 'NONE' <-- Set your calendar image if you're using one.
intA[1000] = strcmp(strS[1004], 'NONE')
goto_unless(!intA[1000]) @3
strclear(strS[1004])
@3
title(#res<0000>) <-- Set your window title
intF[1380] = 3
bgmLoop('BGM02') <-- Set your BGM
#res<0001> <-- Text begins here
pause
To end a seen, you’ll want to type a jump followed by an end of file. If you were in SEEN0514 you’d type:
jump(515)
eof
I think those are all the basic commands you’ll need.
Branching the story with choices.
If you want to make a real Visual Novel you’re gonna want choices. We aren’t looking for any of that Telltale rubbish where the choices don’t change anything. This is how to make a long lasting change to your VN.
In this example, I am working with a tutorial scenario. In the scenario, little old Taka is searching for a schoolgirl killer! You must decide on where he gets information from, and depending on which information Taka gained, future dialogue will be different. Due to this being a tutorial I will make all of the scenes short and simple. Once you understand the method, you can use it in large complex branches if you so wish.
First in my .utf file I set up the choice text.
<0165> I decided to pry for more information.
<0166> Talk to random students.
<0167> Talk to Yuki.
<0168> Talk to classmates.
The first line sets up the choice, and the next three are the options. For the sake of hitting all the bases, I will have three different routes here.
The “Talk to random students” choice will give a short scene that is then followed by the “Talk to classmates scene.”
The “Talk to Yuki” choice will give a short scene.
The “Talk to classmates” choice will give a longer scene.
With this setup, you have a quick escape choice, you have a required information choice, and you have an extra information choice. Whether a reader is rushing through the VN or looking for every bit of story, there’s an option.
I then have my different branches written out one after the other.
<0169> I approach a random student...
<0170> \{Student}"Heeeh, the killer?"
<0196> I approach the class representative.
<0197> Her name is Otonashi Iroha, but everyone calls her Mama for some reason.
<0213> I search for the white haired girl.
<0214> The only problem is... I have no idea where she'd be.
Note that the order of my choices don’t match the order I’ve written the scenes. You can put these scenes at any point in your script and it’ll be fine. If you suddenly decide to add a new choice, just write it onto the bottom of your .utf.
Over in my .org file is the scene written as such:
#res<0165>
pause
intF[1350] = select_s(#res<0166>, #res<0167>, #res<0168>)
goto_unless(!intF[1350]) @13
#res<0169>
pause
Expand for explanation
This command sets intF[1350] (a variable) to the number of the choice picked, with the top choice being void. The second choice will set intF[1350] to 1.
The goto command will send you to the next @ heading unless intF[1350] has no value, aka, if the reader picked choice 1. So if the reader picks choice one, this line will be ignored and the scene will continue as normal.
Set the #res numbers to match your choice text. Then set the goto to the next @ heading.
Follow the goto with the resulting scene of your first choice.
Once the resulting scene is complete, begin your next @ heading.
@13
goto_unless(intF[1350] == 1) @14
#res<0213>
My @13 begins with a goto. This will send you to the scene of my third choice if intF[1350] doesn’t equal 1. If the user picked choice 2 they will stop here. If they picked choice 3 they will go to the next @ heading.
My @14 is written as:
@14
#res<0196>
pause
Expand for summary
Picking choice 1 (Talk to random students) will not send you anywhere. It’ll just read the next line as normal. That line is “<0169> I approach a random student…”
If you don’t pick choice 1, you’ll be sent to the next @. The next @ says if you picked choice 2 (Talk to Yuki) then play the next line as normal. That line is “<0213> I search for the white haired girl.”
If you don’t pick choice 2, you’ll be sent to the next @. The next @ says if you picked choice 3 (Talk to classmates) play the next line as normal. That line is “<0196> I approach the class representative.”
Simple so far. Our branch should work at this point, but there are two problems. One, we haven’t reconnected it to the main story. Two, we haven’t set a dedicated flag for this choice.
Reconnecting the story is simple. Once your scene has completed, put a “goto @” aimed at the @ header following all of your choice scenes. My final choice scene was @14, so the connection point would be @15.
As I mentioned previously, I decided to have my choice 1 scene link to the choice 3 scene. This was very simple. At the end of choice 1 I typed “goto @14”
Now how do we make this choice something to be remembered? Well, you’ll need to set aside an IntF variable. I like to choose easy to remember numbers, so I picked intF[50]
In my scenario, when you choose the “Talk to Yuki” choice, you learn the name of the killer.
When you choose any other choice, you simply hear of the killer’s past.
I need my VN to reflect this in the dialogue.
At the end of my “Talk to Yuki” scene, just before the goto jump, I typed “intF[50] = 1”
Similarly, at the end of my “Talk to Classmates scene” I typed “intF[50] = 2”
So if a reader learns the name of the killer intF[50] = 1, and if they don’t intF[50] = 2
Then comes a future scene. In this scene Taka is asking for information, but the information he asks for changes depending on which choice was picked previously.
I write a scene in which Taka knows the killer’s name, and a scene in which he doesn’t.
These look like:
<0224> \{Taka}"Do you know a girl who causes conflict?"
<0235> \{Taka}"Do you know a girl named Yuka?"
The branching moment occurs on this line in my utf, under the @17 header:
<0223> I think over what I've learned.
Following that line in my .org I set a goto command.
#res<0223>
pause
goto_unless(intF[50] == 2) @18
#res<0224>
pause
My goto says if intF[50] is 2, continue the scene as normal. It’ll play 0224
<0224> \{Taka}"Do you know a girl who causes conflict?"
The scene is bookended with a goto @19
If intF[50] is 1, the reader will be sent to @18. My @18 looks like this:
@18
#res<0235>
pause
It’ll play 0235
<0235> \{Taka}"Do you know a girl named Yuka?"
The scene ends with a goto @19
And with that, my story has rejoined back to the common route. The flag intF50 will be set to either 1 or 2 until I change it later, and you can reference the flag later in the same way should you wish this choice to have future impact. The great thing is that, before beginning any @ scene you can simply put a goto_unless(intF[50] == 2) and it’ll automatically skip the scene if the person hasn’t triggered the required choice. Just make sure you note down all your intF variables!