Skriptthread zum Creation Kit

So, ich wage mich dann mal an das (versuchte) Verstehen der Skriptsprache heran :) Aller Anfang ist der Anfangsskript...in der Skyrim.esm von SureAI ist der Gott sei Dank schon sehr reduziert.
Jetzt suche ich nach jemandem, der mir diesen Skript möglichst genau erklären kann...Ich versuche mal ihn selbst zu interpretieren, aber da stoße ich sehr schnell an meine Grenzen :)

;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment;NEXT FRAGMENT INDEX 332 --- Nach einen Strichpunkt ist alles ein Kommentar, oder?
Scriptname QF_MQ101_0003372B Extends Quest Hidden --- Der Skriptname, klar... Außerdem wird eine Quest namens "Hidden" "Extended", was genau bedeutet das?

;BEGIN ALIAS PROPERTY StartMarkerRef --- Kommentar
;ALIAS PROPERTY TYPE ReferenceAlias --- Kommentar
ReferenceAlias Property Alias_StartMarkerRef Auto --- ReferenceAlias klingt nach etwas wie einer Verknüpfung... Aber was sind Properties?
;END ALIAS PROPERTY --- Mal wieder Kommentar

;BEGIN ALIAS PROPERTY Player --- Auch ein Kommentar, oder?
;ALIAS PROPERTY TYPE ReferenceAlias --- Oder haben diese Kommentare noch eine andere Funktion?
ReferenceAlias Property Alias_Player Auto --- Hier wird wieder eine Verknüpfung erstellt... aber was bedeutet eigentlich das Auto?
;END ALIAS PROPERTY --- Kommentar...

;BEGIN FRAGMENT Fragment_2 --- Hoffentlich immer noch Kommentar
Function Fragment_2() --- Wird hier eine Funktion erstellt? Wenn ja, müsste die nicht auch irgendwo aufgerufen werden, um wirksam zu werden?
;BEGIN CODE --- ...
Game.GetPlayer().moveto(Alias_StartMarkerRef.GetRef()) --- Der Spieler wird zu dem Marker Teleportiert, der vorher verknüpft wurde?
Game.FadeOutGame(false, true, 2.0, 1.0) ; Fade in after the mainmenu --- ???
;END CODE --- Und nochmal Kommentar
EndFunction --- Das Ende der Funktion
;END FRAGMENT --- Der Vorletzte...

;END FRAGMENT CODE - Do not edit anything between this and the begin comment --- ...und letzte Kommentar.

Ich musste das ganze Leider als Zitat formatieren, da ansonsten die Fette Schreibweise nicht angezeigt wurde.
Hoffentlich kann sich jemand die Mühe machen, mir den Skript zu erklären, ich will schließlich wissen, was ich da einbaue. Mir ist klar, dass es wohl noch schwer zu verstehen für mich ist, ich sehe mir ja parallel auch andere Webseiten zu Papyrus durch, aber nur an Aufgaben kann man wachsen ;)
Danke schonmal!
 
Hi, Mal ein paar Antworten in Kurzform auf deine Fragen. Du musst aber trotzdem die Dokumentation von Papyrus (creationkit.com) durchgehen:

1. 'Extends' bedeudet, dass dein Script von einem anderen abgeleitet wurde. Dein script 'erbt' alle Eigenschaften (funktionen...).
Beispiel: QF_MQ101_0003372B ist in deinem Fall also eine 'Quest' und hat Zugriff auf alle Funktionen... von Quest

2. Alles nach einem Semikolon ist ein Kommentar und wird nicht ausgewertet (es gibt ein paar ausnahmen z.B. in einer Zeichenkette...)

3. Property: Ein Property ist ein Objekt oder eine Variable bzw. eine Sammlung von Objekten/Variablen (Array), die dem Script übergeben wird, so dass man dieses im Script verarbeiten kann. 'Auto' heißt, dass bestimmte Funktionen automatisch erstellt werden. In der Regel wird 'Auto' immer benutzt.
Ein 'Quest Property MeineQuest Auto' ist also eine Quest namens MeineQuest. (Diese Quest muss im CR dem Property des Scripts zugewiesen werden)

4. "Function Fragment_2()" Ist eine Funktion. Wenn diese aufgerufen wird, wird der Code bis zum dazu gehörenden 'EndFunction'-Tag ausgeführt. Du hast recht, die Funktion muss auch irgendwo aufgerufen werden, damit diese etwas macht.

5. Zu den verschachtelten Funktionen innerhalb Fragment_2():
hier schaust du dir am besten die entsprechenden Funktinen in der Doku an (also Game.GetPlayer() und Actor.MoveTo() usw...)


Gruß, AZ
 
  • Like
Reaktionen: Dacri
Super, das hat mir schonmal weitergeholfen! Dass ich deswegen noch nicht Skripten kann war mir von vornherein klar, ich wollte nur die Funktion dieses spielstartenden Skripts verstehen, bevor ich mich an weiteres mache! Dankeschön :)
 
Du solltest diese Fragmente allerdings niemals von Hand bearbeiten. Diese Fragment-Codes sind eine Sammlung von Script-Befehlen, die in den Stages einer Quest gesetzt werden. Für Anderungen musst du das direkt dort machen, während dieses Fragment automatisch nachgeführt wird.
Meist hat aber eine Quest noch ein weiteres Script, das z.B. QuestXScript heisst und sich neben dem Fragment-Schnipsel befindet und das kannst du mit Edit Source bearbabeiten.

Dafür habe ich selbst ein Problem und zwar habe ich einen Ring des Käfers, der beim Anziehen Debug-Ausgaben macht.
In dem Moment wollte ich eine Variable aus einer Global ausgeben, die relevanten Bereiche:

GlobalVariable Property DRWPrimaryNeedsStateHunger Auto
AddDebugInfoInt("Hunger Status", (DRWPrimaryNeedsStateHunger.GetValue() as Int))

Dazu ein Auszug aus meinem Papyrus-Log, wo ich zusätzliche Trace-Ausgaben aus einem anderen Script auf die selbe Global mache:
[12/12/2012 - 08:21:37PM] DRW: Type: Hunger , Value: 95.000000 , Level: 4
[12/12/2012 - 08:22:06PM] error: Cannot call GetValue() on a None object, aborting function call

In der ersten Zeile sieht man, dass die Global existiert und einen Wert hat. Das ist die Trace-Ausgabe aus dem anderen Script.
In der Zeile gleich danach wird über das Käfer-Script reklamiert. Die Global ist aber normal deklariert und mit Auto-Fill abgefüllt.
Es erscheint mir eher wie ein Bug, aber vielleicht sehe ich ja auch den Wald vor Bäumen nicht.

Edit
Das kann doch nur ein Bug mit dem Initialisieren der Property der Global sein. Die Syntax zum auslesen und schreiben von Werten von Globals sollte ja wirklich idiotensicher sein.

[12/13/2012 - 09:05:03AM] DRW: Type: Hunger , Value: 117.000000 , Level: 5 , GameTimeTick: 0.000000
[12/13/2012 - 09:05:03AM] error: Cannot call GetValue() on a None object, aborting function call

Der Wert von Value ist direkt eine GlobalVariable von mir, die funktioniert einwandfrei in dem Script. Jetzt musste ich aber noch neu im selben Script die TimeScale für GameTimeTick in meine Berechnungen einbeziehen und verdammt, das gibt 0 zurück, das ist, wie wenn es die TimeScale nicht gäbe, obwohl die einwandfrei unter Propertys gefüllt ist.
 
Zuletzt bearbeitet:
Ich hab zwar in einem anderen Post dannach gefragt und auch Antwort bekommen, jedoch komme ich nicht weiter.
Brauche ich ein Script, wenn ich möchte, das ein bestimmter Follower Lvl 20 erst mit Player Level 18 angeheuert werden kann?
Wenn ja, wie muss das aussehen und wie oder wo muss ich es einbinden.
Sorry, aber mein Gebiet ist Grafik und bei allem anderen bin ich ein Super Dau.

Danke
 
:):):):D:lol::cry:
danke liebe(r) Dacri, aber wie ich aber oben erwähnte, komme ich damit nicht weiter! Sorry, ich bin däääääämlich.
Ich hoffte auf eine Beschreibung, die ich auch verstehe!:oops:

Danke!
 
Ich habe mehrere kleine Fragen:
1. Wie kann ich festlegen, dass der Kurier einen bestimmten Brief nach Abschluss einer bestimmten Quest dem Spieler liefert?
2. Wie kann ich den Essential-Status von NPCs entfernen?
3. Wie kann ich bestimmte Dialogoptionen so einstellen, dass sie erst bei Abschluss einer anderen Quest angezeigt werden und eine Quest startet?
 
Zuletzt bearbeitet:
2. Vielleicht hilft dir SetEssential weiter...
3. Normalerweise sollte es einfach gehen, indem du bei den Conditions der Dialoge die QuestStage der ersten Quest abfragst... Zum starten der zweiten Quest müsstest du dann im Result Script Fenster SetQuestStage verwenden...Zumindest wars so in Oblivion :D
 
Zu den noch offenen Fragen
1. Wie kann ich festlegen, dass der Kurier einen bestimmten Brief nach Abschluss einer bestimmten Quest dem Spieler liefert?
3. Wie kann ich bestimmte Dialogoptionen so einstellen, dass sie erst bei Abschluss einer anderen Quest angezeigt werden und eine Quest startet?

würde ich gerne noch wissen,
4. wie ich es hinbekomme, dass man, wenn man eine Tür aktiviert und durch diese teleportiert wird oben links eine Meldung erhält.
Ich will, dass man die Tür zwar aktivieren kann, aber eine Meldung angezeigt bekommt a la "Ihr dürft dieses Haus nicht betreten".
5. Gibt es eine Möglichkeit, herauszubekommen, was der Spieler gerade als Waffenart ausgerüstet UND gezogen hat?
(Bogen, Einhandwaffe, Zweihandwaffe, Schild, Zauber)?
6. Kann man den Spieler dazu zwingen, die ausgerüstete Waffe zu behalten, solange er sie gezogen hat?
 
Zuletzt bearbeitet:
Zu 1:
Es dürfte schwierig werden 100% ob der Kurier jetzt kommt oder nicht, da der Kurier meines Wissens nach eine World Interaction ist (WI). Bedeutet es Stehen eine menge Conditions zwischen dem erscheinen oder nicht erscheinen des Kuriers (ich glaube sogar eine GetRandomPercent Condition). Jedoch ist er spawned er meistens wenn man eine Hauptstadt betritt.
Falls du der Englischen Sprache mächtig bist: Hier ist ein Geniales Tutorial über den Kurier!

Zu 3:
Das funktioniert mit der GetStage Condition. Setze die Condition auf die Stage die das beenden der Quest initializiert.

Zu 4:
Wenn das nur bei einer bestimmten tür geschehen soll, würde ich dir einen Script mit dem Event Onactivation empfehlen. Hier ist ein beispiel script:
Code:
ScriptName MyScript Extends ObjectReference

Message Property MyMessage Auto

Event OnActivate(ObjectReference akActionRef)
    
    if akActionRef == game.GetPlayer()
        
        MyMessage.Show() ;zum testen kannst du debug.Notification("MEIN TEXT") verwenden
    
    EndIf

EndEvent

Zu 5:

Ja da gibt es mehrere möglichkeiten dies heraus zu finden. Es gibt die Function(für Script) .GetEquippedItemType() und das gleiche als Condition(für quest z.B) Hier die CK wiki Seite

Zu 6:
Wie meinst du das jetzt? Das man die Waffe nicht wegschmeißen kann solange sie gezogen ist oder wie?
 
  • Like
Reaktionen: FreshTheFallen
Wie meinst du das jetzt? Das man die Waffe nicht wegschmeißen kann solange sie gezogen ist oder wie?
Nein, dass man sie nicht wechseln kann solange sie gezogen ist.
Ich würde vorher gerne abfragen, was denn jetzt gerade ausgerüstet ist z.b. mit if-Abfragen,
und davon abhängig dann eben das Wechseln während die Waffe/der Zauber gezogen ist, enablen oder disablen.
 
Achso, hab den unterschied zwischen einer gezogenen Waffe und einer ausgerüsteten erst nicht erkannt^^.
Ich bin mir nicht sicher ob das machbar ist. Ich weis nicht genau wie das Spiel das "switchen" zwischen waffen/spells durch hotkeys vollzieht.
Wenn das nur auf bestimmte Waffen bezogen sein soll (ObjektReferences) sollte es machbar sein, aber wenn jede waffe und jeder Spell dafür in frage kommt, denke ich nicht das das machbar/außerst schwer machbar ist.
 
Zu den noch offenen Fragen
5. Gibt es eine Möglichkeit, herauszubekommen, was der Spieler gerade als Waffenart ausgerüstet UND gezogen hat?
(Bogen, Einhandwaffe, Zweihandwaffe, Schild, Zauber)?
?
Vielleicht kannst du daraus was basteln. Ist aus meinem Karren Script. Legt die Waffe ab und zieht sie wieder an.

Properties:
Form Property PlayerRightHandItem Auto --> CommandingActorPersistenceForm(00000294)
int property playerRightHandItemType Auto


Function HandleRightHandByAttachCar()
PlayerRightHandItemType = player.GetEquippedItemType(0)
If PlayerRightHandItemType == 10 ; shield
PlayerRightHandItem = player.GetEquippedShield()
player.UnequipItem(PlayerRightHandItem, false, true)
Else
PlayerRightHandItem = player.GetEquippedWeapon(0)
player.UnequipItem(PlayerRightHandItem, false, true)
Endif
endFunction


Function HandleRightHandByDeAttachCar()
player.EquipItem(PlayerRightHandItem, false, true)
endFunction

Hier noch die Values von GetEquippedItemType:

0: Nothing
1: One-handed sword
2: One-handed dagger
3: One-handed axe
4: One-handed mace
5: Two-handed sword
6: Two-handed axe/mace
7: Bow
8: Staff
9: Magic spell
10: Shield
11: Torch
12: Crossbow
 
Hi, ich möchte bei einem OnHit-Event prüfen, wieviel Schaden der Treffer am Ziel verursacht( bzw. wieviel Leben abgezogen wird).
So weit ich weiß gibt es dazu keine Funktion.
Dachte daran irgendwie abzufragen, wieviel life der NPC/Player vor und nach dem Hit hat und die Differenz sollte dann der Schaden sein. Aber wie mache ich das?

Und generell zum OnHit-Event: Wird der Code ausgführt bevor oder nachdem dem Opfer das Leben abgezogen wird?
 
@azraelb
Ich weis leider auch nicht, wann der code ausgeführt wird, ich vermute mal nachdem das leben abgezogen worde... da es in skyrim keine funktion gibt, welche die max Leben als int wiedergibt, könnte das tricky werden.

Edit: nach ein bisschen rumtesten scheint es so, das GetBaseActorValue() doch die max health wiedergibt. (zumindestens für npc's denke das funktioniert nicht beim Spieler)
Also könnte man folgendes verwenden:
Code:
Actor Property MyActor Auto

Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, \
  bool abBashAttack, bool abHitBlocked)
  
Float maxHealth 
Float CurrentHealth
Float Damage
If (MyActor as ObjectReference) == self
    maxHealth = MyActor.GetBaseActorValue("Health")
    currentHealth = MyActor.GEtActorValue("Health")
    Damage = MaxHealt - CurrentHealt
endif

    if akAggressor == Game.GetPlayer()
        debug.messagebox("MyActor maxHealt="+maxHealth+ "MyActor currentHealth="+MyActor.GetActorValue("Health")+ "")
        debug.messagebox("du hast" +Damage+ "Schaden verursacht")
    EndIf
EndEvent
Allerdings wird der gesammte von gemachte schaden bei der 2ten messagebox angegeben, vllt kannst du aber was draus machen^^
 
  • Like
Reaktionen: azraelb
@azraelb
Ich weis leider auch nicht, wann der code ausgeführt wird, ich vermute mal nachdem das leben abgezogen worde... da es in skyrim keine funktion gibt, welche die max Leben als int wiedergibt, könnte das tricky werden.

Edit: nach ein bisschen rumtesten scheint es so, das GetBaseActorValue() doch die max health wiedergibt. (zumindestens für npc's denke das funktioniert nicht beim Spieler)
Also könnte man folgendes verwenden:

Allerdings wird der gesammte von gemachte schaden bei der 2ten messagebox angegeben, vllt kannst du aber was draus machen^^

Erstmal danke für die Infos, aber ich habe noch ein paar Fragen:

1. Bist du dir wirklich sicher, dass GetBaseActorValue() das max. Leben incl. der Modifier (z.B. +20 Leben auf der Rüstung) liefert?
Ich habe die Doku http://www.creationkit.com/Actor_Value nämlich anders verstanden...

2. Wenn ich irgendwie an die Modifier (siehe Link von 1. ) kommen würde wäre das ganz gut^^ wenn man wirklich nicht an die Basis-werte und die einzelnen Modifikatoren kommt (hmm evtl. kann man irgendwie abfragen, welche effekte grad aktiv sind? im Menü kann man das ja auch sehen), dann ist mir schleierhaft, für was diese ganzen Actor Value Funktionen überhaupt gut sind...

3. Denke nicht, dass mir das was bringt (selbst wenn ich wirklich den max.Health Wert incl. Modifikatoren bekomme), denn das o.g. scrpt gibt mir ja nur beim 1. Schlag den korrekten Wert wieder (und auch nur, wenn das Opfer volles Health hatte). jeder weitere Treffer würde ja dann den Gesamtschaden ausgeben.
-> Ich brauche aber wirklich genau den Schaden des einen treffers, werde also wahrscheinlich nicht drum herum kommen das aktuelle health vor und nach dem Schlag abzufragen


Hintergrund ist: Ich erstelle für meine Mod "Dark Side of Skyrim" neue (gescriptete) unique items. Eines der uniques soll ein Mana-Shield gewähren das (zumindest) einen Teil des dmg vom Mana abzieht und nicht vom Leben.

Edit:
Ich glaube langsam, dass ich mit Scripting hier nicht zum Ziel komme, allerdings habe ich evtl. bei Perks etwas gefunden. Kann sein, dass man das Problem mit einem hidden Perk lösen kann, welcher Schaden/Leben/Mana ändert. Muss mich aber mit Perks erst noch ein wenig auseinander setzen...
 
Zuletzt bearbeitet:
Ja, ich habe wieder eine Frage ;)

Kann man mit einem Scriptbefehl mit sofortiger Wirkung die Karte disablen, sodass sie nicht mehr verwendet werden kann, eine Nachricht oben links anzeigen, und dann wieder durch Aktivieren einer Triggerbox (wahrscheinlich mit einer RefID)
die Karte wieder aktivieren und die Nachricht nicht länger anzeigen?
Ich hatte zwar schon grobe Planungen mit If und elseif, aber ich weiß nciht, wie ich die Karte disable/enable.
 
Dies wird erst mit einer entsprechenden SKSE funktion möglich. Aller dings gibt es bereits einen "workaround" für das problem. Benötigt jedoch auch SKSE hier ist ein script dafür:
Code:
[COLOR=#000000][FONT=monospace]Event OnInit()[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]RegisterForMenu("[/FONT][/COLOR]MapMenu[COLOR=#000000][FONT=monospace]")[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]EndEvent[/FONT][/COLOR]


[COLOR=#000000][FONT=monospace]Event OnMenuOpen(string MenuName) [/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]if MenuName == "[/FONT][/COLOR]MapMenu[COLOR=#000000][FONT=monospace]"[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]ForceCloseMenu()[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]Debug.Notification("Menu exited")[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]endif[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]EndEvent[/FONT][/COLOR]

[COLOR=#000000][FONT=monospace]Function ForceCloseMenu()[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]DisablePlayerControls()[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]EnablePlayerControls()[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]While Utility.IsInMenuMode()[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]Input.TapKey(Input.GetMappedKey("Tween Menu"))[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]EndWhile[/FONT][/COLOR]
[COLOR=#000000][FONT=monospace]EndFunction[/FONT][/COLOR]

Ich denke die while loop wird nicht benötigt, habs sie aber sicherheits halber trotzdem hinzugefügt.
 
Hallo Leute!
Ich suche ein Skript für an ein Gespräch, das überprüft ob ich von einem Misc objekt (Einer Münze) genügend als 5 und mehr Einheiten im Inventar hab, und nur dann die möglichkeit gibt ein neues passendes topic auszuwählen

Hoffe ihr könnt mir helfen
Grüze
LindayWolf