[Tutorial] Papyrus Beispielskripte

E

Ehemaliger Benutzer

Gast
Ich denke, es wäre eine gute Idee verschiedene Beispielskripte für mehr oder weniger komplexe Aufgaben in einem Thread zu sammeln. Dass erspart dann womöglich einzelnen Moddern die Notwendigkeit das Rad für seine Zwecke neu erfinden zu müssen.

Nachdem ich eines meiner - einfacheren - Scripte ins CK Wiki rein gestellt habe (um zu sehen wie das mit der Wiki Software so funktioniert) mache ich hier den Anfang mit ein paar seit langem tadellos funktionierenden Beispielen.

Vielleicht hilft es ja jemandem weiter.

=================================
Hinweis:

Wenn ihr auf den Player zugreifen wollt, so vermeidet den unnötigen Einsatz der Funktion GetPlayer(). Eine Actor Property mit der Referenz PlayerRef arbeitet bis zu 1000 mal schneller.

z.B:



Actor Property PlayerRef Auto

PlayerRef.Additem(Objekt, Menge)




=================================

Ein einfaches Uhrzeitskript, dass über einen Magic Effekt aufgerufen werden kann.

Code:
ScriptName NNWUhrzeitScript Extends ActiveMagicEffect

Message Property NNWZeitAnzeigen Auto
GlobalVariable Property GameHour Auto

float Function ZeigeZeit() 

	Float Time = GameHour.GetValue()
	Int Std = Math.Floor(Time) ;Entfernt die Nachkommastelle der Float Variable um diese als Integer nutzen zu können
	Time = Time - Std
	Time = ((Time / 5)*3)
	Time = Time + Std
	Return Time
EndFunction

Event OnEffectStart(Actor akTarget,Actor akCaster)

NNWZeitAnzeigen.Show(ZeigeZeit())
EndEvent

Ein "Lichtquellen" Aktivator der automatisch die Innenbeleuchtung von Tag auf Nacht und umgekehrt umschalten kann.

Code:
Scriptname NNWTagesLichtSkript extends ObjectReference  

GlobalVariable Property GameHour Auto
GlobalVariable Property NNWweiter Auto
Int Property Intervall = 60 Auto
Keyword Property NNWTagesLichtQuelle Auto
Keyword Property NNWLampenReferenz Auto
ObjectReference Property TagesLicht Auto Hidden 
ObjectReference Property Lampe Auto Hidden

Event OnInit()
 	RegisterForSingleUpdate(10)
	TagesLicht = GetLinkedRef(NNWTagesLichtQuelle)
	Lampe = GetLinkedRef(NNWLampenReferenz)
	
EndEvent
 
Event OnUpdate()

Float Zeit = GameHour.GetValue()
Bool weiter = NNWweiter.GetValue()

If(Zeit > 19 || Zeit < 7)
		Disable()
		TagesLicht.Disable(True)
		Lampe.Enable(True)
		
Else
		EnableNoWait()
		TagesLicht.Enable()
		Lampe.Disable(True)
EndIf

If weiter
		RegisterForUpdate(Intervall)
Else
	UnregisterForUpdate()
EndIf
EndEvent

Ein einfaches Sortierskript. Ich habe dabei bewusst auf eine Formlist verzichtet, da man hiermit mehr Kontrolle über den Sortier Vorgang hat.

Code:
ScriptName NNWMaterialSortierSkript Extends ObjectReference

Import Utility

Keyword Property NNWErz Auto
Keyword Property NNWBarren Auto
Keyword Property NNWMaterial Auto
ObjectReference Property ErzKiste Auto Hidden
ObjectReference Property BarrenKiste Auto Hidden
ObjectReference Property MaterialKiste Auto Hidden
MiscObject[] Property MaterialListe Auto
Actor Property PlayerRef Auto

int Menge = 0

Function MaterialEinlagern()

ErzKiste = GetLinkedRef(NNWErz)
BarrenKiste = GetLinkedRef(NNWBarren)
MaterialKiste = GetLinkedRef(NNWMaterial)

Menge = PlayerRef.GetItemCount(MaterialListe[0])
if(Menge >0)
ErzKiste.Additem(MaterialListe[0], Menge)
PlayerRef.RemoveItem(MaterialListe[0], Menge)
endif

Menge = PlayerRef.GetItemCount(MaterialListe[1])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[1], Menge)
PlayerRef.RemoveItem(MaterialListe[1], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[2])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[2], Menge)
PlayerRef.RemoveItem(MaterialListe[2], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[3])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[3], Menge)
PlayerRef.RemoveItem(MaterialListe[3], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[4])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[4], Menge)
PlayerRef.RemoveItem(MaterialListe[4], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[5])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[5], Menge)
PlayerRef.RemoveItem(MaterialListe[5], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[6])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[6], Menge)
PlayerRef.RemoveItem(MaterialListe[6], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[7])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[7], Menge)
PlayerRef.RemoveItem(MaterialListe[7], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[8])
if(Menge > 0)
ErzKiste.Additem(MaterialListe[8], Menge)
PlayerRef.RemoveItem(MaterialListe[8], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[9])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[9], Menge)
PlayerRef.RemoveItem(MaterialListe[9], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[10])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[10], Menge)
PlayerRef.RemoveItem(MaterialListe[10], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[11])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[11], Menge)
PlayerRef.RemoveItem(MaterialListe[11], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[12])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[12], Menge)
PlayerRef.RemoveItem(MaterialListe[12], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[13])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[13], Menge)
PlayerRef.RemoveItem(MaterialListe[13], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[14])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[14], Menge)
PlayerRef.RemoveItem(MaterialListe[14], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[14])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[14], Menge)
PlayerRef.RemoveItem(MaterialListe[14], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[15])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[15], Menge)
PlayerRef.RemoveItem(MaterialListe[15], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[16])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[16], Menge)
PlayerRef.RemoveItem(MaterialListe[16], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[17])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[17], Menge)
PlayerRef.RemoveItem(MaterialListe[17], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[18])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[18], Menge)
PlayerRef.RemoveItem(MaterialListe[18], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[19])
if(Menge > 0)
BarrenKiste.Additem(MaterialListe[19], Menge)
PlayerRef.RemoveItem(MaterialListe[19], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[20])
if(Menge > 0)
MaterialKiste.Additem(MaterialListe[20], Menge)
PlayerRef.RemoveItem(MaterialListe[20], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[21])
if(Menge > 0)
MaterialKiste.Additem(MaterialListe[21], Menge)
PlayerRef.RemoveItem(MaterialListe[21], Menge)
EndIf

Menge = PlayerRef.GetItemCount(MaterialListe[22])
if(Menge > 0)
MaterialKiste.Additem(MaterialListe[22], Menge)
PlayerRef.RemoveItem(MaterialListe[22], Menge)
EndIf
EndFunction

Event OnActivate(ObjectReference akActionRef)
	MaterialEinlagern()
EndEvent

Ein Transportabler Beutel. Dafür ist es allerdings notwendig, den in Skyrim vorhandenen statischen Beutelmesh - Clutter\Container\Pouch01.nif in ein Misc Object hinein zu operieren.

Code:
ScriptName NNWBeutelSkript extends ObjectReference

ObjectReference Property NNWStatischeTruhe Auto
MiscObject Property NNWBeutel Auto
Sound Property KlapperKlapper Auto
Message Property NNWTascheNachricht Auto
ObjectReference Ich

Event OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer)
  If(akOldContainer && !akNewContainer)
  Ich = (Self as ObjectReference)
	Ich.BlockActivation()
  ElseIf(akNewContainer == NNWStatischeTruhe)
		NNWTascheNachricht.Show()
		Utility.Wait(1)
	NNWStatischeTruhe.RemoveItem(NNWBeutel, 1, False)
	Game.GetPlayer().AddItem(NNWBeutel, 1, True)
  endIf
endEvent

Event OnEquipped(Actor akActor)
	If(akActor == Game.GetPlayer())
		Utility.Wait(1)
 		KlapperKlapper.Play(Game.GetPlayer())
		NNWStatischeTruhe.Activate(Game.GetPlayer())
	endif
EndEvent

Event OnActivate(ObjectReference akActionRef)
	
	If(akActionRef == Game.GetPlayer())
	If(Game.GetPlayer().IsSneaking())
			KlapperKlapper.Play(Game.GetPlayer())
			NNWStatischeTruhe.Activate(Game.GetPlayer())
	Else
	Ich.Activate(akActionRef, True)
 	EndIf
	EndIf
EndEvent

Fragen / Anregungen / Verbesserungsvorschläge?
 
Zuletzt bearbeitet von einem Moderator:
Sehr gute idee! Ich denke damit kannst du vielen leuten weiter helfen^^. Nur ich hätte noch 2 Fragen:
1.Kann ich ein paar scripts in den thread hinzufügen, wenn mir gute beispiele einfallen?^^
2.Warum keinen While loop im Sortierscript?
 
1)Ja, aber dann sollte man den Threadtitel ändern.

2) Mehr Kontrolle über die einzelnen Objekte.
 
Nachdem ich heute eines meiner - einfacheren - Skripte ins CK Wiki rein gestellt habe (um zu sehen wie das mit der Wiki Software so funktioniert) habe ich mich dazu entschlossen dass ebenfalls hier zu posten.
Vielleicht hilft es ja jemandem weiter.
Solltet ihr Fragen dazu haben => Nur zu.

Ein einfaches Sortierskript. Ich habe dabei bewusst auf eine Formlist verzichtet, da man hiermit mehr Kontrolle über den Sortier Vorgang hat.

so würde das bei mir aussehen. Deine Logik ist dabei unverändert.

Code:
ScriptName NNWMaterialSortierSkript Extends ObjectReference


Import Utility
Keyword Property NNWErz Auto
Keyword Property NNWBarren Auto
Keyword Property NNWMaterial Auto
ObjectReference Property ErzKiste Auto Hidden
ObjectReference Property BarrenKiste Auto Hidden
ObjectReference Property MaterialKiste Auto Hidden
MiscObject[] Property MaterialListe Auto
int Menge
Actor Player

Event OnActivate(ObjectReference akActionRef)
         Player = Game.GetPlayer()
         ErzKiste = GetLinkedRef(NNWErz)
         BarrenKiste = GetLinkedRef(NNWBarren)
         MaterialKiste = GetLinkedRef(NNWMaterial)
         MaterialEinlagern(1)
         MaterialEinlagern(2)  ; hier wäre aber eine Schleife angebrach die durchzählt.. oder einfach das Array abspuhlt
         MaterialEinlagern(3)
         ;etc.
EndEvent

Function MaterialEinlagern(Int i)
   Menge = 0
    Menge = Player.GetItemCount(MaterialListe[i])
      if(Menge > 0)
        ErzKiste.Additem(MaterialListe[i], Menge)
        Player.RemoveItem(MaterialListe[i], Menge)
      EndIf
EndFunction


Edit:
So wärs noch schöner.. kanns aber jetzt natürlich ned testen

Code:
ScriptName NNWMaterialSortierSkript Extends ObjectReference
 
Import Utility
Keyword Property NNWErz Auto
Keyword Property NNWBarren Auto
Keyword Property NNWMaterial Auto
ObjectReference Property ErzKiste Auto Hidden
ObjectReference Property BarrenKiste Auto Hidden
ObjectReference Property MaterialKiste Auto Hidden
MiscObject[] Property MaterialListe Auto
int Menge
Int i
Actor Player

 
Event OnActivate(ObjectReference akActionRef)
         Player = Game.GetPlayer()
         ErzKiste = GetLinkedRef(NNWErz)
         BarrenKiste = GetLinkedRef(NNWBarren)
         MaterialKiste = GetLinkedRef(NNWMaterial)
         i = 1
         while (i <= MaterialListe[MaterialListe.Length - 1])
           Menge = 0
           Menge = Player.GetItemCount(MaterialListe[i])
            if(Menge > 0)
              ErzKiste.Additem(MaterialListe[i], Menge)
                 Player.RemoveItem(MaterialListe[i], Menge)
              EndIf
            i += 1
         endWhile
EndEventv
 
Zuletzt bearbeitet:
Die Definition der Actor Referenz ist m.E überflüssig da man mit Game.GetPlayer() diesen sowieso an der Angel hat und das andere nur nutzloses Zuweisungs geschubse darstellt.

Eigentlich ist meine Variante mit der ausgelagerten Funktion ebenfalls schon zuviel des guten, da man den ganzen Kram auch direkt im OnActivate Event platzieren kann.

Code:
Event OnActivate(ObjectReference akActionRef)
Menge = 0
    Menge = Game.GetPlayer().GetItemCount(MaterialListe[0])
      if(Menge > 0)
        ErzKiste.Additem(MaterialListe[0], Menge)
        Game.GetPlayer().RemoveItem(MaterialListe[0], Menge)
      EndIf	
EndEvent

Einen Whileloop habe ich auch schon getestet. Es landet dann alles in der selben Kiste. Wenn man die Erze von den Barren und das Holz + die Federn von ersteren beiden trennen möchte benötigt man jeweils 1 gesonderten Loop für den jeweiligen Kistentyp, es sei denn man verwendet ebenfalls ein Array für die Kisten. Das bindet dann allerdings den Aktivator an dieses Array und die Verwendung der Keywords fällt dann flach.
Bei den Ingredienzien läuft das dann komplett aus dem Ruder, weil diese mit ihrer EV Sortierung eingetopft werden. Ausser man sortiert das Array von Hand, wozu ich keine Lust habe. Ein Whileloop wäre zwar schön, verbessert allerdings das Skript nicht wirklich.

Vorschläge?
 
Actor Player
Player = Game.GetPlayer()
dann immer Player.mach...
Dann fragt man nicht jedesmal die Gameengin
weniger Code liest sich besser, und eventuell auch schneller.

Einen Whileloop habe ich auch schon getestet. Es landet dann alles in der selben Kiste.

öhh ja nicht gesehen.. sind ja 2 kisten ... dann würd ichs so machen

Code:
ScriptName NNWMaterialSortierSkript Extends ObjectReference
 
Import Utility
Keyword Property NNWErz Auto
Keyword Property NNWBarren Auto
Keyword Property NNWMaterial Auto
ObjectReference Property ErzKiste Auto Hidden
ObjectReference Property BarrenKiste Auto Hidden
ObjectReference Property MaterialKiste Auto Hidden
MiscObject[] Property MaterialListe Auto
int Menge
Int i
Actor Player


Event OnActivate(ObjectReference akActionRef)
         Player = Game.GetPlayer()
         MaterialKiste = GetLinkedRef(NNWMaterial)
         MaterialEinlagern(1)
         MaterialEinlagern(2)
EndEventv

Function MaterialEinlagern(int k)

If k = 1 Then
  Kiste = GetLinkedRef(NNWErz)
ElsIf K = 2 then
  Kiste = GetLinkedRef(NNWBarren)
Endif
         i = 1
         while (i <= MaterialListe[MaterialListe.Length - 1])
           Menge = 0
           Menge = Player.GetItemCount(MaterialListe[i])
            if(Menge > 0)
              Kiste.Additem(MaterialListe[i], Menge)
                 Player.RemoveItem(MaterialListe[i], Menge)
              EndIf
            i += 1
         endWhile
EndFunction


oder so .. bin mir aber der Übergabe Syntax nicht sicher


Code:
ScriptName NNWMaterialSortierSkript Extends ObjectReference
 
Import Utility
Keyword Property NNWErz Auto
Keyword Property NNWBarren Auto
Keyword Property NNWMaterial Auto
ObjectReference Property ErzKiste Auto Hidden
ObjectReference Property BarrenKiste Auto Hidden
ObjectReference Property MaterialKiste Auto Hidden
MiscObject[] Property MaterialListe Auto
int Menge
Int i
Actor Player


Event OnActivate(ObjectReference akActionRef)
         Player = Game.GetPlayer()
         MaterialKiste = GetLinkedRef(NNWMaterial)
         MaterialEinlagern(GetLinkedRef(NNWBarren))
         MaterialEinlagern(GetLinkedRef(NNWBarren))
EndEventv

Function MaterialEinlagern(Kiste)

         i = 1
         while (i <= MaterialListe[MaterialListe.Length - 1])
           Menge = 0
           Menge = Player.GetItemCount(MaterialListe[i])
            if(Menge > 0)
              Kiste.Additem(MaterialListe[i], Menge)
                 Player.RemoveItem(MaterialListe[i], Menge)
              EndIf
            i += 1
         endWhile
EndFunction
 
Zuletzt bearbeitet:
Dann fragt man nicht jedesmal die Gameengin. weniger Code liest sich besser, und eventuell auch schneller.
Nicht unbedingt die function GetActorReference() besteht nur aus (GetReference() as Actor) wovon letzteres wesentlich schneller ausgeführt wird.

Desweiteren was haltet ihr davon?:

Code:
Formlist Property MaterialListe Auto   ;materialListe ist indiesem fall eben eine Formlist und kein array.

Event OnActivate(ObjectReference akActionRef)
Menge = 0
min = 0
max = MaterialListe.GetSize()
Object = MaterialListe.GetAt(min)
    While (min <= max)
        Menge = Game.GetPlayer().GetItemCount(Object)
        if Object.HasKeyword(NNWErz)
            ErzKiste.Additem(Object, Menge)
        ElseIf Object.HasKeyword(NNWBarren)
            BarrenKiste.Additem(Object, Menge)
        Else
            MaterialKiste.Additem(Object,Menge)
        EndIf    
        Game.GetPlayer().RemoveItem(Object, Menge)
        min += 1
    EndWhile  
EndEvent

Wenn man keine Objekte direckt anfassen will, was ich immer sehr empfehle, kann man natürlich anstatt Keywords den Objekten zuzuteilen, diese auch anderen formlists zuteilen und dann anstatt:
Code:
if Object.HasKeyword(NNWErz)
Dies benutzen:
Code:
if NNWErzFormlist.HasForm(Object)
Dies für die restlichen Keywords natürlich wiederholen.

Pros:
-Der mod wird dadurch sprachkompatible.
-0 conflicts mit anderen mods.
Cons:
-Jenachdem wielang diese Formlists werden brauch der Script wesentlich länger
 
Zuletzt bearbeitet:
Nicht unbedingt die function GetActorReference() besteht nur aus (GetReference() as Actor) wovon letzteres wesentlich schneller ausgeführt wird.
Desweiteren was haltet ihr davon?:

naja ich schreibe sonst vbscript. Für mich ist der Player wie ein Object. Das setzt man einmal und arbeitet dann mit der Object Variable .... und ich bin schreibfaul :-D

Yepp sehr schön dein Code
 
Wenn man keine Objekte direckt anfassen will, was ich immer sehr empfehle, kann man natürlich anstatt Keywords den Objekten zuzuteilen, diese auch anderen formlists zuteilen und dann anstatt:

Ja würde ich auch empfehlen.
Meine Mod fasst kein einziges Object an. Ich mache alles über Alias, Formlist etc.

Das ist z.B. mein Holz sammel Script. Will ich da was hinzugeben oder wegnehmen, einfach nur die Liste Mutieren. Der Script bleibt immer gleich. Ist ein riesen Vorteil.

Code:
Scriptname xgfPferdeKarrenWood extends activemagiceffect  
Idle property HolzSammeln Auto
Idle property IdleStop_Loose Auto
MiscObject Property xgfPferdeKarrenFireWoodItem Auto
GlobalVariable Property xgfPferdeKarrenWoodCut Auto
GlobalVariable Property xgfPferdeKarrenTreeDirtClear Auto
FormList Property xgfPferdeKarrenTreeList Auto 
FormList Property xgfPferdeKarrenTreeDirtList Auto
Message Property xgfPferdeKarrenMsg03 Auto
Message Property xgfPferdeKarrenMsg02 Auto
Message Property xgfPferdeKarrenMsg01 Auto


ObjectReference BaumDa
Actor Player
float fPosX
float fPosY
float fPosZ
float fAngZ


EVENT onEffectStart(Actor akTarget, Actor akCaster)
;Debug.MessageBox(xgfPferdeKarrenWoodCut.GetValue())
  Player = Game.GetPlayer()
   fPosX = Player.GetPositionX()
   fPosY = Player.GetPositionY()
   fPosZ = Player.GetPositionZ()
   BaumDa = Game.FindClosestReferenceOfAnyTypeInList(xgfPferdeKarrenTreeList, fPosX , fPosY , fPosZ , 150.0)
      If BaumDa
             If xgfPferdeKarrenTreeDirtList.HasForm(BaumDa) 
               xgfPferdeKarrenMsg01.Show()
             Else
                     Player.PlayIdle(HolzSammeln)
                       xgfPferdeKarrenMsg02.Show()
                      Utility.Wait(3)
                         if xgfPferdeKarrenTreeDirtClear.GetValue() >= 4 ||  xgfPferdeKarrenTreeDirtList.GetSize() >= 4
                                   xgfPferdeKarrenTreeDirtClear.SetValue(0) 
                                     xgfPferdeKarrenTreeDirtList.Revert()
                                    Player.AddItem(xgfPferdeKarrenFireWoodItem, 1)
                          EndIf
                        xgfPferdeKarrenTreeDirtClear.SetValue( xgfPferdeKarrenTreeDirtClear.GetValue() +1)
                             xgfPferdeKarrenTreeDirtList.AddForm(BaumDa)
                               Player.PlayIdle(IdleStop_Loose)
                              BaumDa.Disable()
                              Utility.Wait(30)
                          BaumDa.Enable(True)
              EndIf
      Else
         xgfPferdeKarrenMsg03.Show()
      EndIf
EndEvent
 
Wenn man keine Objekte direckt anfassen will, was ich immer sehr empfehle, kann man natürlich anstatt Keywords den Objekten zuzuteilen, diese auch anderen formlists zuteilen und dann anstatt:

Damit hast du zusätzlich zu deinem Aktivator 3 Formlists / 3 zusätzliche Einträge in der ESP. Das Array brauch ich nur in der Reihenfolge voll machen wie die Sortierung des CKs ist. Die Sortierung der FList musst du obendrein von Hand korrigieren. Geht beim Material, allerdings nicht bei den Ingredienzien denn da wirst alt, weil du dass für jedes neue Pi wiederholen musst.

Könntest du deinen Lösungsansatz als komplettes Beispielskript hierein stellen? Den je mehr Beispiele wir haben, desto hilfreicher wird dieser Thread.
 
Code:
Actor Property PlayerRef Auto
Formlist Property NNWErzFormList Auto  ;Anstatt keywords auf die obejcte zusetzen erstellt man eine Formlist mit diesen Objecten
Formlist Property NNWBarrenFormList Auto
Formlist Property NNWMaterialFormlist Auto
ObjectReference Property ErzKiste Auto Hidden
ObjectReference Property BarrenKiste Auto Hidden
ObjectReference Property MaterialKiste Auto Hidden
Formlist Property MaterialListe Auto
int Menge
int min
int max

Event OnActivate(ObjectReference akActionRef)
Menge = 0
min = 0
max = MaterialListe.GetSize()

    While (min <= max)
        Object = MaterialListe.GetAt(min)
        Menge = PlayerRef.GetItemCount(Object)
        if NNWErzFormList.HasForm(Object)
            ErzKiste.Additem(Object, Menge)
        ElseIf NNWBarrenFormList.HasForm(Object)
            BarrenKiste.Additem(Object, Menge)
        ElseIt NNWMaterialFormList.HasForm(Object)  ;wenn es nur else wäre würde [U]jedes[/U] object das nicht in einer der oberen formlists enthalten is zur kiste hinzugefügt.
            MaterialKiste.Additem(Object,Menge)
        EndIf    
        PlayerRef.RemoveItem(Object, Menge)
        min += 1
    EndWhile  
EndEvent

Es ist richtig, das man die objekte alle per hand in die passenden formlists füllen muss (erz1 muss z.B in Formlist MaterialListe UND in Formlist NNWErzFormlist). Jedoch wie Xgf schon erwähnt hat hat man durch diese prozedur den vorteil, das man neue Objecte einfach den passenden Formlists hinzufügen kann und nichts weiter verändern muss. Und dadurch werden die Objekte halt nicht direckt berüht, wie als wenn man Keywords auf denen placed.

Geht beim Material, allerdings nicht bei den Ingredienzien denn da wirst alt, weil du dass für jedes neue Pi wiederholen musst.
Das verstehe ich jetzt nicht ganz wie das gemeint ist.
 
Zuletzt bearbeitet:
Die Keywords sind für die Kisten (nicht für die Items!), da man einem Aktivator nur mehrere Referenzen mit eben diesen zuweisen kann. Funktioniert bei mir ähnlich wie bei den Bücherregalen.

Das verstehe ich jetzt nicht ganz wie das gemeint ist.

Bei über 90 Einträgen, die du jedes mal passend für die DV von Hand umsortieren musst, ist das eine eklige Arbeit (AB / CD usw.).
Dein Lösungsvorschlag ist trotzdem gut.

@Quad2Core unter mir

Ja das kommt halt drauf an wieviele ingredients du in der formlist haben willst und wieviele nicht, aber wenn du alle items haben willst kannst du sie ja einfach per drag and drop hinzufügen und das wars kein weiteres sortieren ist nötig. Für die Deutsche Version musst du nichts weiter tun. Die Formlists funktionieren mit jeder sprach version von skyrim.

Wenn man nicht alle einsortieren möchte, ist das Skript schon wieder wie mit Schrot auf Spatzen zu schiessen.
Für die DV musst du die einzelnen Objekte so umsortieren, das z.B ein Steinhuscherei in Behälter S und ein Drosselei in Behälter D landet.
Ansonsten landen alle beide in B : Birdegg01 & 02
 
Zuletzt bearbeitet von einem Moderator:
Die Keywords sind für die Kisten
Aso hehe hatte es mir wohl doch nicht genau genug angeguckt^^. Ich hatte eigentlich nur das Prinzip angepasst, welches ich für mein customizable weights mod erstellt habe.

Bei über 90 Einträgen, die du jedes mal passend für die DV von Hand umsortieren musst, ist das eine eklige Arbeit (AB / CD usw.).
Dein Lösungsvorschlag ist trotzdem gut.
Ja das kommt halt drauf an wieviele ingredients du in der formlist haben willst und wieviele nicht, aber wenn du alle items haben willst kannst du sie ja einfach per drag and drop hinzufügen und das wars kein weiteres sortieren ist nötig. Für die Deutsche Version musst du nichts weiter tun. Die Formlists funktionieren mit jeder sprach version von skyrim.
 
@Quad2Core: Die getAt()-Function muss im while-Loop ausgeführt werden, ansonsten wird nur das Object an der Stelle 0 (weil min = 0 deklariert wurde) bis zu "max" Mal den Containern hinzugefügt. Und bitte, verwendet niemals Game.getPlayer(). Diese Function ist so ziemlich die langsamste von ganz Papyrus. Das Austauschen von Game.getPlayer() mit einer playerRef-Property hat mir bei dieser Mod das Skript um bis zu 1 Sekunde verschnellert.
 
  • Like
Reaktionen: Quad2Core
@Kahmul
jo stimmt mein fehler wird berichtigt. Ich hatte schon mal davon gehört das Game.getPlayer() nicht so gut sein soll, aber das es so langsam ist oO. Danke für die information, man lernt nie aus :)

Edit:
wen es interessiert: Ich hab gerade einen post auf Gameskyrim.com gefunden, welcher sogar besagt, dass die version über den property bis zu 1.000 x schneller ist (ja eintausend).
Hier die source (englisch)
 
Zuletzt bearbeitet:
Jep, stimmt. Wurde mehrmals von mehreren Leuten getestet. Wen so etwas mehr interessiert sollte im Beth-Forum vorbeischauen, da wird so etwas oft diskutiert.
 
Ich finde auch diese Information sollte gepinnt werden und/oder in der CK wiki enthalten sein, da man anstonsten nur darauf stößt, wenn man explizit danach sucht.

p.s scheint so als steht jetzt doch noch ne menge Arbeit vor mir hehe (alle scripts überarbeiten :/)
 
Ich habe die Tage erst mit jemanden im Beth-Forum darüber diskutiert, da er die These gebracht hat, dass ein Alias/Property effizienter sei als Game.GetPlayer() und dass man Game.GetPlayer() nie benutzen soll.

Ich bin nicht der Meinung, dass das 100%ig korrekt ist. Ich mag zwar hier auf Kleinigkeiten rumreiten, aber imho ist das wichtig für das verstehen einer Script-/Programmiersprache:

Ein Alias mag zwar schneller sein als Game.GetPlayer(), effizienter ist allerdings Game.GetPlayer(), da ein Alias/Property während der kompletten Laufzeit im Cache gespeichert wird, während Game.GetPlayer() nur für nen Bruchteil einer Sekunde im Cache gehalten wird.

Aus diesem Grund verwende ich einmal Game.GetPlayer() in der Funktion und speichere mir den Rückgabewert in eine Variable -> Diese variable wird nur solange gespeichert wie sie benötigt wird, nämlich nur während der Laufzeit der Funktion.

Problematisch ist Game.GetPlayer() erst dann, wenn man das mehrmals hintereinander aufruft...
 
  • Like
Reaktionen: Ysolda und Dacri