Scripts operate in varying states - but a script can only be in one state at a time. What code is run when a function is called or an event occurs depends on the state the script is in.
Defining a state in a script is very simple, just set up a state block as follows:
state MyState ; Various functions here endState
If you want your script to start in a particular state, put "auto" in front of the state block:
auto state StartHere ; Functions here endState
The 'Empty State'
The 'empty state' is the implicit state that every function not inside a state block is in.
function MyFunction() ; This function is in the 'empty state' endFunction state MyState function MyFunction() ; This function is in the MyState state endFunction endState
Defining Functions/Events Inside States
To define a function or event inside a state, simply put the function or event inside the state block.
state MyState function SpecialFunction() ; This function is in the MyState state endFunction endState
Please note: the function or event must be defined in the 'empty state' with the same return type and the same parameter types or the compiler will complain at you. This is because of the way the game resolves function and event calls at run-time.
function SampleFunction(int myParameter) ; Code here endFunction state SampleState function SampleFunction(int aParameter) ; This function is fine - the type of parameter is the same as in the 'empty state' endFunction function OtherFunction() ; Error! OtherFunction does not exist in the 'empty state' endFunction endState state OtherState int function SampleFunction(int myParameter) ; Error! SampleFunction return type doesn't match the one in the 'empty state' endFunction endState state YetAnotherState function SampleFunction(int myParameter, float parameter2) ; Error! SampleFunction parameters don't match the one in the 'empty state' endFunction endState
For your convenience, events that various kinds of scripts can receive are already defined for you in the empty state inside the scripts that you extend (i.e. ObjectReference, Actor, etc). So you do not have to define events in the empty state when all you want to do is modify the event in one particular case.
How Functions Are Picked
When someone calls a function, or the object receives an event, the one that is picked is resolved as follows:
- If the script has the function in its current state, call that one
- If the script extends another script that has the function in its current state, call that one
- If the script has the function in the 'empty state', call that one
- If the script extends another script that has the function in the 'empty state', call that one
In short, functions inside states override functions inside the 'empty state', and functions inside derived scripts override the ones in the scripts they extend.
Scriptname ParentScript extends Quest Function MySuperCoolFunction() Debug.Notification("HELLO WORLD!") endFunction State StateThree Function MySuperCoolFunction() Debug.Notification("I saw a mudcrab the other day...") endFunction endState
Scriptname ChildScript extends ParentScript State StateOne Function MySuperCoolFunction() Debug.Notification("STOP RIGHT THERE CRIMINAL SCUM!") endFunction endState State StateTwo Function MySuperCoolFunction() ;do nothing endFunction endState State StateThree ;MySuperCoolFunction() not defined endState ; State StateFour ;MySuperCoolFunction() not defined endState
If we call MySuperCoolFunction() on ChildScript, here are the results of what notification is printed in the four defined states.
- StateOne - "STOP RIGHT THERE CRIMINAL SCUM!" - Priority 1.
- StateTwo - Nothing happens - Also Priority 1.
- StateThree - "I saw a mudcrab the other day..." - Priority 2
- StateFour - "HELLO WORLD!" - Priority 4 - If we had a function defined in our empty state of ChildScript, then that function will run instead per Priority 3.
How to Set a Script's State
Setting a script's state is simple, just call GotoState(string asStateName) with the name of the state you want it to go to as a string. The following sequence of events will then take place:
- OnEndState is sent to the script for the state that they were in before.
- The state is switched to the requested state
- OnBeginState is sent to the script for the state it just entered.
The name of the state to enter is not case-sensitive. If you want to go to the 'empty state', simply pass in the empty string: "".
Also - calling GotoState will not end your function - it will still continue to run, so it's perfectly acceptable to just change your object's state during a certain piece of code and to change it back when you're done.
function MyFunction() GotoState("TurnOffActivate") ; Do a bunch of long-running stuff GotoState("") endFunction state TurnOffActivate event OnActivate(ObjectReference akTriggerRef) ; Do nothing endEvent endState
How to Get a Script's State
Getting a script's state is also simple, call GetState() which will return the state name, as a string, that the script is currently in. Please note that the case of the state name depends on the call that set that state in the first place, and that string compares are case-sensitive, so be careful when doing compares. (In the future we may have ways to compare strings that ignores case to make this easier - for now, be careful)
Tricks and Tips
- If you want to disable an event or function when you are in a particular state, simply define that event or function in the state and leave it empty. This is especially useful if you want to, say, ignore any activate events while you are in the middle of doing something.
- If only having one state at a time is a bit too restricting for you, remember that you can always attach multiple scripts to the same object - and each script can have its own, separate state! This may help you with more complex operations. Of course you can also fall back on just using if statements as well with your own state variables.
- Because state names are simply strings, you can construct them at run-time using the "+" operator. For example, you can define "State1", "State2", and so on, and pick them via the following:
Function GotoNumberedState(int number) GotoState("State" + number) EndFunction
States are a powerful and reasonably easy way to modify the behavior of your script without having to write overly large if statements or other complicated code. Sometimes problems that seem overly complex or troublesome may become easier with creative use of states!
|Language:||English • français|