I search for solutions in this order: Past Code, Unreal Source, Wiki, BUF, groups.yahoo, google, screaming at monitor. – RegularX

Function call specifiers

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search

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.

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:

  1. B.F()
  2. B.F()
  3. A.F()
  4. A.F()

No surprises here.

Case 2: State X[edit]

If our B instance is in state X, the following implementations are called:

  1. B.X.F()
  2. B.F()
  3. A.X.F()
  4. 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:

  1. B.Y.F()
  2. B.F()
  3. B.X.F()
  4. 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?

  1. B.Y.F()
  2. B.F()
  3. A.X.F()
  4. 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!