Extending Scripts (Papyrus)
Overview[edit | edit source]
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. More specific script objects are based on more general ones. Typically more specific objects are called children and the more general ones are called parents. Script children inherit certain qualities from their parents. For example, Actor Script has access to all the events and functions listed on ObjectReference Script and Form Script, even though they aren't all listed on Actor Script.
Terminology[edit | edit source]
- Parent: The original script that is being extended.
- Child: The script that is extending its parent.
- Inherit: When a child script gains something from its parent without modifying it, it "inherits" them.
- Override: When a child script changes the behavior of something in its parent by making a new version, it "overrides" the parent version.
How to extend[edit | edit source]
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.
Example:
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[edit | edit source]
Functions and Events[edit | edit source]
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.
Example:
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:
Child MyFunction!
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:
Parent MyFunction!
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:
Parent MyOtherFunction!
The child doesn't override this function, so the original parent function is used.
Calling a function on your parent[edit | edit source]
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 you script to only make a minor tweak to something before letting the parent do all the heavy lifting.
Example:
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[edit | edit source]
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[edit | edit source]
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.
Example:
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[edit | edit source]
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.
Example:
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.