Jump to content

Puzzled by order of effect in papyrus script


Recommended Posts

I have solved the problem but I wonder how/why Papyrus does what I found. Simply trying to learn because, at some point, I'd like to publish mods that make extensive use of scripting and would like them to be free of bugs (introduced by me).

 

I'm writing and testing a mod in a game where I happen to have the KS Hairdos - HDT SMP (Physics) mod and noticed that some of the time an NPC gets stretchy physics hair. This is a known bug. No (known) fix but the mitigation is to either unequip and reequip the NPC's wig or save/restore the game.

 

But since I was writing a mod, I decided to add a utility dialog branch to the mod's dialog tree to unequip and requip the NPC's wig. I tried doing it all in one function and ended up without a wig at the end. So, I split it into 3 functions, stripWig(), equipWig() and cycleWig() along with adding a couple global variables (sigh). Here are the relevant fragments.

 

 

Armor npcWig
Actor npcWigActor

 

Function stripWig(Actor npc)
if (npc)
npcWig = npc.getWornForm(0x00000002) as Armor
if (npcWig)
npcWigActor = npc
npc.unequipitemSlot(31)
endif
endif
EndFunction

Function equipWig(Actor npc)
if (npc && npcWig && (npc == npcWigActor))
npc.equipItem(npcWig)
endif
EndFunction

Function cycleWig(Actor npc)
if (npc)
stripWig(npc)
equipWig(npc)
endif
EndFunction

 

 

Begin Script

WodoDance.stripWig(akSpeaker)

 

End Script

WodoDance.equipWig(akSpeaker)

 

 

If I simply call cycleWig() from the Creation Kit Topic Info Begin Script window, the NPC ends up not wearing her wig. However, if I call stripWig() from the Begin Script window and then call equipWig() from the End Script window, works perfectly.

 

The only think I can think of is unequipitemslot() returns after scheduling the task but without actually completing the task. So what I think I get is Equip followed by Strip (and thus no wig). But by calling from Strip from the Begin window, the engine completes the task before executing the code in the End window. Does that make sense?

 

Anyway, I have the feature working so I don't believe I need help with the code. I'm simply trying to understand what is happening rather than me just guessing.

Edited by WodoOfSkyrim
Link to comment
Share on other sites

The only think I can think of is unequipitemslot() returns after scheduling the task but without actually completing the task. So what I think I get is Equip followed by Strip (and thus no wig). But by calling from Strip from the Begin window, the engine completes the task before executing the code in the End window. Does that make sense?

You're right, unequipitemslot() likely isn't verifying whether the item was actually unequipped, particularly because it doesn't return any value which would let you know whether it had succeeded or failed.

Link to comment
Share on other sites

WodoOfSkyrim wrote: "Here are the relevant fragments."

 

Not really.. you provided code snippets from external script. A TopicInfo script looks as follow:

 

 

 

;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment
;NEXT FRAGMENT INDEX 2
Scriptname BYOH_TIF__01016412 Extends TopicInfo Hidden
; https://forums.nexusmods.com/index.php?/topic/9227268-puzzled-by-order-of-effect-in-papyrus-script/

; Keep in mind: This scriptname is originally made for Hearthfire DLC, your scriptname has to be different !!!


;BEGIN FRAGMENT Fragment_0
Function Fragment_0(ObjectReference akSpeakerRef)
Actor akSpeaker = akSpeakerRef as Actor
;BEGIN CODE
;;    (GetOwningQuest() as BYOHRelationshipAdoptionScript).RejectPet()
;;    (GetOwningQuest() as BYOHRelationshipAdoptionScript).ForcegreetEventReady = False

    ; *** your code ***
    WodoDance.stripWig(akSpeaker)

;END CODE
EndFunction
;END FRAGMENT


;BEGIN FRAGMENT Fragment_1
Function Fragment_1(ObjectReference akSpeakerRef)
Actor akSpeaker = akSpeakerRef as Actor
;BEGIN CODE
;;    akSpeaker.SetAV("Variable07", 0)
;;    akSpeaker.EvaluatePackage()

    ; *** your code instead ***
    WodoDance.equipWig(akSpeaker)

;END CODE
EndFunction
;END FRAGMENT

;END FRAGMENT CODE - Do not edit anything between this and the begin comment

  WodoDanceScript PROPERTY WodoDance auto


;/ *** begin multi line comment

    Next functions are code inside "external script" with was assigend by property WodoDance.
    We assume the scriptname is WodoDanceScript (that means saved as WodoDanceScript.psc).

; -- FUNCTIONs -- 2

  Armor npcWig
  Actor npcWigActor

;---------------------------------
FUNCTION stripWig(Actor akSpeaker)  ; akSpeaker = npc
;---------------------------------
IF ( akSpeaker )
    npcWig = akSpeaker.GetWornForm(0x00000002) as Armor        ; SKSE required
    IF ( npcWig )
        npcWigActor = akSpeaker                ; * make an actor persistent
        akSpeaker.UnEquipItemSlot(31)                        ; SKSE required
    ENDIF
ENDIF
ENDFUNCTION


;---------------------------------
FUNCTION equipWig(Actor akSpeaker)  ; akSpeaker = npc
;---------------------------------
IF ( akSpeaker )
    IF (npcWig) && (akSpeaker == npcWigActor)
        akSpeaker.EquipItem(npcWig)
        npcWig = None
        npcWigActor = None                    ; * release the actor persistence
    ENDIF
ENDIF
ENDFUNCTION

end of multi line comment *** /;

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...