User Functions

User-Defined Functions - a feature added with OBSE v18

OBSE allows scripters to define their own functions, which can be called from other scripts.

A simple function script might look like:

ScriptName Multiply            ; the name of this function

float arg1                     ; holds an argument passed to the function
float arg2                     ; second arg
float localVar                 ; a local variable
   
Begin Function {arg1, arg2}    ; function body, with parameter list in {braces}
  Let localVar := arg1 * arg2
  SetFunctionValue localVar    ; this is the value that will be returned  
  Return                       ; optional, causes the function to return immediately
End

To call this function you would use:

Call Multiply 10 5

To store the result (50, in this case):

Let someVar := Multiply 10 5


When a function is called, script execution passes to the function and resumes after the function call when a return statement is encountered or execution reaches the end of the function script.

Factoring commonly-used code out into a function prevents repetitious code and shortens scripts. Encapsulating complicated routines into stand-alone functions results in simplified, more readable code.

Functions are defined as Object scripts but are treated as a distinct type with special limitations.

A function script can contain only one block. The name of the script is the name of the function.

Parameters are stored in local variables and must be indicated within {braces} in the function definition.

A set of empty braces indicates the function takes no arguments.

When parsing a function call, the compiler will verify that the number and type of the arguments match those expected by the function's parameter list.

If the called function is specified as a ref variable this validation cannot be performed; it is the scripter's responsibility to ensure the argument list is valid to avoid errors at run-time.

NotesEdit

  • Function scripts should never be attached to any object.
  • All variables in a function script must be declared before the function body.
  • Local variables and argument variables retain their values only until the function returns.
  • Numbers, references and strings passed as parameters are copied to their proper local variables. Changing these copies do not change the original variables in the calling script.
  • Arrays, on the other hand, are passed as pointers to the original arrays, therefore changes to arrays passed as parameters will persist after the user function returns.
  • Clean up
    • Strings passed as parameters are destroyed when the function returns.
    • Any other string stored in local variables must be explicitly destroyed with sv_Destruct before the function execution ends (or else they will bloat the savegame).
    • Arrays passed as parameters are pointers to the original arrays, so no clean up is necessary (the pointer, itself, is destroyed automatically).
    • Local arrays are destroyed automatically when the function execution ends.
    • All other local variables (shorts, floats, refs etc.) are also destroyed when the function execution ends.


Functions have some useful properties.

  • Because they are object scripts, you can call them on references using someRef.Call someFunc; any commands used inside the function will then operate implicitly on the calling reference.
  • Because they are scripts, they can be stored in and called using ref variables, and even passed as arguments to other functions.
  • Functions can call other functions, including themselves (i.e. recursively);
for instance:
ScriptName Pow            ; calculates base to the exp power
float base
short exp
short val

begin Function {base, exp}
  if exp == 0
    let val := 1
  else
    let val := base * Call Pow base, exp - 1
  endif
  SetFunctionValue val
end

OBSE allows a maximum of 30 nested function calls. This means the above function will only work with exponents less than 30.


FunctionEdit

A blocktype which precedes the body of a function.

Begin Function {arg1, arg2, ... arg10}
    ; function body
End

This blocktype is only valid within function scripts.

A parameter list consisting of up to ten local variables used to hold arguments passed to the function must follow this keyword enclosed in curly braces;

if the function takes no arguments the braces should be empty.


SetFunctionValueEdit

Specifies the value to be returned from a function.

(nothing) SetFunctionValue returnValue:expr

Valid only within a Function block.

If a function does not specify a return value, the return value is assumed to be numeric zero.

If multiple calls to SetFunctionValue are processed within a single Function block, the most recent value specified will be returned.


CallEdit

Calls a user-defined function.

(returnValue:multi) ref.Call function:ref arg1:multi arg2:multi ... arg10:multi

Should be followed by a list of arguments matching the types expected by the function.

If a calling reference is specified, commands within the function body will operate on that reference.

Call returns whatever value is returned by the function.

See alsoEdit