Skyrim:Variablen und Properties

Aus Skript-Wiki
Version vom 13. August 2012, 13:01 Uhr von Keris (Diskussion | Beiträge) (Textersetzung - „tesscript>“ durch „papyrusscript>“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Beschreibung

Variablen und Properties (Eigenschaften) sind ähnliche Dinge, beide „halten“ Werte (Zahlen und Objects). Eine Variable ist „private“, d.h. sie ist nur im Script bekannt und nur im Script kann auf ihren Wert (lesend und schreibend) zugegriffen werden. Eine Property ist im grunde genommen eine Variable, auf die mit anderen Scripts zugegriffen werden kann, ihr Inhalt kann von anderen Scripts gesetzt (Set) und geholt (Get) werden.

Wenn eine Variable oder Property einen numerischen Wert enthält, kann auf diesen Wert zugegriffen werden. Wenn eine Variable oder Property ein Object enthält, kann auf die Properties und Funktionen dieses Objects zugegriffen werden (dies ist vergleichbar mit den Referenz-Variablen im CS von Oblivion bzw. im GECK von Fallout3)


Deklaration von Variablen

<papyrusscript>

float myFloat
float myOtherFloat = 13.5

</papyrusscript>

myfloat wird mit 0 initialisiert, myOtherFloat mit 13,5. Die Werte beider Variablen können im Script verändert werden aber nirgends sonst.

Deklaration von Properties

Full Property

Um eine Property zu definieren, schreibt man zuerst den Typ, dann „property“, dann den Namen der Property. Man kann zwei Funktionen definieren. Ein „Get“ gibt den Wert der Property zurück und ein „Set“ erlaubt es, der Property einen neuen Wert zuzuweisen. Das Ganze wird mit „EndProperty“ abgeschlossen.

Beispiel <papyrusscript> 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 </papyrusscript>

Wenn man die Get-Funktion weg lässt, ist die Property nur zum Beschreiben (Write-only). Von außen kann der Wert der Property geändert aber nicht gelesen werden. Das lokale Script kann natürlich den zugehörigen gespeicherten aktuellen Wert lesen. Wenn man die Set-Funktion weg lässt, ist die Property nur zum Lesen (Read-only). Von außen kann der Wert gelesen aber nicht geändert werden. Auch hier ist das lokale Script in der Lage, den Wert zu ändern, den die Property bereit stellt.

Man muss nicht so wie im o.g. Beispiel verfahren, um das Get- und Set-Handling der Property zu realisieren. Die Funktionen können alles mögliche tun. Man kann zum Beispiel einige If-Anweisungen in die Set-Funktion packen, um sicher zu stellen, dass ein Wert immer innerhalb eines bestimmten Wertebereiches bleibt. Oder man kann eine kleine Animation abspielen, wenn ein bestimmter Wert gesetzt wird. Ach was, man muss nicht einmal eine Variable haben – ein berechneter Wert oder eine Konstante tut es auch!

Beispiel: <papyrusscript> bool property Locked

 bool function get()
   return IsLocked()
 endFunction
 function set(bool value)
   Lock(value)
 endFunction

endProperty </papyrusscript>

Die obige Property versteckt die Lock und IsLocked ObjectReference Funktionen, so dass man dies Objekt öffnen und abschließen kann, indem man einfach das Locked auf True oder False setzt.

Beispiel: <papyrusscript> int myVar = 5 int property ReadOnly

 int function get()
   return myVar
 endFunction

endProperty </papyrusscript>


Das obige Beispiel ist Read-only. Scripts können von außerhalb den Wert nicht ändern. Das Script selbst jedoch kann den Wert der Variablen ändern.

Beispiel:

<papyrusscript> int myVar = 5 int property WriteOnly

 function set(int value)
   if value >= 0
     myVar = value
   else
     myVar = 0
   endIf
 endFunction

endProperty </papyrusscript>

Das obige Beispiel ist Write-only. Scripts können von außerhalb den Wert nicht lesen. Es enthält ein If, um sicher zu stellen, dass der Wert niemals kleiner 0 ist.

Auto-Properties

Eine Auto-Property schreibt das Get und Set selbst, quasi hinter den Kulissen. Es gibt einige kleine Optimierungen im VM, dass die Auto-Properties ein wenig schneller macht. Um eine Auto-Property zu erstellen, reicht es, die Funktionen weg zu lassen und „auto“ an das Ende der Property-Definition zu schreiben. Man kann einen Anfangswert für die Property mit der Syntax „=<value>“ setzen.

Beispiel: <papyrusscript> int property myInt = 5 auto </papyrusscript>

Auto-Read-only-Properties

Eine Auto-Read-only-Property ist eine Auto-Property, deren Wert niemals geändert werden kann. Das kann praktisch sein, wenn bestimmte Zahlen unterschiedliche Dinge im Script bedeuten und es gewünscht wird, dass der Wert statt druch eine Zahl durch einen Namen repräsentiert wird. Man spezifiziert dies durch den Gebrauch von „AutoReadOnly“ anstelle von „Auto“. Bei solchen Properties muss ein Anfangswert mit der Syntax „=<value>“ gesetzt werden.

Beispiel:

<papyrusscript> int property myReadOnlyInt = 20 autoReadOnly </papyrusscript>

Conditional-Properties

Man kann keine Property als bedingte Property deklarieren, bei einer Auto-Property geht es jedoch, denn was diese tatsächlich tut, ist eine verborgene Variable zu definieren, die als Conditional-Variable erzeugt wurde. Das ist der Grund, weshalb man entstellte Auto-Property-Namen bemerkt, wenn man eine Papyrus-Variable in einem Bedingungssystem wählt – man wählt aus einer Liste von verborgenen Variablen.

Beispiel:

<papyrusscript> int property myVar auto conditional </papyrusscript>

Mehr Information über das Conditiona-Schlüsselwort befindet sich in der Papyrus-Einführung

Properties von einem |Quest-Script bekommen

von einem Ergebnis-Script der selben Quest

Oft benötigt man eine Property eines |Quest-Script und will es in einem Ergebnis-Script oder sonst irgendwo benutzen. Dies ist eines der etwas trickreicheren Dinge, aber wenn man erst einmal verstanden hat, was passiert, gibt es Sinn. Schaue als erstes auf das Beispiel, dann wollen wir beschreiben, was passiert.

<papyrusscript>

;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

</papyrusscript>

Was hier passiert, ist dass wir eine Property „deadCount“ im Script "MQ01Script" haben, welches der Quest MQ01 zugeordnet ist. Wir haben ebenfalls ein Script, das zur Quest MQ01 „gehört“ (das könnte ein Dialog-Ergebnis sein, ein Package-Ergebnis oder ein Script, welches mit einem Alias verbunden ist).

In dem Ergebnis-Script erzeugen wir eine Variable, die das |Quest-Script repräsentiert, welches die Property besitzt, die wir wollen (in diesem Fall die Property "DeadCount" des MQ01Scripts). Beachte, dass unsere Variable myQuest als MQ01Script deklariert ist. Dies ist deswegen, weil wir mit unserem |Quest-Script "scriptName MQ01Script extends Quest" tatsächlich einen neuen Objecttyp erzeugt haben… ein MQ01Script-Object. GetOwningQuest gibt ein QuestObject zurück (wenn wir es nicht erweitern). Deshalb müssen wir die von GetOwningQuest zurück gegebene Quest als neues Object mit „myQuest = GetOwningQuest() as MQ01Script" casten (d.h. eine Typumwandlung erzwingen), damit wir Zugriff auf angebotenen Properties haben. Wenn wir es nicht als MQ01Script casten, würde es nur die Funktionen und Properties eines Questobjects haben, welches dann nicht unsere deadCount-Property hätte.

Mit anderen Worten, solange wir das von GetOwningQuest zurückgegebene Object nicht als unser neues Script casten, haben wir unser neuen in dem neuen Script deklarierten Properties nicht zur Verfügung.

Mit einem kmyQuest

Wenn das Fragment, dass du benutzt, in einem Dropdown-Control ein "kmyquest" anzeigt, kannst du ein Script auswählen, das der Quest zugefügt ist, der das Fragment gehört. Und dann die „Magische Variable“ kmyquest nutzen, um auf das |Quest-Script zugreifen zu können, ohne es zu casten.

Das obige wird damit zu Folgendem vereinfacht: <papyrusscript>

float myDeadCount
myDeadCount = kmyQuest.deadCount ;getting property
kmyQuest.deadCount = 5 ;setting property

</papyrusscript>

Von einem nicht zugeordneten Fragment oder einem anderem Quest-Script

Was zu schreiben ist… das Wesentliche: man muss eine Property in seinem Script definieren (und im Editor-Interface als eine andere Quest festlegen, auf dessen Properties du zugreifen willst). Dann kannst du auf diese Properties zugreifen. Mit anderen Worten, hat dein Script eine Property einer anderen Quest, kannst du auf dessen Properties zugreifen.

Warnung

Man muss vorsichtig sein mit den Variablen und Auto-Properties, auf die von anderen Scripts zugegriffen werden kann – besonders wenn einige Scripts irgendwo anders eine Property haben, die auf ein Base-Script verweist, oder versuchen, das Base-Script zu casten. Damit wäre es möglich, zwei Kopien eines Scripts zu haben, auf die vom selben Object zugegriffen wird, wodurch eine andere Kopie der Variablen oder Auto-Property erzeugt wird.

Dies ist doppelt richtig bei Scripts mit zum Spiel gehörenden Funktionen ((native Functions), weil das Spiel z.B. diese an Ingame-Objekte zu jeder Zeit wo es gebraucht wird, anfügen kann. Dadurch wird eine andere Kopie der Variable oder Auto-Property erzeugt.

Anmerkungen

Die Liste der Properties im Properties Dialog wird nur nach dem Einfügen einer neuen Property oder nach dem Übersetzen des Scripts mit dem Build-In-Editor aktualisiert.

Siehe auch