Extending Scripts (Papyrus)
- 1 Overview
- 2 How to extend
- 3 What an extended script can do
- 4 Common Functions and Events
Script extending is the act of taking a script that almost does what you want, and then modifying some of its events or functions to do something different without editing the original script.
- The script that is extending its parent.
- When a child script gains something from its parents without modifying it, it "inherits" these things.
- When a child script changes the behavior of something in its parent by making a new version, it "overrides" the parent's version.
- The original script that is being extended.
How to extend
Extending a script is easy: At the top of the script after "scriptname x", you add "extends y" where Y is the name of the script you want to extend.
Scriptname SpikeTrap extends Trap
In this case, the "SpikeTrap" script is extending the "Trap" script. You can kind of think of this as an "is a" relationship. A SpikeTrap "is a" Trap.
What an extended script can do
Functions and Events
An child script has access to all the functions and events from its parent. Any function or event that you do not implement in the child script is inherited by the child. If a function or event is implemented in the parent, and you implement it in the child as well, then the child one overrides the parent, and any calls to that function or event will use the child's version instead. Note that when you implement the function or event in the child you must match the parameters and the return type, along with the name. If you don't the script will not compile.
Scriptname ParentScript Function MyFunction() Debug.Trace("Parent MyFunction!") EndFunction Function MyOtherFunction() Debug.Trace("Parent MyOtherFunction!") EndFunction
Scriptname ChildScript extends ParentScript Function MyFunction() Debug.Trace("Child MyFunction!") EndFunction
- Attaching the child script to something and then calling MyFunction on it:
The child here is overriding and replacing the parent's function with its own.
- Attaching the parent script to something and then calling MyFunction on it:
The child script doesn't exist in this case, so the old parent functionality stays intact.
- Attaching either script to something and then calling MyOtherFunction on it:
The child doesn't override this function, so the original parent function is used.
Calling a function on your parent
If you want to actually call a function on your parent script and ignore the function in your own script, you can use the special "parent" variable. Note that this variable only works on yourself - you cannot use it to call something on a different script. This is most commonly used if you want your script to only make a minor tweak to something before letting the parent do all the heavy lifting.
Scriptname ChildScript extends ParentScript Function MyFunction() Debug.Trace("Child MyFunction!") parent.MyFunction() EndFunction
- Calling MyFunction on this child script attached to an object:
Child MyFunction! Parent MyFunction!
Note that the parent variable forced the parent version of the function to be called, rather then calling the child version.
States in a child script are merged with states from the parent script. Functions in the same state in the child will override functions in the parent - and all states will be merged.
- Parent has state, child does not: Parent functions in that state will be used.
- Child has state, parent does not: Child functions in that state will be used.
- Parent has function in state, child does not: The parent version will be used.
- Child has function in state, parent does not: The child version will be used.
- Both have function in the same state: The child version will be used.
Properties in a parent script behave just as if they were properties on the child script. However, you cannot override them in the child to do something different. If you attempt to do so the compiler will complain.
Scriptname ParentScript int Property MyProperty Auto
Scriptname ChildScript extends ParentScript Function MyFunction() Debug.Trace("MyProperty = " + MyProperty) EndFunction
Note that MyProperty is used in the child script as if it existed there, even though it exists in the parent.
Variables are private and can not be seen by any other script, including your parent or child scripts. Having a variable with the same name as one in your parent script will completely hide the parent variable when accessed in a child function. The function on the parent will use its own variable.
Scriptname ParentScript int MyVar = 1 Function MyFunction() Debug.Trace("Parent MyVar = " + MyVar) EndFunction
Scriptname ChildScript extends ParentScript string MyVar = "Hello World!" Function MyFunction() Debug.Trace("Child MyVar = " + MyVar) parent.MyFunction() EndFunction
- Calling MyFunction on a child script attached to an object:
Child MyVar = Hello World! Parent MyVar = 1
Note that both scripts can only see their local copy of the variable.
A note on casting objects as their parent types
Lets say I've got a script
Horse and I've got a script which extends
WarHorse. In general, a horse would probably run away when seeing a wolf, but a warhorse may attack it instead:
Scriptname Horse extends Actor Event OnSeeWolf() Debug.Notification("Horse runs away.") EndEvent
Scriptname WarHorse extends Horse Event OnSeeWolf() Debug.Notification("Horse attacks wolf.") EndEvent
I have an actor
MeanWarhorse with the script
WarHorse attached. Consider the following block of script:
(MeanWarhorse as Horse).OnSeeWolf()
When I call this which message am I going to see, "Horse runs away" or "Horse attacks wolf"?:
It turns out that even if you have cast an object to a parent type (Horse), the object will still behave according to the script attached to it in the CK. Thus in this case, the message you would see is "Horse attacks wolf.". This is a very useful thing to know if you need to send messages to an object, but don't know exactly what type of object it is.
Lets say I've got another type of Horse called a
CartHorse. A carthorse can't run away because it's attached to a cart, so it just stands there looking twitchy.
Scriptname CartHorse extends Horse Event OnSeeWolf() Debug.Notification("Horse gets twitchy.") EndEvent
I have a cloak style enchantment effect on the wolf which does the following:
Scriptname WolfFearEffect extends ActiveMagicEffect Event OnEffectStart(Actor akTarget, Actor akCaster) (akTarget as Horse).OnSeeWolf() EndEvent
With this setup, when a warhorse comes under the wolf's fear effect, it will attack the wolf. When a carthorse is affected, it will stand there getting twitchy, and when an other kind of horse comes under affect, it will run away.
Note: If in this example I had both
CartHorse attached to the same actor, it would be treated as one or the other picking one type seemingly at random.
Common Functions and Events
The functions and events listed here are on all Papyrus scripts, and do not require you to extend another one.
- Function GotoState(string asNewState)
- Changes this script state to the passed-in state
- string Function GetState()
- Returns the state the script is currently in
- Event OnBeginState()
- Called when a state has just been switched to
- Event OnEndState()
- Called when a state is about to be switched away from
|Language:||English • français|