Prüfen, ob ein Objekt im Spielerinventar liegt

TripleBlade

Fremdländer
Hallo, wie schon der Titel sagt, versuche ich zu prüfen, ob der Spieler gerade "mein" Objekt aufgehoben hat. Ich erschaffe per PlaceAtMe() relativ einfach ein Objekt in der Welt,
nachdem der Spieler einen Zauber ausgeführt hat.
Da es sich bei dem erschaffenen Objekt aber um einen Kuchen und nicht um einen Actor handelt, kann ich diesem kein Script zuweisen. Momentan regle ich dieses Problem über eine while Schleife,
die ich dem MagicEffect hinzugefügt habe. Das ganze ist für mich auch nur deswegen möglich, weil der Kuchen nach 30 Sekunden wieder aus der Welt gelöscht wird (ansonsten würde die while Schleife
ja auch für immer laufen). Trotzdem ist das ganze nicht sehr elegant:

Code:
Scriptname spawnsweetroll extends ActiveMagicEffect
Potion Property sweetRoll auto
Objectreference newRefStore


Event onEffectStart(ACTOR akTarget, ACTOR akCaster)


    newRefStore = akTarget.placeAtMe(sweetRoll)
    int waito = 30


    while (waito >= 0)
        
        if(Game.GetPlayer().GetItemCount(newRefStore) < 1)
            utility.wait(1)
            waito -= 1
        
        else    
            Game.GetPlayer().DropObject(newRefStore)
        ENDIF
    endwhile
newRefStore.disable()
endEvent

Besser wäre eindeutig, zu überprüfen, ob der Kuchen aufgehoben wird. Leider kann man dem Kuchen anscheinend kein Script zuweisen, das dieses Event ausführt und sich selbst nach 30 Sekunden löscht.
Meine Frage ist also ganz einfach: Weiß jemand, wie man Events eines anderen Objekts ausliest? :p
mfg TripleBlade
 
Ich sehe bei deinem Script folgendes Problem:
GetItemCount verlangte eine Form und deine ObjectReference wird daher zu einer Form gecastet, was bedeutet das dein Script verursacht,
dass wenn das Event onEffectStart feuert alle "sweetRoll's" aus dem Spieler Inventar entfernt werden. Und nach der Loop nur die ObjectReference newRefStore disabled wird.

Ich verstehe dein vorhaben aber so, dass sich der Komplette Script nur auf diese eine Reference beziehen soll.
Das heißt du müsstes einen Weg finden, um diese Reference irgendwo zwischen zu speichern.
Ich würde das mit einer Quest bzw einer AliasReference machen:
  1. Dafür musst du eine Quest erstellen, welche start game und run once NICHT gecheckt hat.
  2. erstelle in dieser Quest ein Alias mit Find Matching Reference gefüllt wird checke die folgenden Checkboxen: In loaded Area; Closest;
  3. Nun musst du noch eine Condition hinzufügen, die sicherstellt, das dabei nur nach "sweetRoll" gesucht wird. Die GetIsID condition sollte dafür funktionieren.
  4. Jetzt kannst du dem Alias noch einen Passenden Script zu weisen, der tuen soll was du willst. z.B:
    Code:
    [COLOR=#0000FF][FONT=monospace][B]Event [/B][/FONT][/COLOR][COLOR=#6565C6][FONT=monospace][B]OnContainerChanged[/B][/FONT][/COLOR][COLOR=#000000][FONT=monospace]([/FONT][/COLOR][COLOR=#008040][FONT=monospace][B]ObjectReference[/B][/FONT][/COLOR][COLOR=#000000][FONT=monospace] akNewContainer[/FONT][/COLOR][COLOR=#0080FF][FONT=monospace][B],[/B][/FONT][/COLOR][COLOR=#008040][FONT=monospace][B]ObjectReference[/B][/FONT][/COLOR][COLOR=#000000][FONT=monospace] akOldContainer[/FONT][/COLOR][COLOR=#000000][FONT=monospace])
    [/FONT][/COLOR][COLOR=#0000FF][FONT=monospace][B]if [/B][/FONT][/COLOR][COLOR=#000000][FONT=monospace]akNewContainer == Game.GetPlayer()
    [/FONT][/COLOR]​    Game.GetPlayer().DropObject(self, 1)
    [COLOR=#0000FF][FONT=monospace][B]endif
    [/B][/FONT][/COLOR][COLOR=#0000FF][FONT=monospace][B]endEvent[/B][/FONT][/COLOR]
Nun musst du nur noch deinen Bisherigen Script anpassen:
Code:
Quest Property MyQuest Auto

[COLOR=#0000FF][FONT=monospace][B]Event [/B][/FONT][/COLOR][COLOR=#6565C6][FONT=monospace][B]OnEffectStart[/B][/FONT][/COLOR][COLOR=#000000][FONT=monospace]([/FONT][/COLOR][COLOR=#008040][FONT=monospace][B]Actor[/B][/FONT][/COLOR][COLOR=#000000][FONT=monospace] akTarget[/FONT][/COLOR][COLOR=#0080FF][FONT=monospace][B],[/B][/FONT][/COLOR][COLOR=#008040][FONT=monospace][B]Actor[/B][/FONT][/COLOR][COLOR=#000000][FONT=monospace] akCaster[/FONT][/COLOR][COLOR=#000000][FONT=monospace])
   newRefStore = akTarget.placeAtMe(sweetRoll)
   MyQuest.Start()
   RegisterForSingleUpdate(30.0)
[COLOR=#0000FF][B]endEvent
[/B][/COLOR]
[COLOR=#0000FF][B]Event[/B][/COLOR] [COLOR=#6565C6][B]OnUpdate[/B][/COLOR]()
   MyQuest.Stop()
   newRefStore.disable()
[FONT=monospace][COLOR=#0000FF][B]endEvent[/B][/COLOR][/FONT][/FONT][/COLOR]

Ich hoffe das hilft dir weiter oder bringt dich wenigstens näher ans Ziel :D
 
Zuletzt bearbeitet:
  • Like
Reaktionen: TripleBlade
Vielen Dank für deine Antwort! Leider hilft mir das gar nicht weiter, da:
1. Das Update wird nicht ausgeführt
Code:
EVENT onEffectStart(ACTOR akTarget, ACTOR akCaster)
    
    
    
    akTarget.placeAtMe(appearExplosion)
    shader.play(akTarget, 2)
    newRefStore = akTarget.placeAtMe(sweetRoll)
    MyQuest.Start()
       RegisterForSingleUpdate(30.0)


endEVENT


Event OnUpdate()
    debug.messagebox("Update!") <--- Diese Nachricht kam im gesamten Spiel nicht ein einziges mal, auch nachdem ich 2. ausgeschlossen habe
    if(Game.GetPlayer().GetItemCount(newRefStore) < 1)
        MyQuest.Stop()
    endif
    RegisterForSingleUpdate(1.0)
    if (MyQuest.IsActive() == False)
         
        newRefStore.placeAtMe(appearExplosion)
    shader.play(newRefStore, 2)
    newRefStore.disable()
    endif
endEvent

2. Die ID des Kuchens, den ich erschaffe, ist nicht die eines normalen Kuchens, sondern die meines Mods. Folglich bringt die Einscgränkung des Quests auf SweetRoll IDs nichts. Wenn ich sie weglasse, läuft der Quest aber auf jedem Objekt... also muss ich wohl das Objekt, das ich im MagicEffect erschaffen habe mit dem Quest verbinden. Wie geht das?

mfg, TripleBlade
 
Zuletzt bearbeitet:
zu 1: Hatte vergessen, das MagicEffects sich selbst unregistrieren, wenn der effect abläuft...

zu 2: das hatte ich in meinem vorherigen Post ja schon beschrieben die Condition ist dafür gut das die AliasReference genau mit diesem Object, welches der Condition zutrifft gefüllt wird.
Poste doch vllt ein paar screenshots wie deine quest aussieht und der Alias dazu..
 
Du könntest auch eine zweite Quest erstellen.
Zu dieser Quest fügst du ein Script hinzu:

Code:
Scriptname MyQuestScript extends Quest Hidden 


; Ref
ObjectReference property MyRef auto

dann in deinem Effekt:
Code:
Quest Property MyQuest Auto

Event OnEffectStart(Actor akTarget, Actor akCaster)

    MyQuest.Start()
    (MyQuest as MyQuestScript).MyRef = mySweetRoll

EndEvent

Dann erstellst du in MyQuest ein PlayerAlias und fügst diesem folgendes Script hinzu:
Code:
Scriptname PlayerAliasScript extends ReferenceAlias  


Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
    MyQuestScript MyQuest = GetOwningQuest() as MyQuestScript
    If (MyQuest.MyRef == akItemReference)
        Debug.Notification("BINGO")
        MyQuest.Stop()
    EndIf
EndEvent

Achtung: nicht getestet, sollte aber so funktionieren.
 
  • Like
Reaktionen: TripleBlade
@justik Sorry, bin noch Anfänger... wo genau füge ich ein Script zum Quest hinzu? So wie ich das jetzt verstehe meinst du auch gar nicht, dass ich einen zweiten Quest hinzufügen soll, sondern den vorhandenen abändern, oder? EDIT: Okay, ich denke ich habe rausgefunden, dass man das Script komplett bearbeiten kann im Scripts Tab des Quests. Mal sehen.
Das mit dem Alias müsste ich aber hinkriegen (im QuestAlias Tab, oder? :p)

@Quad2Core So, hier ein paar screenshots:
Desktop_2014_04_24_15_02_09_478.jpgDesktop_2014_04_24_15_02_16_797.jpgDesktop_2014_04_24_15_02_58_878.jpgDesktop_2014_04_24_15_01_51_854.jpgDesktop_2014_04_24_15_09_55_422.jpg
 
Zuletzt bearbeitet:
Hi.
Mal ne Frage:
Was willst du überhaupt erreichen, wann soll der Kuchen erscheinen und wie soll das ganze von statten gehen. Bevor ihr euch hier noch einen weiteren Ast abbrecht. ;)
 
Also: Mein Test Mod hat zum Ziel, die Person, auf die der Spieler einen Zauber wirkt, in einen Kuchen zu verwandeln (ja, wirklich). Den Zielactor zu ersetzen ist kein Problem. Mein Ziel ist, dass man den Kuchen dann mitnehmen und kann, und nachdem dieser für 30 Sekunden in der Welt war, an dieser Stelle wieder der gespeicherte Actor hingestellt wird. Praktisch wenn jemand im weg steht, oder du willst, dass er irgendwo hingeht :D. Soweit funktioniert das ganze auch. Dass einzige Problem ist, dass wirklich jedem Objekt außer Essen - wie z.B. ein Kuchen - einfach ein Script zugewiesen werden kann, dass von meinem MagicEffect dann die nötigen Variablen erhält.
Mit jedem Objekt und Tier funktioniert das (ich habe den Zauber auch noch für Pferde, Truhen, usw. gemacht), bis auf... den Kuchen. Liegt dieser 30 Sekunden irgendwo rum, tut sich standardmäßig nichts, und ich kann dies auch nicht ändern.

Mein Problem ist jetzt: Ich kriege den (oder die? Ich kann mir das nie merken) Quest nicht zum laufen.
Code:
Scriptname dunTransmogrifyObjectLongScript extends ActiveMagicEffect
POTION PROPERTY sweetRoll AUTO


EXPLOSION PROPERTY appearExplosion AUTO
EFFECTSHADER PROPERTY shader AUTO


OBJECTREFERENCE objStore
OBJECTREFERENCE newRefStore
Quest Property MyQuest Auto


String PROPERTY permanento AUTO
string Property name auto


dunTransmogrifyActorLong mainScript


EVENT onEffectStart(ACTOR akTarget, ACTOR akCaster)
        
    objStore = akTarget
    name = akTarget.GetDisplayName()
    akTarget.placeAtMe(appearExplosion)
    shader.play(akTarget, 2)
    akTarget.disable()
    akTarget.stopCombat()
    
    newRefStore = akTarget.placeAtMe(sweetRoll)
    newRefStore.SetDisplayName(akTarget.GetDisplayName())
    ;newRefStore.SetDisplayName(akCaster.GetDisplayName())
    ;int waito = 30
    MyQuest.Start()
    [B]if(MyQuest.SetCurrentStageID(0))[/B]
        [B]debug.messagebox("wtf! Irgendetwas funktioniert ja wirklich -.-")[/B]
    [B]endif[/B]
    ;OhReally (1)
    (MyQuest as SweetRollQScript).theSweetRoll = newRefStore
    (MyQuest as SweetRollQScript).theeffect = SELF
    (MyQuest as SweetRollQScript).effectascripta = SELF


    
       RegisterForUpdate(1.0)
    ;while (waito >= 0)
        ;if(Game.GetPlayer().GetItemCount(newRefStore) < 1)
            ;utility.wait(1)
            ;waito -= 1
            
        ;else    
            ;utility.wait(10)
        
        ;ENDIF
    ;endwhile
    
utility.wait(1000000)


endEVENT






;Event OnUpdate() <--- MagicEffects lassen Update Events anscheinend nicht zu
    


Function OhReally (int interv)
    Debug.Notification("Hello, world!")
    utility.wait(interv)
    OhReally(interv)
endfunction

Also: Ich habe die Property natürlich zugewiesen, Skyrim scheitert aber daran den Quest auf die Stage 0 zu setzen. Auch sämtliche (zwischenzeitlich hatte ich fast ein Dutzend) messageboxes in den Quest Scripten werden nie angezeigt.
Wie schaffe ich es, dass Skyrim den/die Quest startet?
PS: SweetRollQScript ist das Script auf der Quest, darauf habe ich drei Propertys:
theeffect ist dabei der MagicEffect
effectascripta eigentlich auch, nur eben als
dunTransmogrifyObjectLongScript
theSweetRoll ist der Kuchen. Die drei Propertys sind allerdings Nebensache, solange die Quest nichmal zu laufen scheint.
mfg, TripleBlade
 
Zuletzt bearbeitet:
Gut, soweit verstanden. Ich gönn mir jetzt ne Mütze Schlaf und morgen denke ich darüber nach und erarbeite mit dir ne Lösung dazu
:bye:
 
Also: Die Quest funktioniert jetzt. Ich war tatsächlich nur zu doof den PlayerAlias richtig zu setzen :p
Alle messageboxes, die ich angelegt habe, um zu sehen, ob die Quest überhaupt läuft, funktionieren jetzt.
Mein einziges Problem ist jetzt, wie ich den Kuchen nach "genau" dreißig Sekunden lösche. Der Quest gibt mir jetzt zwar erfolgreich zurück, wenn der Kuchen im Inventar liegt...
ohne Loop sehe ich aber immer noch keine Möglichkeit, dreißig Sekunden zu warten... und währenddessen zu überprüfen, ob ich noch weiter warten muss...
Ich lege mir jetzt einfach eine Variable an, ob der Warteloop weiterlaufen soll, die mir vom Quest gesendet/aktualisiert wird. Mir fällt keine bessere Lösung ein. Aber immerhin erhält mein Hauptscript (MagicEffect) jetzt sofort eine Nachricht, wenn der Kuchen im Inventar liegt. :D


EDIT: Okay, war wohl etwas zu begeistert davon, dass es jetzt in Ansätzen funktioniert: Es scheint nur ein einziger Quest zu existieren, obwohl ich für jedes Objekt einen eigenen Quest will :p
Wie erschaffe ich für jedes Objekt einen eigenen Quest des selben Typs?
Code:
Scriptname dunTransmogrifyObjectLongScript extends ActiveMagicEffect
POTION PROPERTY sweetRoll AUTO


EXPLOSION PROPERTY appearExplosion AUTO
EFFECTSHADER PROPERTY shader AUTO


OBJECTREFERENCE objStore
OBJECTREFERENCE newRefStore
Quest Property MyQuest Auto
Quest Property thestartQuest Auto


String PROPERTY permanento AUTO
string Property name auto
int Property thewaitinteger Auto
bool Property thewaitbool Auto


EVENT onEffectStart(ACTOR akTarget, ACTOR akCaster)
	thewaitinteger = 30
	thewaitbool = True
	objStore = akTarget
	name = akTarget.GetDisplayName()
	akTarget.placeAtMe(appearExplosion)
	shader.play(akTarget, 2)
	akTarget.disable()
	akTarget.stopCombat()
	
	newRefStore = akTarget.placeAtMe(sweetRoll)
	newRefStore.SetDisplayName(akTarget.GetDisplayName())
	
	;int waito = 30
	MyQuest.Start()
	;thestartQuest = new Quest
	;OhReally (1)
	
	(MyQuest as SweetRollQScript).theSweetRoll = newRefStore
	(MyQuest as SweetRollQScript).theeffect = SELF
	(MyQuest as SweetRollQScript).effectascripta = SELF


	
   
	
utility.wait(1000000)


endEVENT

mfg, TripleBlade
 
Zuletzt bearbeitet:
Wann soll den weiter gewartet werden? Wenn sich der Kuchen noch im Inventar befindet?
Und könntest du nochmal alle momentanen Scripts posten?
 
Zuletzt bearbeitet:
Gewartet werden soll nur, wenn der Kuchen nicht im Inventar liegt. Also, hier die Scripts:
1. ActiveMagicEffect
Code:
Scriptname dunTransmogrifyObjectLongScript extends ActiveMagicEffect
POTION PROPERTY sweetRoll AUTO


EXPLOSION PROPERTY appearExplosion AUTO
EFFECTSHADER PROPERTY shader AUTO


OBJECTREFERENCE objStore
OBJECTREFERENCE newRefStore
Quest Property MyQuest Auto
Quest Property thestartQuest Auto


String PROPERTY permanento AUTO
string Property name auto
int Property thewaitinteger Auto
bool Property thewaitbool Auto


dunTransmogrifyActorLong mainScript


EVENT onInit ()
Debug.messagebox("Effect initialized")
Endevent


EVENT onEffectStart(ACTOR akTarget, ACTOR akCaster)
	thewaitinteger = 30
	thewaitbool = True
	objStore = akTarget
	name = akTarget.GetDisplayName()
	akTarget.placeAtMe(appearExplosion)
	shader.play(akTarget, 2)
	akTarget.disable()
	akTarget.stopCombat()
	
	newRefStore = akTarget.placeAtMe(sweetRoll)
	newRefStore.SetDisplayName(akTarget.GetDisplayName())
	
	
	MyQuest.Start()
	;thestartQuest = new Quest
	
	(MyQuest as SweetRollQScript).theSweetRoll = newRefStore
	(MyQuest as SweetRollQScript).theeffect = SELF
	(MyQuest as SweetRollQScript).effectascripta = SELF


	
   
	
utility.wait(1000000)


endEVENT




function restoreactor ()
	debug.messagebox("Spawned the stored Actor!")
	MyQuest.Stop()
	newRefStore.placeAtMe(appearExplosion)
	shader.play(newRefStore, 2)
	newRefStore.disable()
	objStore.moveTo(newRefStore)
	objStore.enable()
endfunction

2.Papyrus Fragment auf dem Quest - zu Testzwecken
Code:
SELF.GetNumAliases()
debug.messagebox("Quest has got" + SELF.GetNumAliases() + "Aliases attached")
Auf dem Fragment sind mehrere Propertys:
dunTransmogrifyObjectLongScript Property effectascripta Auto <--- Der MagicEffect wird dem Quest zugewiesen
ObjectReference Property TheSweetRoll Auto <--- Der im MagicEffect erschaffene Kuchen

3. Das Script auf dem PlayerAlias - funktioniert fast... bis auf den Fakt, dass die Messages bei jedem Objekt kommen, dass der Spieler aufhebt...

Code:
Scriptname maintainSweetRoll extends ReferenceAlias  


Actor Property PlayerRef Auto
int waitintegero
bool waitboolo
Event onInit()
;Debug.messagebox("iuadwhgjzuadgh")
	waitintegero = 30
	waitboolo = True
	SweetRollQScript MyQuesty = GetOwningQuest() as SweetRollQScript
	untilspawn(1, MyQuesty)
EndEvent




Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
    SweetRollQScript MyQuesto = GetOwningQuest() as SweetRollQScript
	dunTransmogrifyObjectLongScript effectoscripto = MyQuesto.effectascripta
	
	
    If (MyQuesto.TheSweetRoll == akItemReference || MyQuesto.TheSweetRoll as Form == akBaseItem)
       Debug.messagebox("BINGOO")
	Debug.Trace("BINGO")
     
    EndIf
		
	waitboolo = false
EndEvent


Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
    SweetRollQScript MyQuesto = GetOwningQuest() as SweetRollQScript
	dunTransmogrifyObjectLongScript effectoscripto = MyQuesto.effectascripta
	
	;Debug.messagebox("BINGO")
    If (MyQuesto.TheSweetRoll == akItemReference || MyQuesto.TheSweetRoll as Form == akBaseItem)
       if(!akDestContainer)
		Debug.messagebox("Sweetroll was put into: " + akDestContainer.GetName())
	endif
	;Debug.Trace("BINGO")
       ;MyQuest.Stop()
    EndIf
	;(MyQuesto.theeffect as dunTransmogrifyObjectLongScript).OhReally(1)
	
	;((MyQuesto.theeffect) as dunTransmogrifyObjectLongScript).thewaitbool = True
	;effectoscripto.thewaitbool = True
	
	;((MyQuesto.theeffect) as dunTransmogrifyObjectLongScript).OhReally(1)
	  ;Debug.messagebox("BINGO OUT")
	waitboolo = true
EndEvent




Function untilspawn (int intero,  SweetRollQScript MyQuesty)
	if (waitboolo == True)
		waitintegero -= intero
	endif
	if (waitintegero <= 0)
			 
			((MyQuesty.theeffect) as dunTransmogrifyObjectLongScript).restoreactor()
			return


	endif
	utility.wait(intero)
	if(waitintegero >= 0)
		untilspawn(intero, myquesty)
	endif


Endfunction
 
Okay, mir ist das mit dem Quest jetzt langsam etwas zu kompliziert (und wohl auch zu spezifisch, um hier anzufragen), also gehe ich lieber zu der guten alten performanceunfreundlichen while Schleife zurück. Die hat ja tatsächlich funktioniert :D
Vielen Dank für Eure Hilfe! Wenn jemand weiß, woran es lag, dass das mit der Quest nicht so funktioniert hat, bitte sagen. Ansonsten bin ich auch mit dem Loop zufrieden.
mfg, TripleBlade