PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Papyrus - Globale Variablen?



walli
14.02.2012, 15:46
Hi, ich versuche schon den halben Tag mit Papyrus warm zu werden und hab echt Probleme mit diesem objektbezogenen Scripts,
die spärlichen Tutorials und engl. Erklärungen sind harter Stoff für einen Hobbyscripter wie mich.
Sicher hat man mit Papyrus wesentlich mehr Möglichkeiten und kann wenn das Scriptgerüst steht mit wenigen Zeilen das machen wofür man bei Fallout/Oblivion seitenweise Code bräuchte, nur hab ich mir den Einstieg leichter vorgestellt.

Momentan versuche ich in einem ObjectReference Script den Wert für eine Globale Variable (genauer gesagt GameDaysPassed) zu erhalten.
Ist das überhaupt möglich oder muss dafür ein "GlobalVariable Script" herhalten?

Ich raffs nicht, eigentlich müsste man doch von überall auf Globals zugreifen können, irgendjemand eine Idee wo ich ansetzen muss? Bei Fallout wäre das ne Sache von 2 Minuten gewesen, hier häng ich schon 6 Stunden drann:(

Boïndil
14.02.2012, 16:33
Hier nur mal, wie ich DayOfTime aufrufe:

GlobalVariable Property TimeOfDayGlobal Auto;

Function XX ()
float timeOfDay = TimeOfDayGlobal.GetValue()
EndFunction

Den Code kannst du angepasst ins Script kopieren. Anschliessend gehst du mit der rechten Maustaste auf das Script im Dialog-Fenster und rufst Properties auf.
Das CK bietet dir dann eine Reihe von Globals an.

Edit:
Von mir aus ist eigentlich die Bezeichnung GlobalVariable-"Script" falsch, es ist eine Klasse in einer objektorientierten Sprache, die Methoden(=Funktionen) und Propertys zur Verfüng stellt. Das ist ein wenig irreführend, weil man vielleicht meint, man müsse ein Script erstellen, das von GlobalVariable ableitet, aber der obige Block kann in jedem Script-Typ stehen, in einer Quest, genau so wie in einem Buch.

Vielleicht interessierts dich, mal in zwei meiner Scripte zu sehen, die verschiedene Elemente und deren Gebrauch zeigt. Ich persönlich lerne am besten durch Beispiele und die CK-Seite ist dafür völlig untauglich.

Scriptname DRWEffectsQuestGoreScript extends Quest
-Quest ruft beim Start ein Menu mit Nein/Ja auf
-Quest hat ein RegisterForUpdate/Event OnUpdate() (Nachfolger von GameMode)



Actor Property Player Auto
Message Property DRWEffectsMsgGoreInit Auto
GlobalVariable Property TimeOfDayGlobal Auto

int goreEnabled = 0 ; Gore aktiv
int goreType = 0 ; Gore-Typ
float goreTreshold = 0.4 ; Schwelle der Einblndung(0.3 -0.4)

int askOnce = 0 ; Box ein Mal(wegen Threading?)
int goreStatus = 0 ; 0 Nicht gestartet, 1: Starten, 2: Gestartet
int goreLevel = 0 ; Speichert den letzten Gore-Level
int goreLevels = 5 ; Anzahl Filter
int playerState = 0 ; Speichert den letzten Status des Players

ImageSpaceModifier[] Property DRWFxGore0 Auto
ImageSpaceModifier[] Property DRWFxGore1 Auto
ImageSpaceModifier[] Property DRWFxGore2 Auto
ImageSpaceModifier[] Property DRWFxGore3 Auto
ImageSpaceModifier[] Property DRWFxGore4 Auto
ImageSpaceModifier Property DRWFxGoreDefault Auto

; Start-Abfrage
Function AskForGore ()
if (askOnce == 0)
askOnce = 1
int selected = DRWEffectsMsgGoreInit.Show()
If (selected == 1) ; Yes
EnableGore()
Else
; Return
EndIf
EndIf
EndFunction

; Gore-Modus aktivieren
Function EnableGore()
goreEnabled = 1
goreStatus = 0
playerState = 0
RegisterForUpdate(1)
EndFunction

; Gore-Modus deaktivieren
Function DisableGore()
UnregisterForUpdate()
Utility.Wait(3)
clearFX(getGoreType())
goreEnabled = 0
goreStatus = 0
playerState = 0
EndFunction

; Gore-Typ setzen
Function SetGoreType (int newType)
newType = fixRange(newType, goreLevels)
If (newType != goreType)
If (goreEnabled == 1)
DisableGore()
Utility.Wait(3)
EndIf
goreType = newType
EnableGore()
EndIf
EndFunction

; --- Helper-Functions -----------------------------------------------------
; Gore anwenden
; FX: 0 1 2 3 4 5 6 7
; FadeOut FadeIn
Function applyGore(ImageSpaceModifier[] objects)
int pState = getPlayerState()
if (pState != playerState)
int gLevel = 0
If (pState != 0)
gLevel = pState + getAmbientType()
EndIf
If (goreStatus == 0)
goreStatus = 1
DRWFxGoreDefault.Apply()
ElseIf (goreStatus == 1)
goreStatus = 2
DRWFxGoreDefault.PopTo(objects[gLevel])
Else
objects[goreLevel].PopTo(objects[gLevel])
EndIf
goreLevel = gLevel
playerState = pState
EndIf
EndFunction

; Player-Status berechnen
; Gore-Level: 0 = gesund, 1 = angeschlagen, 2 = leicht verletzt, 3 = stark verletzt
int Function getPlayerState()
int pState = 0
float pHealth = Game.GetPlayer().GetAVPercentage("Health")
float hPerc = goreTreshold/3
If (pHealth < hPerc)
pState = 3
ElseIf (pHealth >= hPerc && pHealth < hPerc * 2)
pState = 2
ElseIf (pHealth >= hPerc * 2 && pHealth < goreTreshold)
pState = 1
EndIf
Debug.Notification("pState:" + pState+ " pHealth:" + pHealth)
return pState
EndFunction

; Aktuelles Gore-Objekt ermitteln
ImagespaceModifier [] Function getGoreType()
If (goreType == 1)
return DRWFxGore1
ElseIf (goreType == 2)
return DRWFxGore2
ElseIf (goreType == 3)
return DRWFxGore3
ElseIf (goreType == 4)
return DRWFxGore4
EndIf
return DRWFxGore0
EndFunction

; Player-Umgebung
int Function getAmbientType()
int ambientType = 0
If (Player.IsInInterior()) ; Interior
ambientType = 3
Else
int timeOfDay = TimeOfDayGlobal.GetValueInt()
ambientType = 1 ; Tag-Nacht-Schwelle
If (timeOfDay < 4 || timeOfDay > 22) ; Nacht
ambientType = 2
ElseIf (timeOfDay > 7 || timeOfDay < 19) ; Tag
ambientType = 0
EndIf
EndIf
return ambientType
EndFunction

; Deaktiviert alle Effekte eines Bereichs
Function clearFX(ImageSpaceModifier[] objects)
int c = 0
while (c < objects.Length)
objects[c].Remove()
c += 1
endwhile
EndFunction

; Begrenzt Input fuer Gore-Einstellung
int Function fixRange(int indexNumber, int maxRange)
if (indexNumber < 0)
return 0
elseif (indexNumber > maxRange)
return maxRange
endif
return indexNumber
EndFunction

; --- Quest Events -----------------------------------------------------
Event OnInit ()
Utility.Wait(20)
AskForGore()
EndEvent

Event OnUpdate()
applyGore(getGoreType())
EndEvent


Scriptname DRWEffectsControllerScript extEnds ObjectReference
-Script startet beim Öffnen eines Buchs
-Script hat ein verschachteltes Menu
-rekursiver Aufruf von Menu-Funktionen
-Aufruf von Quest-Variablen

; Properties
Book Property MySelf Auto
Message Property DRWEffectsMsgMain Auto
Message Property DRWEffectsMsgSaturation Auto
Message Property DRWEffectsMsgBrightness Auto
Message Property DRWEffectsMsgContrast Auto
Message Property DRWEffectsMsgColors Auto
Message Property DRWEffectsMsgDof Auto
Message Property DRWEffectsMsgBloom Auto
Message Property DRWEffectsMsgGore Auto
Message Property DRWEffectsMsgTools Auto
DRWEffectsQuestScript Property EffectQuest Auto
DRWEffectsQuestGoreScript Property EffectGoreQuest Auto

; Menu Main
Function MenuMain()
int selected = DRWEffectsMsgMain.Show(EffectQuest.EffectsEnabled)
If(selected == 0)
; Return
ElseIf (selected == 1)
MenuSaturation()
ElseIf (selected == 2)
MenuBrightness()
ElseIf (selected == 3)
MenuContrast()
ElseIf (selected == 4)
MenuColors()
ElseIf (selected == 5)
MenuDof()
ElseIf (selected == 6)
MenuBloom()
ElseIf (selected == 7) ; To Do
; MenuGore()
MenuMain()
ElseIf (selected == 8)
MenuTools()
Else
; Return
EndIf
EndFunction

; Menu Saettigung
Function MenuSaturation()
int effectId = 0
int selected = DRWEffectsMsgSaturation.Show(EffectQuest.EffectSet ting(effectId) + 1)
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekt verringern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuSaturation()
ElseIf (selected == 2); Effekt vergroessern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuSaturation()
Else
MenuMain()
EndIf
EndFunction

; Menu Helligkeit
Function MenuBrightness()
int effectId = 1
int selected = DRWEffectsMsgBrightness.Show(EffectQuest.EffectSet ting(effectId) + 1)
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekt verringern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuBrightness()
ElseIf (selected == 2); Effekt vergroessern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuBrightness()
Else
MenuMain()
EndIf
EndFunction

; Menu Kontrast
Function MenuContrast()
int effectId = 2
int selected = DRWEffectsMsgContrast.Show(EffectQuest.EffectSetti ng(effectId) + 1)
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekt verringern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuContrast()
ElseIf (selected == 2); Effekt vergroessern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuContrast()
Else
MenuMain()
EndIf
EndFunction

; Menu Farben
Function MenuColors()
int effectId = 3
int selected = DRWEffectsMsgColors.Show(EffectQuest.EffectSetting (effectId) + 1)
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekt verringern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuColors()
ElseIf (selected == 2); Effekt vergroessern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuColors()
Else
MenuMain()
EndIf
EndFunction

; Menu DoF
Function MenuDof()
int effectId = 4
int selected = DRWEffectsMsgDof.Show(EffectQuest.EffectSetting(ef fectId) + 1)
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekt verringern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuDof()
ElseIf (selected == 2); Effekt vergroessern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuDof()
Else
MenuMain()
EndIf
EndFunction

; Menu Bloom
Function MenuBloom()
int effectId = 5
int selected = DRWEffectsMsgBloom.Show(EffectQuest.EffectSetting( effectId) + 1)
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekt verringern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuBloom()
ElseIf (selected == 2); Effekt vergroessern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuBloom()
Else
MenuMain()
EndIf
EndFunction

; Menu Gore To do
Function MenuGore()
int selected = DRWEffectsMsgGore.Show(EffectGoreQuest.GetGoreEnab led)
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekt verringern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuGore()
ElseIf (selected == 2); Effekt vergroessern
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuGore()
ElseIf (selected == 3); Schwelle 35
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) - 1)
MenuGore()
ElseIf (selected == 4); Schwelle 45
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuGore()
ElseIf (selected == 5); Schwelle 55
EffectQuest.ApplyEffect(effectId, EffectQuest.EffectSetting(effectId) + 1)
MenuGore()
Else
MenuMain()
EndIf
EndFunction

; Menu Tools
Function MenuTools()
int selected = DRWEffectsMsgTools.Show(EffectQuest.EffectsEnabled )
If(selected == 0)
MenuMain()
ElseIf (selected == 1); Effekte aktivieren
EffectQuest.EnableEffects()
MenuTools()
ElseIf (selected == 2); Effekt deaktivieren
EffectQuest.DisableEffects()
MenuTools()
ElseIf (selected == 3); Preset speichern
EffectQuest.SavePreset()
MenuTools()
ElseIf (selected == 4); Preset anwenden
EffectQuest.ApplyPreset()
MenuTools()
ElseIf (selected == 5); Config anwenden
EffectQuest.ApplyConfig()
MenuTools()
Else
MenuMain()
EndIf
EndFunction

; Player aktiviert Buch im Inventar
Event OnEquipped(Actor reader)
If (reader != Game.GetPlayer())
return
EndIf
Utility.WaitMenuMode(2.0)
MenuMain()
EndEvent
; Player aktiviert Buch in der Welt
Event OnActivate(ObjectReference reader)
If (reader != Game.GetPlayer() || IsActivationBlocked())
return
EndIf
Utility.WaitMenuMode(2.0)
MenuMain()
EndEvent

walli
14.02.2012, 17:36
Danke Boïndil, auf eine Antwort von dir hab ich gehofft. Compilieren hat erstmal geklappt, kam nicht darauf GlobalVariable vorher zu definieren.
Sehe ich das jetzt richtig daß man mit Hilfe der eben selbsterstellten (und selbstbenannten) Funktion innerhalb von beliebigen Events des Scripts den Wert aufrufen kann? Ich hoffe es!

Und Gratulation zu deiner Mod, scheint gut anzukommen. Wenn man deine Scripte anguckt kann man neidisch werden.

Edit:
Noch ne Frage zu Properties, wenn ich eine ObjectReference definiere mit:

ObjectReference Property myself auto

Reicht das dann oder muss dann auch das Script mit Rechtsklick->Properties mit dem Object verknüpft werden wo das Script draufliegt?

Boïndil
14.02.2012, 18:14
Soviel ich weiss, müsste man bei bekannten Objekten die Variablen nicht auffüllen:
Book Property MySelf Auto
Book Property DRWEffectsBookController Auto (das Buch gibt es mit dem selben Namen)

Muss man aber austesten und alle Feinheiten sind mir noch nicht klar.
Das hier um Beispiel geht nicht:
Actor Property Player Auto

Aber wenn der Wert mal abgefüllt ist, kann man ihn jederzeit aufrufen.

Ich habe natürlich den Vorteil, dass ich ein wenig Übung mit JS und C# habe.

walli
15.02.2012, 17:28
Hänge immer noch an einem einfachen Script, Problem ist daß ich GetItemCount nicht auf einen Container aufgerufen bekomme.
Hab den Teil des Codes der nicht funzt mal separat in ein Script gepackt um rumzutesten aber bekomme immer wieder Fehlermeldungen.



Hier das "Script" wenn man es so nennen kann:

ScriptName wqEggCountScript Extends Container

Container Property wqTestContainerREF auto
Ingredient Property BirdEgg03 auto

int EggCount
int function GetItemCount(Form akItem) native

Event OnCellAttach()

EggCount = wqTestContainerREF.GetitemCount(BirdEgg03)

endEvent

"(11,31):GetItemCount is not a function or does not exist"
"(11,1):type mismatch while assigning to a int (cast missing or types unrelated)"

Der EventBlock läuft aber wie bekomme ich GetItemCount zum laufen, hab schon ewig mit Functions rumprobiert aber mir fehlen einfach paar Beispiele um das zu raffen, am schlimmsten ist daß "FindText" irgendwie die Scripte ignoriert wenn man sich bestimmte Sachen mal in anderen Scripten angucken will.

Danke schonmal.

Don Kan Onji
15.02.2012, 17:41
Ich packs mal hier mit rein, da sich das ähnelt ;)

Boïndil
15.02.2012, 19:49
Ich glaube, du denkst zuweit, das hier klappt hervorragend:


Book Property DRWEffectsBookController Auto
If (Game.GetPlayer().GetItemCount(DRWEffectsBookContr oller) == 0)
Game.GetPlayer().AddItem(DRWEffectsBookController)
EndIf

tommyd2
15.02.2012, 20:13
Hehe, den Scriptteil habe ich mir gestern schon aus deiner BSA extrahiert und geklaut :list3no: um meinen selbstgebastelten Ring mit Fackelbeleuchtung zum Charakter zu bekommen.
Deine Scripte eignen sich hervorragend dazu, wenn man selbst so gut wie ein Noob in solchen Dingen ist. (Schon aus dem Grund lade ich mir immer deine Mods herunter :cool:)

walli
15.02.2012, 20:19
Ja so hab ich das schon öfters gelesen, Unterschied ist nur das ich das ganze auf einen Container(der auch das Script hat) anwenden will wenn man die Zelle Betritt, und ich muss den genauen Wert auslesen. Aber GetItemCount wird einfach nicht akzeptiert :confused:

Zeck
15.02.2012, 20:44
Lass mal "int function GetItemCount(Form akItem) native" einfach weg und schau nach ob die Properties auch "gefüllt" sind.

Boïndil
16.02.2012, 06:50
Schon mal so versucht?
Container Property MySelf auto

Und du darfst die Variable gleich wie den Container benennen, denn dann erkennennt die Sprache, auf was es sich bezieht. Natürlich nie vergessen, die Porperty abzufüllen.
Container Property wqTestContainer auto

Und das mit native wird garantiert nicht benötigt.

walli
16.02.2012, 08:02
Also Properties sind alle gefüllt, Variable und Container tragen den gleichen Namen, die Fehlermeldung ist immer die gleiche egal ob ich die function-Zeile weglasse oder nicht.
"GetitemCount is not a function or does not exist".

Werde jetzt erstmal mit Hilfe des Skyrim Script Dumpers (http://skyrim.nexusmods.com/downloads/file.php?id=9790) paar Beispiele angucken, hoffentlich find ich mal eins was nicht auf den player läuft sondern auf einen Container.