Archived

This topic is now archived and is closed to further replies.

jharkey

Scripting

Recommended Posts

jharkey    110
hello, there has been a lot of talk on this forum about scripts, and scripting languages. i know this is probably a stupid question, but what is a script? i read that it is used to trigger game events, how does it do that? could you please explain, i have no clue what it is. thanks.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Well what I''ve been trying to do is make something that interprets c-style script code (which is stored in a string). In the script language, you have functions which run some of your engine code. I have a struct in the engine like this:

struct scr_function {
char *name; //eg. "popupmessage"
void (*fp)(char *args[], int nargs); //function pointer
};

The script interpreter then calls the function pointed to by fp, when the script says something like "popupmessage("hello")".

It''s the same sort of thing for variables.

The idea (I think) is to make scripts which are run on events, like a script for when a character dies, or when a goal is acheived.

The point of it is that the code is stored as a string in a text file, and not compiled. So you don''t need to edit the engine to make new scripts.

hope that''s helped.
Frank

Share this post


Link to post
Share on other sites
LilBudyWizer    491
He is assuming it is already parsed. There are two main ways of parsing. One is processing it one character at a time, the other is one line at a time. The simplest is a delimited file, i.e. functionname parm1 parm2 parm3. Parsing this is simple:

[source]
for (szPrev = szInput; *szPrev && (*szCurr = '' ''); szPrev++);
for (szNext = szPrev; *szNext && (*szNext != '' ''); szNext++);
[\source]

Now szPrev points to the start of the function name and szNext - szPrev is the length. You repeat the process by setting szPrev equal to szNext and continue until szNext = ''\0''. This is of course a very simple syntax, but if your needs are simple it serves the purpose. It is still the starting point for this type of parsing if you need something more elaborate. A step up would be skipping any white space with iswhite. If you want to allow statements to be split across lines then you need a terminator such as ; in C/C++. Then instead of reading a line you read lines until you find one with a ; at the end. If you want to allow multistatement lines you read characters until a ; is found. A statement can be anything you define it as and not just a line in notepad.

The best way to code a parser is target a language and then refer to the syntax diagram for it. Usually they start with the definition of a statement. You will notice as you code that it is every thing you need to know to code it. The order that syntax diagrams are introduced for a compiler is usually pretty much the way you code it. They tell you when to loop, they tell you where to put a conditional and when to call a subroutine including when to recursively call a subroutine. An example of recursion is passing the return value of a function as a parameter of a function, i.e. func1(func2(value)). Your main routine identified a function as opposed to a variable by the first ( so you call a routine to parse the parameters which most likely calls a routine to parse one parameter at a time. That routine identifies that a function is being used as a parameter by the second ( which causes it to call the function that parses functions. What you actually do with it when you pass it can be rather complex, but usually parsing is pretty straight forward.

If it is a fixed sequence you can use a sequence of statements. If it is one of several values it is an if or switch. If it is a variable number of occurances it is a loop. The first problem you are likely to run into other than selecting a syntax is func1(func2(value)). You have to track the level. Increment on open, decrement on close and exit with a close at zero. You can do a great deal with a simple parser so I wouldn''t look for a better way until you hit the limits on a simple way.

Anon''s post is the key to actually executing the function. With a simple script that just executes functions with no split or stacked lines you would read a line, search an array of scr_function structures for a match and call the function pointed to.

As for your orginal question the script would call a function that triggers events just like you would in a program. The differance is that the compiler doesn''t do it for you. You have to provide code to interpet a text file, determine that the function should be called and what parameters to pass to it. You also have to provide code to do that at some particular point. As an example when an NPC is targetted by a player you call a function, that function checks if a script is defined for the NPC and if so executes that script. There may be some code you always execute before the script and after as well as default processing if no script exists. Usually you would load and parse all scripts at startup or more precisely when you load an object that referances a script for the first time.

Share this post


Link to post
Share on other sites