Difference between revisions of "Function Reference"
imported>Michaelrw |
imported>SarthesArai m (→Function Header: typo) |
||
Line 13: | Line 13: | ||
A function header starts (optionally) with the return type of the function, and is then followed by the name of the function, its parameters (if any), and any modifiers and flags. | A function header starts (optionally) with the return type of the function, and is then followed by the name of the function, its parameters (if any), and any modifiers and flags. | ||
The [[Identifier Reference|identifier]] used to name the function cannot conflict with any other function in the current script. If the identifier matches a function in the parent script, then the return type and parameters | The [[Identifier Reference|identifier]] used to name the function cannot conflict with any other function in the current script. If the identifier matches a function in the parent script, then the return type and parameters must match the parent script's version of the function - and the function will override the parent's function. | ||
The "Global" flag indicates a function that does not actually run on an in-game object, and has no "Self" variable. | The "Global" flag indicates a function that does not actually run on an in-game object, and has no "Self" variable. |
Revision as of 16:16, 29 December 2013
Functions are units of work that are larger than a single expression, and may take various parameters and return a value to their caller.
Function Definition
<function> ::= <function header> [<function block> 'endFunction']
Function headers must always be followed by a block and an "EndFunction" keyword, unless they are native functions (which are exposed by the game).
Function Header
<function header> ::= [<type>] 'Function' <identifier> '(' [<parameters>] ')' ('global' | 'native')* <flags>*
A function header starts (optionally) with the return type of the function, and is then followed by the name of the function, its parameters (if any), and any modifiers and flags.
The identifier used to name the function cannot conflict with any other function in the current script. If the identifier matches a function in the parent script, then the return type and parameters must match the parent script's version of the function - and the function will override the parent's function.
The "Global" flag indicates a function that does not actually run on an in-game object, and has no "Self" variable.
The "Native" flag indicates a function that does not have a function body, because the function is implemented by the game itself. If you add the native flag to a function the game does not expose, the compiler won't complain, but the game will error at you. The same flag cannot be specified more than once.
Parameters
<parameters> ::= <parameter> (',' <parameter>)* <parameter> ::= <type> <identifier> ['=' <constant>]
The parameter list is a comma-separated list of types and identifiers that indicate the various parameters that a function takes. Each parameter may be optionally followed by an equals sign and a constant, which indicates that the parameter has a default value. If a parameter has a default value, every parameter after it must also have a default value.
Parameters are essentially variables the function has access to that the caller gives initial values to.
Function Block
<function block> ::= <statement>*
The function block contains zero or more statements. This performs the actual work of the function.
Examples
; A simple function that adds the two values together and returns the result
; Global, because it doesn't need a self variable
int Function AddTwo(int a, int b) global
return a + b
endFunction
; A function that increments a value on this script by the specified amount.
; The amount has a default value of 1 (so the caller doesn't have to pass it)
Function IncrementValue(int howMuch = 1)
myValue += howMuch
endFunction
Special Variables
There are two special variables in a function, but only in a non-global one. "Self" refers to the instance of the script that the function is running on, and is useful if you want to pass yourself as a parameter to another function somewhere else.
"Parent" is only used to call a parent script's version of a function, in the case where you extend the parent.
Examples
; Pass our self off to another function
SomeObject.OtherFunction(self)
; Call the parent's version of DoStuff, ignoring our local definition
Parent.DoStuff()
Calling Functions
Global function:
[<identifier> '.'] <identifier> '(' [<parameters>] ')'
Non-global function:
[<expression> '.'] <identifier> '(' [<parameters>] ')'
Calling a function simply involves using the function's identifier, followed by parenthesis, and any parameters that the function takes. The return value of the function is the result of the function call and can be assigned to a variable, or used to call another function or property.
If you are calling a global function and the function's owning script isn't the current script or isn't imported, then you must prefix it with the name of the script the function resides in.
If you are calling a non-global function and it isn't on yourself, then you must prefix it with the object you want to call it on.
Parameters
<parameters> ::= <parameter> (',' <parameter>)* <parameter> ::= [<identifier> '='] <expression>
The parameter list is a comma-separated list of expressions in the same order as the parameters are listed in the function definition. If a parameter is optional, it does not have to be passed (the default value is inserted by the compiler into the call location). You may specify parameters out of order by prefixing the expression with the identifier of the parameter (matching the name of the parameter in the definition) followed by an equals sign.
Examples
; Call the function: MyFunction(int a, int b) and get the result and put it in x
x = MyFunction(1, 2)
; Call the function DefaultFunction(float a, float b, float c = 0.0, float d = 1.0) on MyObject,
; but only pass in the first three parameters
MyObject.DefaultFunction(4.0, 2.0, 1.0)
; Call the function DefaultFunction(float a, float b, float c = 0.0, float d = 1.0), but specify
; argument d out of order because we want c to keep the default it has
DefaultFunction(5.0, 2.4, d = 2.0)
; Call the global function MyGlobal() in the Utility script
Utility.MyGlobal()
Accessing Functions From Other Scripts
There are several methods for accessing one script's functions (or properties, states, etc...) from another script. For the sake of the following examples, let us assume we are working on ScriptA, but we need to access a function that is in ScriptB.
Method One: Setting up the Target Script as a Filled Property
Declare the script that you want to access (ScriptB) as a property within the script you are trying to access it from (ScriptA).
- This method is best when you only need access to a script that has a single instance (like a script attached to a specific Quest or ReferenceAlias). This is because you will have to choose the specific instance of the script you want to access when you fill the property in the CK.
Example:
myRefAliasScript property refScript auto ;fill this property with your quest in the CK editor
;...
refScript.myRefAliasScriptFunction01()
refScript.myRefAliasScriptFunction02() ;access two functions that are in the reference alias script
Method Two: Access the Target Script by Creating a Variable On-the-fly
Declare a variable that has the type of the target script (ScriptB) that you want to access. Then set that variable to equal the instance of ScriptB that needs to be accessed. This method is best for times when:
- (1) There are more than one instances of ScriptB that need to be differentiated (ScriptB is attached to several different Actors, for example)
- (2) ScriptB does not exist before run-time, so a property cannot be filled with it (ScriptB is attached to an ObjectReference that doesn't exist until ScriptA PlaceAtMe()'s it into existence, for example)
Example One:
Access the script functions on a created ObjectReference:
ObjectReference Pony1 = PlayerRef.PlaceAtMe(myCustomPony) ;create two ponies. Let us assume that myCustomPony is a base Actor that has 'PonyScript.psc' attached to it.
ObjectReference Pony2 = PlayerRef.PlaceAtMe(myCustomPony)
PonyScript Pony1Script = Pony1 as PonyScript ;declare two variables, each pointing to the INSTANCE of PonyScript attached to one particular pony
PonyScript Pony2Script = Pony2 as PonyScript
Pony1Script.groomPony() ;groom pony one, using the groomPony() function in (its instance of) PonyScript
Pony2Script.killPony() ;kill pony two, using the killPony() function in (its instance of) PonyScript
Note: sometimes you will have to cast the object with ScriptB attached to it before declaring the variable will work. Let us say that Pony1 was an Actor instead of an ObjectReference, for instance. Since PonyScript extends ObjectReference, we first need to cast Pony1 as an ObjectReference before we can cast it as a PonyScript, otherwise the compiler will throw out errors:
Actor Pony1 = somePony
PonyScript Pony1Script = (Pony1 as ObjectReference) as PonyScript
Example Two:
Find an Actor's linked reference, and conditionally access the script functions on that reference:
ObjectReference possibleTable1 = Actor1.GetLinkedRef()
if (possibleTable1 as Furniture) == magicTable ;is the actor linked to a magicTable?
magicTableScript TableScript1 = possibleTable1 as magicTableScript
TableScript1.explode() ;if so, use the magicTable's script function to make the magicTable explode!
endif
Notes
- The nomenclature of Bethesda's functions' arguments is consistent, prefixing argument names such that their nature is easily determined. The naming convention is as follows, each prefix denoting the corresponding qualities:
- a : Argument :: b : Bool :: f : Float :: i : Int :: p : Pointer :: s : String :: k : Form/Alias :: u : Unsigned
- auiCount, for instance, is an unsigned integer argument while asFileName is a string argument. Note that 'p' and 'k', for Papyrus' purposes, are interchangeable and that Papyrus does not actually have pointers.
Bugs
- In typed functions, the compiler does not properly check all code paths for returns with values. If the function exits without providing a return value, the result is indeterminate and causes unexplained failures throughout related scripts (possibly due to stack corruption).
See Also
Language: | [[::Function Reference|English]] • [[::Function Reference/fr|français]] |
---|