Special keywords in UnrealScript.
Self
The Self keyword represents the object it is used it.
Self.Destroy();
has the same meaning like
Destroy();
Self isn't really useful here, but the next (silly :rolleyes:) example will not work without it:
Level.Game.RegisterDamageMutator(Self); if ( Level.Game.BaseMutator == Self ); log("I'm the boss");
None
None is an empty object reference. Every object variable (classes, Actors, UWindow stuff) can take this value.
Note: You cannot access the properties of object references set to None. Trying to do so causes so-called Accessed None log warnings. Accessed Nones can lead to unexpected results and should be avoided by using something like:
if ( MyActor != None ) { ... }
Default
The Default keyword is used to access default properties of variables in a class.
Note that the two following lines will always log the same values:
log(Class.Default.ItemName); log(Default.ItemName);
Note that you can also change the default variable value by using the same syntax:
MyObject.Default.SomeVar = SomeNewDefaultValue;
Of course you'll lose the old default value if you do this, so if you want it back you'll have to save it yourself, or restart the level.
Static
The Static keyword is used to call static functions of a class:
class'DeathMatchPlus'.Static.StaticSaveConfig();
Super
With the Super keyword you can call functions in the same state of a superclass of this object.
Let's take the BugEyedMonster class from Extending States. Its superclass Monster is a subclass of Pawn: Pawn >> Monster >> BugEyedMonster.
Let's suppose you have overridden the Monster's PostBeginPlay function in BugEyedMonster, but it should still execute the stuff in the Monster class's PostBeginPlay function. It would be a bad idea to copy all of the code from Monster.PostBeginPlay to BugEyedMonster.PostBeginPlay.
The better way would be this:
function PostBeginPlay() { // our own code here Super.PostBeginPlay(); // do the stuff from Monster }
It might seem obvious, but these functions do not share their local variables. They are completely different functions. If PostBeginPlay() got some variables passed to it, you will have to pass them along in the Super.PostBeginPlay() statement if you want Monster's version of the function to have them too.
Now let's say you have another function WhatToDoNext in your BugEyedMonster class. You need to execute the stuff from the Pawn class's WhatToDoNext function, but not the code from the Monster class. Again copying code isn't the solution. Pawn is a superclass of our BugEyedMonster, so you can use the Super keyword again, this time with a slightly different syntax (note that if you've ever wanted to do something like Super.Super, this is how to do it):
function WhatToDoNext(name LikelyState, name LikelyLabel) { Super(Pawn).WhatToDoNext(LikelyState, LikelyLabel); ... }
Again: If the BugEyedMonster is in a certain state then WhatToDoNext function of the same state in the Pawn class will be called. If Pawn doesn't have that state or the function isn't declared in that state of the Pawn class or any of its superclasses, then the non-state WhatToDoNext function of the Pawn class will be executed. If Pawn also doesn't have a global WhatToDoNext function then the global WhatToDoNext function of the most-derived superclass will be used. In any other case (i.e. there's no WhatToDoNext function in Pawn or any superclass) the compiler will tell you about that.
Note that the simple Super.FunctionName() call will not call the super class version of a function if the state containing the function does not exist in the super class. You have to distiguish between two cases here:
- The state extends another state in the same class
- Super.FunctionName() will call the function in the state's parent state. (also see Extending States)
- The state doesn't extend another state
- Super.FunctionName() will call the non-state version of the function in the same class or any of its super classes.
Tarquin: Would a tree diagram help (assuming I've got it right)
Wormbo: This stuff can become quite complex, so maybe I'll start up a page about state hierarchies or something. This works quite similar to class hierarchies and actually is as simply, but you first have to get a grip at the concept.
Global
The Global keyword calls the most-derived global (non-state) version of a function, i.e. if there's a non-state version of the function in this class it will be executed, if not the non-state version of the function will be searched for in the superclasses.
In other words, Global.DoStuff looks for a version of DoStuff that is non-state. If there isn't a non-state DoStuff in the current class, it climbs the tree until it finds one.
The BugEyedMonster again: :-)
Let's say you have a SitDown function in the BugEyedMonster's Idle state and a non-state SitDown function in the Monster class, but no non-state SitDown function in the BugEyedMonster class.
Now if you are in the BugEyedMonster's Idle state and execute
Global.SitDown();
the most-derived global version of the SitDown function is the non-state one in the Monster class.
It's more obvious than for the Super keyword, but it's still worth mentioning that the two functions don't share their local variables.
Stop
Stop is a keyword relevant only in latent runtime, so for short, States. Stop is used to end execution of state code (not functions). Think of it as an equivalent of the return keyword for states, if it is easier, not by the fact it returns a value but because it stops the execution of the code that follows. This is best used when labeling States as making multiple labels will not mean each label is executed at a specific time, but all sequentially (starting with the label you specified by using either the goto keyword or GoToState(<state name>,<label>), or Begin if no label is specified). Please note that as stop, goto can only be called from State code to use that certain State label; in special circumstances, there are situations when labels can be used within functions as well, but a goto call from a function within a State will not call that State's label. If you want to reach a certain label from a function, use GoToState(). Here is a nice example on how to take advantage of the Stop keyword from the Engine.Mover.TriggerToggle state:
state () TriggerToggle { [...] Open: if ( DelayTime > 0 ) { bDelaying = true; Sleep(DelayTime); } DoOpen(); FinishInterpolation(); FinishedOpening(); if ( SavedTrigger != None ) SavedTrigger.EndEvent(); Stop; Close: DoClose(); FinishInterpolation(); FinishedClosing(); }
For additional information on goto and Stop, see Flow_Syntax, for more information regarding Global and states, in general, see also State.
Tarquin: "Think of it as an equivalent of the return keyword for states if it is easier" – how is it like a return? Where do you return when you reach a Stop?
Mychaeel: I suppose that the analogy is that you return from the code you're currently executing, skipping the remaining statements (in the function body or the state), not that you return to somewhere.
Xian: Exactly :) Perhaps I should have been a bit more precise but Mychaeel read between the lines. Return has 2 purposes, one to return a value and one to stop the remainder of the code.
Oh and coincidentally by opening Flow_Syntax I found this:
Stop
Imediately stops execution of State code. This is like the return command for states.
So I guess another author thought it like me :) I always believe it is better to give analogies when it comes to code (basically the "you know one, you know them all" theory). But yeah I'll make it a bit clearer.
Derrick: As a somewhat noob to UnrealScript (and even Unreal for that matter) it's hard for me to understand what the following code really is doing without having knowledge of what a BaseMutator or DamageMutator is. Perhaps you could think of a more universal example. But, then again I don't think this is really meant as a tutorial.
Level.Game.RegisterDamageMutator(Self); if ( Level.Game.BaseMutator == Self ); log("I'm the boss");
I'm assuming that RegisterDamageMutator is accessed publicly, here adding the object to the list of the game's registered damage mutators? (whatever that means) and it assigns itself as the value of the game's sole base mutator? (whatever that means) and only then can it display messages to the log page?