Variables and Properties
Variables and Properties are similar things, they both "hold" values and objects. A variable is "private" meaning that only that script is aware of them, can set their contents, and get their contents. A Property is essentially a variable that other scripts can access, their contents can be set and get by a other scripts.
If a variable or property holds a numeric value, like an integer, get/set returns its value. If a variable or property holds an object, you can access that object's properties and functions. (This is analogous to a reference variable from the old scripting system.)
float myFloat float myOtherFloat = 13.5
MyFloat starts at 0, myOtherFloat starts at 13.5 and can be set by scripting in its own script, but nothing else.
To define a property, you first write the type, then "property", then the name of the property. You then define two functions, a get which returns the property's value, and a set which takes a new value for the property. And then you cap it off with "EndProperty"
int myInt_Var = 0 ; Where the property's value is stored int property myInt int function get() return myInt_Var endFunction function set(int value) myInt_Var = value endFunction endProperty
If you leave out the get function, the property is write-only - other people can set the value, but no one can read it. The local script, of course, can read the actual variable the property works with. If you leave out the set function, the property is read-only - other people can see the value, but they can't change it. Again, the local script can always set the variable that the property returns.
You don't have to just have the property return and set the value like you see above - the functions could do anything. You could, for example, put some if statements in the set function to ensure that the value is never outside a certain range. Or you could even play an animation when a certain value is set. Heck, you don't have to actually have a variable at all - it could be a calculated value or a constant.
bool property Locked bool function get() return IsLocked() endFunction function set(bool value) Lock(value) endFunction endProperty
int myVar = 5 int property ReadOnly int function get() return myVar endFunction endProperty
The above property is read-only. Scripts outside of this one cannot change the value, but the script itself can change the value of the variable.
int myVar = 5 int property WriteOnly function set(int value) if value >= 0 myVar = value else myVar = 0 endIf endFunction endProperty
The above property is write-only. Scripts outside of this one cannot read the value. It also uses an if to make sure the value is never below 0.
If a full property has its value set in the Creation Kit, its set function will be called when the object is initialized, just before its OnInit event is called.
An auto property is one that writes the above get and set functions for you, behind the scenes. There are also some minor optimizations in the VM that speed up auto properties slightly. To make an auto property, simply omit the functions and endProperty and add "auto" to the end of the property definition. You can set the property's initial value using the "= <value>" syntax.
int property myInt = 5 auto
Auto Read-only Properties
An auto read-only property is an auto property that can never have its value changed. This can be convenient if certain numbers mean different things in your script and you want to use a name instead of a number to represent it. You specify these by using "AutoReadOnly" instead of "Auto". These properties must have their initial value set using "= <value>" syntax.
int property myReadOnlyInt = 20 autoReadOnly
Properties cannot be declared as conditional. Auto properties can be defined as conditional because what they actually do is define the hidden variable they create as conditional. This is why you see mangled auto property names when you select a Papyrus variable in the condition system - you're selecting from a list of hidden variables.
int property myVar auto conditional
Getting Properties of a Quest Script
From Result Script Owned by the Same Quest
Often you will need to get a property of a quest script, and use it in a result script somewhere else. This is one of the more tricky things, but once you understand what's happening, it makes sense. First look at the example, then we'll describe what's happening.
;I have a quest script with this in it: scriptName MQ01Script extends Quest int property deadCount auto ;I have a result script (OWNED by MQ01) with this in it: MQ01Script myQuest ;declares a variable "myQuest" which is a TYPE of MQ01Script myQuest = GetOwningQuest() as MQ01Script ;sets the myQuest variable to it's owning quest as the type MQ01Script float myDeadCount ;declaring the variable "myDeadCount" myDeadCount = myQuest.deadCount ;setting local variable to be the quest's property value ;you can also set the quest property thusly: myQuest.deadCount = 10
What's happening here is that we have a property "deadCount" that is in the script "MQ01Script" attached to MQ01. We also have a script that is owned by MQ01 (could be dialogue result, package result, or script attached to an alias).
In the result script, we create a variable that represents the quest script that has the property we want (in this case MQ01Script's "DeadCount" property). Note our variable myQuest is declare as MQ01Script. This is because when we made our quest script "scriptName MQ01Script extends Quest" we've essentially created a new type of object... a MQ01Script object. GetOwningQuest returns a quest object (before we extended it). So we also need to cast the quest returned by GetOwningQuest AS that new object "myQuest = GetOwningQuest() as MQ01Script" so we have access to it's extended properties. If we didn't cast it as a MQ01Script it would only have the functions and properties of a Quest object, which wouldn't contain our deadCount property.
In other words, when we created MQ01Script which extended the Quest script, unless we cast the object returned by GetOwningQuest AS our new script, it won't have our new properties declared in our new script.
If the fragment you are using has a "kmyquest" drop down, you can select a script attached to the quest owning that fragment, and then use the kmyQuest "magic variable" to refer to quest script without casting it.
the above would be simplified to just:
float myDeadCount myDeadCount = kmyQuest.deadCount ;getting property kmyQuest.deadCount = 10 ;setting property
From Within a Magic Effect Script
Let's look at an example where a scripted spell accesses a quest's properties:
Scriptname myQuestNameScript extends Quest Int Property PublicInt Auto ; This value is defined as a property and can be accessed from outside this script Int PrivateInt = 30 ; This value is private to the script and cannot be accessed from outside this script Function DamageTargBasedOnPublic(Actor akTarget) ;This code will damage the akTarget for PublicInt damage akTarget.DamageAV("Health", PublicInt) EndFunction Function DamageTargBasedOnPrivate(Actor akTarget) ;This code will damage the akTarget for PrivateInt damage akTarget.DamageAV("Health", PrivateInt) EndFunction
Now that we have defined our quest script and created an accessible property, we can control it from the outside.
Scriptname mySpellEffectScript extends activemagiceffect myQuestNameScript Property myQuestRef auto Event OnEffectStart(Actor akTarget, Actor akCaster) myQuestRef.PublicInt = 20 ; This will change the damage for the DamageTargBasedonPublic Function myQuestRef.DamageTargBasedOnPublic(akTarget) ; You can manipulate this damage by changing PublicDamage Prior to calling it myQuestRef.DamageTargBasedOnPrivate(akTarget) ; This will always do 30 damage unless the quest changes the private variable EndEvent
After this point, you will need to go to the properties window for whatever your script is attached to (in this case, the script properties windows of the script for mySpellEffectScript) and then set the property for myQuestRef to the Quest associated with the quest script.
Getting Properties From Any Other Script
You can use the above example regarding the Magic Effect script as a basis for your script. You must define a property in your script, with the "Type" of your object you are wishing to access. If your object has a custom script, define the type as your object's script name. Be careful not to declare it as the object's name. All objects can have multiple scripts, so you must specify the script name you want to access. For a list of objects you can use as a type that are already within the game, visit the Script Objects page.
Be careful with variables and auto properties on "base" scripts, which are extended by multiple other scripts. This is because it would be possible to have multiple scripts containing the same variable or auto property attached to the same object, and the game may not reliably select the appropriate instance of the variable or property.For example, consider the following 3 short scripts:
ScriptName Base extends ObjectReference Int Property MyValue Auto
ScriptName Derived1 extends Base
ScriptName Derived2 extends Base
Because both Derived1 and Derived2 extend Base, they each inherit its MyValue property.Now, imagine that an object is created and the scripts Derived1 and Derived2 are both attached to it. Trying to access the value of MyValue by casting this object to Base will not reliably return the same value:
(MyObjectReference as Base).MyValue
This is doubly-true of variables and auto properties declared in native script objects, such as the Actor Script. This is because the game can attach these to in-game objects at any time if it needs to, thereby creating another copy of the variable or auto property.In order to avoid these problems, avoid editing native script objects, and in the case where a single object has multiple scripts attached to it that inherit the same property, make sure you cast it to its most derived form before attempting to access that property. In the above example, that would mean using syntax like this:
(MyObjectReference as Derived1).MyValue
- The list of properties in properties dialog is only updated after adding a new property or after compiling the script with the build-in editor.
|Language:||English • français|