Expressions and Data References
Expressions in HeroScript are similar to most other programming languages. They can be anything from a simple number to a complex mathematical formula involving calls to other functions. They are only valid as parts of statements.
There are also various different kinds of data references in HeroScript. For example, how to access the data in a timer field, a subfield, and an array, all warrant some additional explanation, which is included on this page.
These are the ways of referencing different types of data.
- integer: 123
- float: 3.14, 0.23, .7
- time interval: interval: 0:30:00.000
- string: "hello"
- vector3: (1.0, 0.0, 0.0) ** as of HeroEngine 1.23
There are also various string tokens such as the following:
$$: Inserts a "$" character in a string
$Q: Inserts a double-quote " in a string
$R: Inserts a return character <cr> in a string
$T: Inserts a tab character in a string
Please see the section on System Variables.
Node/Class Field References
Given that myVar is a variable of a type with a class that has field1, and field1 is of a class type that has field2, subfields are accessed as follows:
Timer field references
Given that n is a reference to a node, and that node has a class with the field exampleTimer of any timer type, the following fields may be retrieved:
WallClockTimers have a fireTime field which can be read or set. It is a combination DateTime such as
SYSTEM.TIME.NOW. Other timers have an interval field which can be read or set to a TimeInterval.
The remaining field can be set to a Time Interval but only applies until the timer fires (does not change interval).
Given that myVar is a variable of a list type, the following gives the first element of the list:
|Operator||Name||Operand data type(s)|
|+||add||integer, float, string|
|+=||add and assign||integer, float, string|
|-=||subtract and assign||integer, float|
|*=||multiply and assign||integer, float|
|/=||divide and assign||integer, float|
|is exactly||test class on node||node - produces boolean|
|is kindof||test class on node||node - produces boolean|
|= or ==||equal||integer, float, string, node, class, boolean - produces boolean|
|>||greater than||integer, float, string - produces boolean|
|>=||greater than or equal||integer, float, string - produces boolean|
|<||less than||integer, float, string - produces boolean|
|<=||less than or equal||integer, float, string - produces boolean|
|!= or <>||not equal||produces boolean|
|mod||produce remainder||modulus operator: returns the integer remainder|
|& | ^ ~ << >>||bitwise operations||Same as C. See http://en.wikipedia.org/wiki/Bitwise_operation|
Expressions are processed from left to right, except in specific precedence cases.
| IS KINDOF
| boolean "not"|
| bit shift left|
bit shift right
less than or equals
greater than or equals
not equal to
|^||bitwise "exclusive or"|
|lowest||= += -= *= /=||assignment|
It is worth noting that in some cases, evaluation will stop before the entire expression is processed. For example, if there are multiple AND operators in an expression, which would all need to be TRUE simultaneously, then if any single one of them results as FALSE, the Here's Journey engine won't bother evaluating the others.
For example, suppose that trying to check the value of a field on a noderef will result in a script error if the NodeRef is None. So it is desirable to check that the node exists:
function demo (n as noderef of class x) if n != None then if n.name = "Bob" kill(n) . . .
A faster way to do this would be:
if n != None and n.name = "Bob" kill(n) .
So, even though checking
n.name would generate an error if
n was None, the engine won't get that far. However, writing the above statement as:
if n.name="Bob" and n!=None
then it *would* generate an error, since the engine would be evaluating the
n.name part first.
The same principle (processing stops when it becomes unnecessary) is true for the OR operator, except that it is reversed. For example, if there are multiple expressions being compared with OR, then the first one that returns a value of TRUE means that the rest can be skipped.
if i mod 7 . if x == 2 . if y <= 27 . if n is kindof ExampleClassName .
println("runLimit = "+SYSTEM.EXEC.RUNLIMIT.timeString) runLimit = 0:0:0.5