Note: Scripting is a new feature at this point, in early development. The implementation so far is a framework that allows for a breadth of functionality to be implemented, however, the language and features are likely to evolve to meet requirements ; if the scripting language doesn't do something you feel it should, please get in contact with Iain Maltz.
Scripting support in GPHUD is supposed to allow functionality beyond that which exists through existing commands, for example an Armor damage mitigation system that doesn't allow damage to go below 1 point.
The language used is a C style language (like LSL) and has the following instructions:
if ([condition]) { [statements] } ''else { [statements] }'' [type] [variablename] = [expression]; [variablename] = [expression]; while ([condition]) { [statements] }
Ten operators exist
+ (Addition) - (Subtraction) * (Multiplication) / (Divide) == (Equality) != (Inequality) < (Less Than) > (Greater Than) <= (Less Than or Equal to) >= (Greater Than or Equal to)
Seven data types exist
Character - GPHUD character Avatar - SL Avatar Group - CharacterGroup Response - Result from an API call String - Text string Integer - Whole number (integer) List - Weakly typed list of other data types
Two pre-defined variables exist
CALLER - refers to the Character that initiated the script AVATAR - the Avatar/User (owner of the character) that initiated the script
Some polymorphism exists and works, e.g. 5+“5” will produce “55” (the string), while 5+5 produces the integer 10. Some operations dont make sense, like Avatar + Character and will produce run time errors.
Of particular note, the “Response” object, if evaluated as a string (e.g. String message=responseobject) will produce the API call's returned message. Evaluating the Response as an integer produces “0” for no errors and “1” for the response being an error.
Lists also can be cast to an Integer which will put the list's size in the Integer.
You may also see variables in debug dumps called PC, IC and SUSP ; these are used internally by the virtual machine to store state, are initialised at the point the VM is suspended, and are restored before the VM is resumed. They are of no practical use to the end user and are inaccessible through the programming language (as their real variable names start with a space), however, they may be displayed during debug runs of scripts.
Lists are accessible using standard [] methods, such as
List sample=["One!","Two","Three"]; sample[0]="One"; sample[1]=sample[1]+"Two";
Note that lists are not strongly typed - you can mix anything inside a List - Integers and Strings in the same List, and you should take care to make sure the types are as you (or the function you're calling) are as expected. Nested lists are not currently supported.
Source script: Maximum 65535 lines of up to 65535 columns (16 bit values in Debug instruction) String: Maximum length 65535 (16 bit size in bytecode) Execution cycles: 10,000 bytecode instructions (arbitary limit)
There are some function calls available, an up to date list is available via introspection.
These generally take one or more parameters and always return a single variable, which may be discarded.
E.g. this calls gsSayToChar and captured the result in the integer variable useless
Integer useless=gsSayToChar(CALLER,"Hello caller");
However one can also just discard the result by calling
gsSayToChar(CALLER,"Hello caller");
Since gsSayToChar always returns the useless response of the integer 0, this second form is easier to use. 1)
The most expansive of the function calls is gsAPI which allows the script to run any API command that isn't an alias (e.g. Health.healRoll
or whatever). The return from this function is of a unique type, a “Response”, which corresponds to the response the HUD normally gives when the command is invoked - e.g. for healroll it would return a message about how much healing was done to the caller.
If a response is used as a string, its message is returned. If a response is used as an integer (e.g. if (response==0)) then the number 0 refers to success, and 1 means the call errored.
You can use this same “function calling” syntax to call another script. Note that variables are all GLOBAL and shared between scripts that call each other.
A script may also “return” an expression, e.g. return “String”; or return 5+5; . You can also just call return; in which case it returns an integer of zero.
As example:
Create a script called askQuestion
questions=questions+1; return gsGetText(CALLER,"Input some text");</pre> Create another script called test<pre> Integer questions=0; String response1=askQuestion(); String response2=askQuestion(); Integer r=gsSayAsHUD(CALLER,"Asked "+questions+" questions, got "+response1+" and "+response2);
Then, when you run “test”, it will load and call the other script twice, and produce appropriate output, e.g.:
GPHUD: Asked 2 questions, got test1 and test2
Note: You can not call scripts that were compiled before this change was implemented (due to those scripts using absolute addressing, and newly compiled scripts using relative addressing). You can resolve this issue by simply recompiling your existing target script.
Normally the HUD presents a very simple set of choices to fill out mandatory fields on the character sheet and so forth.
It may be desirable to have a script run to guide the user through this, or to provide more complex logic (see the example script later).
There is a KV called Instance.CharInitScript
which causes a script to be run before the usual character initialisation steps.
NOTE: it is very important you code this script carefully ; messing it up will prevent both logins and character creation - this script is always invoked.
'MUST check if the values are already set
' - do not blindly code queries to the user, you should instead check the current value, and if missing, THEN and only then prompt the user. (see note below, see example script further down)Note about “checking if values are already set” - If the character initialisation script “finishes” without querying the user for any input, then the login will proceed normally and complete. For technical reasons (and the fact the login code needs rewriting some day), if any user interaction is done (getString, getChoice, etc) then the character's login will be restarted from scratch - this means if you ALWAYS ask a question in your startup script, the user will be trapped in an infinite loop of running the startup script over and over. For an already set up character, your script should check values and exit, not query the user for anything.