Release 3, 2007-10-28
Copyright 2007 Jon Watte, All Rights Reserved.
This code is released under the MIT license. For more information, see http://www.opensource.org/licenses/mit-license.php
Download condscript-071028.zip
To use, add the following files to your project:
In your game constructor, #include ConditionalScriptNodes.h, and call RegisterConditionalMethods(). This will make two new Methods available in the Script Editor: Execute Text, and Execute Text Conditional. You may have to scroll the list of methods/boxes in the script editor to see them both.
When an Execute Text Conditional method is dragged into the script, the children of that node will execute only if the script text returns a true value. True values are not nil, not 0, and not the empty string. An example of a script text is "$foo > 3" which reads the console variable $foo, and returns true (1) if the value, treated as an integer, is greater than 3.
Execute Text uses the exact same script text execution, but will always execute the child nodes.
You enter the script text in the Method Settings for the script Method, in the Script Text setting. If there is a syntax error, it will be logged to the console.
The script text execution is functional in structure. Everything returns a value. Statements can be chained, with an optional semicolon after each statement. The semicolon is only required if you want to explicitly use an empty statement.
Values can be literals (integer, string, or the special value nil), variables, or expressions.
Integers are just numbers (1, 4, 17).
Strings are surrounded by double quotes: "Paris in the spring." You can include a double-quote by typing it twice: "He said: ""Open Sesame!""" Comparisons involving strings are case sensitive, and use ASCII collating sequence.
The special value nil is the default value, tests as false, and is not equal to any other value.
Local variables, which will lose their value when the script executes the next time. These are regular identifiers up to length 31 characters, with no special prefix character. Examples include "theValue" "foo3" and "_x_y_z" (without the quotes).
Global variables, which are stored on the infinite root zone of the world. These are prefixed with an at sign. Examples are "@theGlobal" "@3foo" and "@_". There is never aliasing between globals and locals. These are persisted with the scene in level save files. There is no way to set these in the world editor, except to run a script during load time that assigns values to globals.
Console variables, which are prefixed with a dollar sign. Examples are "$moof" and "$displayHeight". These are persisted in the console variable files (.cfg files), and do not follow the level, world, or player.
Node variables, which are stored on a given node. Currently, the only node you have access to in a given script is the Target node of that script. You store variables in the target node by prefixing the variable name with a question mark. Examples include "?lastUseTime" and "?hitpoints". If the infinite zone is the target node of the script, then globals and target variables do alias -- for the infinite zone, "?foo" and "@foo" is the same.
Expressions are where you can do fun stuff. Most operators are implemented, although the precedence may be different from what you would find in "C".
"and" and "or" are NOT short-cut evaluating. Both sides are evaluated before the logical test is made. The values nil, 0 and the empty string evaluate as false; all other values evaluate as true.
The value of an if expression is the "then" value if true, else the "else" value. If the if expression is false, and there is no else clause, then the value of the if statement is nil.
You cannot chain assignments. C-style "a = b = 3" will not work.
There are no in-place modifying operators, such as "+=". This may change in the future.
There are no arrays. This may change in the future.
Here are some example scripts, broken out to separate lines. Unfortunately, you have to paste them all as one long line in the C4 Script Editor, because I have not written a custom script manipulator for these types.
You may not be used to seeing regular parentheses used for creating scope blocks. However, because everything returns a value, and the semicolon (which is optional) only serves to say "do this then that, and return the last value," you can use them that way.
Scripts cannot be longer than 512 "ops," where an "op" is typically any token in the script text. The script "4 + 5" is three ops.
Identifiers cannot be longer than 31 characters. This includes the leading character for globals and node variables.
String constants cannot be longer than 255 characters.
Negative numeric literals are parsed as unary minus operator followed by a positive integer, so INT_MIN is not representable as a literal.
There are few errors that can happen during execution, because variables that are not set default to nil, and you can set any variable name to any value.
Strings cannot be longer than 4096 characters; attempting to concatenate strings to get a longer string will stop execution of the script, but will not otherwise be seen (there are no runtime console logs).
Division by zero yields nil.
Some tokens are intended for future expansion; try not to use those tokens for your local variables for maximum compatibility. These tokens include:
If I get some more time, I plan to add the following features:
This project is developed based on C4 Engine version 142 on Windows using Visual Studio 2005 SP1. Sometime in the future, C4 will evolve to the point where this functionality is no longer needed. Portability to other environments is probable, but not guaranteed.
For future code updates, see http://www.mindcontrol.org/~hplus/C4/