Difference between revisions of "States (Papyrus)"
imported>Ereksen m |
imported>Mojo (Added example of priorities of how functions are picked) |
||
Line 80: | Line 80: | ||
In short, functions inside states override functions inside the 'empty state', and functions inside derived scripts override the ones in the scripts they extend. | In short, functions inside states override functions inside the 'empty state', and functions inside derived scripts override the ones in the scripts they extend. | ||
For example: | |||
<source lang="papyrus"> | |||
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 | |||
</source> | |||
<source lang="papyrus"> | |||
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 | |||
</source> | |||
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= | =How to Set a Script's State= |
Latest revision as of 00:23, 5 December 2013
Overview[edit | edit source]
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 States[edit | edit source]
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'[edit | edit source]
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[edit | edit source]
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[edit | edit source]
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.
For example:
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[edit | edit source]
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[edit | edit source]
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[edit | edit source]
- 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
Conclusion[edit | edit source]
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 |
---|