Editing Variables and Properties
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
=Description= | |||
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. | 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.) | |||
=Declaring Variables= | |||
<source lang="papyrus"> | <source lang="papyrus"> | ||
float myFloat | float myFloat | ||
Line 10: | Line 11: | ||
</source> | </source> | ||
MyFloat starts at 0, myOtherFloat starts at 13.5 and can be set by scripting in | MyFloat starts at 0, myOtherFloat starts at 13.5 and can be set by scripting in it's own script, but nothing else. | ||
=Declaring Properties= | |||
==Full Property== | |||
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" | 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" | ||
Line 75: | Line 76: | ||
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. | 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. | ||
==Auto Properties== | |||
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. | 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. | ||
Line 85: | Line 84: | ||
</source> | </source> | ||
==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. | 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. | ||
Line 94: | Line 92: | ||
</source> | </source> | ||
==Conditional Properties== | |||
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. | 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. | ||
Line 103: | Line 100: | ||
</source> | </source> | ||
More information on the conditional keyword can be found in the [[Papyrus_Introduction#Writing_Custom_Functions|Papyrus Introduction]] | More information on the conditional keyword can be found in the [[Papyrus_Introduction#Writing_Custom_Functions|Papyrus Introduction]] | ||
=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. | 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. | ||
Line 129: | Line 125: | ||
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 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 | In otherwords, 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. | ||
===With kmyQuest=== | |||
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. | 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. | ||
Line 138: | Line 134: | ||
float myDeadCount | float myDeadCount | ||
myDeadCount = kmyQuest.deadCount ;getting property | myDeadCount = kmyQuest.deadCount ;getting property | ||
kmyQuest.deadCount = | kmyQuest.deadCount = 5 ;setting property | ||
</source> | </source> | ||
==From a non-owned fragment / other quest script== | |||
Need to write this... basic gist: You need to define a property in your script (and set it through the editor interface to be the other quest whose properties you want access to), then you can access that property's properties. In other words, your script has a property of the other quest; then you access that property's properties. | |||
[[User:Evernewjoy|Evernewjoy]] | |||
---- | |||
'''Accessing a Script's Variables From Another Script''' | |||
---- | |||
''Here are the steps to using a variable from one script in another script, please note the script could be of any type, not just a quest script.'' | |||
'''1.''' Define the variable you want to pass to other scripts as a property as explained above. | |||
Here is a full script containing a property / publicly-available variable | |||
<source lang="papyrus"> | <source lang="papyrus"> | ||
Scriptname | Scriptname RamaJRMasterScript extends ObjectReference | ||
;this value is private to the script and cannot be | |||
;accessed | |||
int hiddenInt = 144 ;initialized value | |||
;the name of the property/var you want to use in | |||
;other scripts, which is just a wrapper for the | |||
;hidden var | |||
int property publicInt | |||
int function get() | |||
return hiddenInt | |||
endFunction | |||
function set(int value) | |||
hiddenInt = value | |||
endFunction | |||
endProperty | |||
</source> | </source> | ||
(code above was essentially copied from earlier in this article, but this is a complete running script) | |||
'''2.''' In the other script, where you want to access the variable from the script above, you must define the following: | |||
* the script that contains the variable you want to access, you must define the script as a property, note that the type of the property is the name of the script that contains the variable you want. | |||
* a variable that is going to be used to refer to the script property in A (above) | |||
''See below for a working script with some especially important lines emphasized.'' | |||
Note that the message used in this script must be created by you if you want to use this script example, use the %.0f twice in your message to accommodate the two variables I am passing. I pass one variable just so you have a way to know your message itself is working properly: | |||
<source lang="papyrus"> | <source lang="papyrus"> | ||
Scriptname | Scriptname RamaWorkingSCRIPT extends ObjectReference | ||
;you must set these "property" values outside this | |||
;script. | |||
;see number 3 in article (below) | |||
message property msg auto | |||
;*** | |||
RamaJRMasterScript property masterScript auto | |||
RamaJRMasterScript scriptVar | |||
;*** | |||
;the scriptVar above is very important because you | |||
;cannot directly access a property script, you must | |||
;use a variable that is private to this script. | |||
bool done = false ;ensures switch runs only once | |||
int test = 2 | |||
;any event could be used here, like onTriggerEnter, | |||
;make a trigger volume in the editor and attach | |||
;this script to it and use onTriggerEnter for | |||
;easy testing | |||
;this example works with an activator of some kind | |||
;like a button or door | |||
EVENT onActivate (objectReference triggerRef) | |||
if (!done) | |||
;only run if player is the one activating this | |||
;object | |||
if(triggerRef == game.getplayer()) | |||
done = true ;makes button run only once | |||
;--- External Variable Script Section Begins | |||
;*** | |||
scriptVar = masterScript | |||
;*** | |||
;this line above is VERY important, you have to | |||
;set the script var within the script itself, | |||
;to the script-as-a-property that contains the | |||
;the variable you want to access | |||
scriptVar.publicInt += 1 | |||
;you can now manipulate the other script's hidden | |||
;var via its public property name and functions, | |||
;using the scriptVar | |||
msg.show(scriptVar.publicInt,test) | |||
;a sample message to prove you have accessed the | |||
;other script correctly, should get a value of 145 | |||
;for the script var when it is first displayed | |||
endif | |||
endif | |||
endEVENT | |||
</source> | </source> | ||
'''3.''' Final steps, setting the properties | |||
You | |||
'''You must have an object in the game world / your dungeon / cell for each script.''' | |||
''You need an instance of the script that has your variable that you want, in this case RamaJRMasterScript. | |||
You need this even if the script is just a variable storage device / reservoir'' | |||
A. Once you create the object, could be an activator of any kind or an actor, or anything really, attach the RamaJRMasterScript script. | |||
B. Name this object something clear, like "sampleReferenceWithScriptInstance" | |||
C. Now make the switch object, I used a dwarven button, you can use any activator you want. | |||
D. Now attach the script RamaWorkingSCRIPT to the button/activator. | |||
E. '''Now set the properties of the button/activator:''' | |||
msg = your sample message that you create that contains two %.0f for use with the variables | |||
masterScript = point this to the INSTANCE/Object of the script that you have, the name will appear as the fancy name you created above. | |||
Plus it is very likely to be the only option the list | |||
'''Things to Remember''' | |||
* If you do not make an instance of the script that contains the variable you want to access, you cannot use the variable, you must have an object with the variable-reservoir script attached to itself. | |||
* Remember to set the scriptVar to the script-as-a-property, the highlighted line in the script itself. | |||
If you follow all these steps you will now be able to access and modify variables from one script in another script. | |||
'''Example uses: | |||
''' | |||
1. keeping track of a total of enemies killed, where each enemy has a death script to increment a value in a master script | |||
2. keeping track of number of switches activated, where each switch increments a master script variable | |||
3. basically infinity different very important and wonderful things, hee hee! | |||
♥ | |||
Rama | |||
PS: Infinite ♥ and thank you's to our friends at Bethesda for giving us such an awesome game as Skyrim and such an beautiful editor as the Creation Kit! | |||
The Creation Kit is incredibly stable, robust, and a joy to use. | |||
Thank you! | |||
End [[User:Evernewjoy|Evernewjoy]] | |||
=Warnings= | |||
Be careful with variables and auto properties on scripts that are extended by other scripts - especially where some script somewhere else may have a property pointing to the base script, or trying to cast to the base script. This is because it would be possible to have two copies of a script attached to the same object, thereby creating two copies of the variable/auto property - and the other scripts that refer to the base script may randomly pick which one to talk to. | |||
This is doubly-true of scripts with native functions, as 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. | |||
==Notes== | ==Notes== | ||
*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. | *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. | ||
=See Also= | |||
*[[Property Reference]] | *[[Property Reference]] | ||
[[Category: Papyrus]] | [[Category: Papyrus]] | ||
[[Category: Papyrus Tutorials]] | [[Category: Papyrus Tutorials]] | ||