Once I get that upgrade to 36-hour days, I will tackle that. – Mychaeel
Function call specifiers
UnrealScript provides two special keywords for calling functions that would otherwise not be accessible: Super for calling overridden functions and Global for calling non-state functions. However, these function call specifiers are only allowed for calling functions on the same instance (or class for static functions) as the code calling the functions.
Contents
Super[edit]
The keyword Super is used to call an overridden version of a function on the same instance or class.
Simple version: Direct parent state or class[edit]
Syntax:
Super.functionname([parameters])
The simple version uses the parent context of the current state or class to call the function with the specified name. The parent context of a state is either the parent state or, if the state doesn't extend any other state, the state's containing class. The parent context of a class is its parent class.
Note: If the current context doesn't actually override the function called through Super this call will almost be the same as calling the function directly.
Advanced version: Indirect parent class[edit]
Syntax:
Super(classname).functionname([parameters])
The advanced version looks for a class with the specified name. If the call originated in state code or a state function, it looks for a state with the same name in that class and uses that as context for calling the function. If no such state is found, the class is used as context.
Note: This behavior does not play nice with states extending another state with a different name. See examples below.
Global[edit]
The keyword Global is used to call the most-derived non-state version of a function. If the instance is not in any state, this has the same effect as calling that function directly.
Syntax:
Global.functionname([parameters])
Examples[edit]
For this example we'll use two classes. The parent class A:
class A extends Actor; function F(); // doesn't override anything state X { function F(); // overrides A.F }
...and the derived class B:
class B extends A; function F(); // overrides A.F state X // extends A.X { function F(); // overrides A.X.F } state Y extends X { function F(); // overrrides B.X.F }
Now we have an instance of class B that wants to call various implementations of function F():
F(); Global.F(); Super.F(); Super(A).F();
Which implementation those four lines will actually call depends on where exactly they are in class B.
Case 1: No state[edit]
If the instance of B is not in any state, the following implementations are called:
- B.F()
- B.F()
- A.F()
- A.F()
No surprises here.
Case 2: State X[edit]
If our B instance is in state X, the following implementations are called:
- B.X.F()
- B.F()
- A.X.F()
- A.X.F()
Just as expected.
Case 3: State Y[edit]
If the B instance happens to be in state Y, things look a bit different:
- B.Y.F()
- B.F()
- B.X.F()
- A.F()
Wait, Super(A).F()
calls the non-state version of F() in class A? Unfortunately this is a limitation of the advanced version of the Super keyword. It doesn't actually check state inheritance, but only looks for a state with the same name in the specified class.
Case 4: Code in state X after switch to state Y[edit]
This one is a bit tricky and something you have to watch out for, because it may cause you some trouble. Pretend we have the following function in state B.X:
function G() { GotoState('Y'); F(); Global.F(); Super.F(); Super(A).F(); }
The code being executed may still be in state X, but the instance has already switched to state Y. Which versions of F() will be called?
- B.Y.F()
- B.F()
- A.X.F()
- A.X.F()
The second one was expected, Global doesn't care about the state and just calls the global version. Numbers 3 and 4 were kind of expected as well, the code is in state X, so Super calls would be relative to that.
The first one is a bit surprising, though. Code in one state calls a function in a different state! Similar things would happen if you switch from the global state to X or Y or from X or Y to the global state, a simple call to F() will call the new state's implementation.
Be very careful when calling functions after a state switch, the compiler doesn't check for this case. If you try to call a function that is available in the old state, but not in the new state, the game will crash mercilessly!
Declarations | Preprocessor • Classes • Interfaces • Cpptext • Constants • Enums • Structs • Variables (Metadata) • Replication block • Operators • Delegates • Functions • States • Defaultproperties (Subobjects) |
---|---|
Types | bool • byte • float • int • name • string • Object • Class • Enums • Structs (Vector ⋅ Rotator ⋅ Quat ⋅ Color) • Static arrays • Dynamic arrays • Delegates • Typecasting |
Literals | Boolean • Float • Integer • Names • Objects (None ⋅ Self) • Vectors • Rotators • Strings |
Flow | GoTo • If • Assert • Return • Stop • Switch • While • Do...Until • For • ForEach • Break • Continue |
Specifiers | Super • Global • Static • Default • Const |
UnrealScript | Syntax • .UC • .UCI • .UPKG • Comments • #directives • Native |