WodoOfSkyrim Posted October 22, 2020 Share Posted October 22, 2020 (edited) 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 npcWigActor npcWigActor Function stripWig(Actor npc) if (npc) npcWig = npc.getWornForm(0x00000002) as Armor if (npcWig) npcWigActor = npc npc.unequipitemSlot(31) endif endifEndFunctionFunction equipWig(Actor npc) if (npc && npcWig && (npc == npcWigActor)) npc.equipItem(npcWig) endifEndFunctionFunction cycleWig(Actor npc) if (npc) stripWig(npc) equipWig(npc) endifEndFunction Begin ScriptWodoDance.stripWig(akSpeaker) End ScriptWodoDance.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 October 22, 2020 by WodoOfSkyrim Link to comment Share on other sites More sharing options...
Reneer Posted October 22, 2020 Share Posted October 22, 2020 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 More sharing options...
ReDragon2013 Posted October 22, 2020 Share Posted October 22, 2020 (edited) 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 October 22, 2020 by ReDragon2013 Link to comment Share on other sites More sharing options...
Recommended Posts