Mod:Creation Kit/Extending Scripts (Papyrus)

Overview
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, Mod:Creation Kit/Actor Script has access to all the events and functions listed on Mod:Creation Kit/ObjectReference Script and Mod:Creation Kit/Form Script, even though they aren't all listed on Actor Script.

=Terminology=
 * 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= 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=

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.

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

Child MyFunction! The child here is overriding and replacing the parent's function with its own.
 * Attaching the child 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 the parent script to something and then calling MyFunction on it:

Parent MyOtherFunction! The child doesn't override this function, so the original parent function is used.
 * Attaching either script to something and then calling MyOtherFunction on it:

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 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

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.
 * Calling MyFunction on this child script attached to an object:

States
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
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
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

Child MyVar = Hello World! Parent MyVar = 1 Note that both scripts can only see their local copy of the variable.
 * Calling MyFunction on a child script attached to an object: