Simple Game Scripting Part 1: Storing/Reading Your Scripts
This article and all it's contents are © 2000 David Goodlad. They may not be reproduced in any form without permission from the author.
I will very gladly give permission to copy the article, though, so send me an email!
Over the past few months, many people have been asking on messageboards for help with scripting in their games (especially RPG's). This topic is an extremely important part of programming your game, yet it seems to be one of the least-documented aspects out there!
This series of articles will hopefully get you to the point where you can easily use custom scripting commands in your game to control any possible event you wish to occur.
A reminder, though, is that this is not necessarily the best, nor the fastest, possible way of adding scripting functionality. The code has been written in such a way that the concept should be easily understood so that you can design your own implementation which best suits your particular game. Also, the code requires Visual Basic 6; VB5 does not have a couple of the required functions such as Split() and CallByName().
The basic idea behind a custom scripting 'language' for your game is so that you do not have to hard-code every single possible event and conversation into your game. It also avoids the need to recompile the executable for the game each time you wish to slightly alter the storyline or for example the effects of drinking Potion X on a character with a 'Good' alignment.
For this first article in the series I will be explaining the general structure of your scripts, and how to store your scripts on disk, then read from them later.
The method to read/write discussed in this article will leave your scripts easily editable by the end-user of your game. This is usually not desirable, so I suggest changing these later to implement some sort of custom resource-file setup that you should use for your graphics and sounds as well.
Script File Syntax/Format
Your scripts will be plain text, formatted with a very simple syntax:
Each line will have this simple format. There is an exception, though. You will want to be able to define blocks of these commands (I will go into why later). So, to define such a block:
For example, if there is a block type called 'Event':
All commands must be contained in 'Blocks', even if there is only one of them. The reasoning for this will become clear later; for now just accept my words as the truth :)
This is the simple structure of your scripts. It may not seem very useful/extensible right now, but later on you will understand. You will just have to trust me about this, just as with the rule about commands having to be within blocks.
Loading Your Scripts
There is no real need to discuss the writing of your script files from VB, as you can simply use notepad or another plain-text editor to do this.
But, loading your script files into your game for use is another story. There are numerous questions which can be asked about how to do this, such as how the lines of 'script' can be parsed into separate pieces, and how to store the scripts while in memory.
User-Defined Types - Gotta Have 'Em!
The first thing to be done is define a user-defined type for a script command line. I suggest placing this into a class module, probably called something such as CScriptParser in order to allow for further expansion in later parts of this series of articles.
This should be placed in the declarations section of your class module. Another useful UDT that should be created is one for an event block:
To prepare for storing your scripts, you'll need a variable array (put it into your declarations section of the class module you created earlier as well):
This creates a limit of 1024 possible blocks loaded simultaneously. You can always increase this if you need to. The iLastBlock variable is simply to keep track of the last element in the array which is occupied. You should initialize this variable to -1 when an instance of the class is created, so in the Class_Initialize method of your class, put:
Actually Loading the Script File
Now that we've got all of our storage structures created, we can actually load our script file. Put this function into your class module:
Hopefully the comments in the code for the LoadScriptFile function are sufficient to explain what the more confusing lines do. The use of string manipulation functions such as InStr, Left$, and Right$ can become very confusing if you have not used them before, or don't know how they work. Therefore, if you wish to truly understand how the string parsing works, I suggest you read up on these functions, and other related ones including Mid and Split.
Until next time...
By now, you should understand how to load and store your script files on disk and in memory. This is the most important piece, and can be the most complicated. The actual loading and splitting up of the individual lines is integral to the use of your scripting engine, and thus you have to make absolutely sure that it is foolproof (or as close to this as possible!). I suggest adding error handlers, and using the return value of LoadScriptFile to check whether the file was loaded correctly when you call it.
In the next article in this series, the actual use of your scripting will be discussed. The third part of this series will then continue along that theme and go into much more depth with the implementation, including a section on interfacing the scripting engine with a tile-based system in order to create events.
Though simple, if you would like the source code to this part of the series, the class module is available at:
Contact + Future Releases
Updated versions of this article, as well as the later parts of the series as they are written, will be available from my website, the black hole.
I can be reached for comments or questions at
I sincerely hope you've gained from this article, and look forward to the next part of the series!