Access Property in another script?

Post » Wed Jun 20, 2012 8:27 pm

I have two scripts attached to an Actor, both extend the Actor script. Script A has a number of Properties defined, script B needs to access those. How do I go about this? Simply naming a Property of script A in script B won't compile because the compiler says no such Property exists. I have seen http://www.creationkit.com/Variables_and_Properties#Getting_Properties_of_a_Quest_Script of using an external Property in the wiki, but that was with a Quest script and a result script owned by that Quest, so it's a different situation. My two scripts are no child/parent of each other.

Note, I don't want to do this by using the Property as a parameter in a custom function, that would essentially make script A "send" script B the Property. I want B to access A's Properties on it's own, no help from other scripts.

EDIT:

Looks like using this works? I noticed it compiled successfully but figured this couldn't be right because MyScriptRef has no value. Apparently I look at this the wrong way, since after rereading the wiki page it should work like this.

ScriptA MyScriptRef

myVar = MyScriptRef.PropertyofScriptA
User avatar
Robert Devlin
 
Posts: 3521
Joined: Mon Jul 23, 2007 2:19 pm

Post » Wed Jun 20, 2012 10:15 pm

Not sure on the question, but if both scripts have an OnUpdate block, and RegisterForUpate(X) is used, things go wrong. I had two scripts on a container, and if they both contained the OnUpdate block, instead of the OnUpdate block recieving an update every X seconds as per the RegisterForUpdate(X) in the same script, each script recieved the update just once, and then stopped receiving updates.
User avatar
Celestine Stardust
 
Posts: 3390
Joined: Fri Dec 01, 2006 11:22 pm

Post » Wed Jun 20, 2012 4:17 pm

I'm only scripting Functions right now, I don't have any Events yet, so I'm not having such a problem. Right now everything compiles, I'll test it later.
User avatar
Carlos Vazquez
 
Posts: 3407
Joined: Sat Aug 25, 2007 10:19 am

Post » Wed Jun 20, 2012 5:35 pm

Not sure on the question, but if both scripts have an OnUpdate block, and RegisterForUpate(X) is used, things go wrong. I had two scripts on a container, and if they both contained the OnUpdate block, instead of the OnUpdate block recieving an update every X seconds as per the RegisterForUpdate(X) in the same script, each script recieved the update just once, and then stopped receiving updates.

Did you have an UnregisterForUpdate in one of your scripts? According to the wiki, RegisterForUpdate registers for all the scripts sharing the same object. So if your container has two scripts on it, calling RegisterForUpdate from one of them would have both of them receiving the event.

I've tested it out with quests and magic effects, and can confirm it's true. It's also true for RegisterForAnimationEvent, and I assume for all the other RegisterX functions.

Guess that's a reason why it's a bad idea to put scripts directly on the player. Also got worried about spells and magic effects. Thought that it meant an event received by one effect would be received by another effect from the same spell, but fortunately not since each effect is its own item with its own set of scripts.
User avatar
matt
 
Posts: 3267
Joined: Wed May 30, 2007 10:17 am

Post » Wed Jun 20, 2012 4:23 pm

An alternative I use (and it may not work in your situation) is to create a quest with whatever Event you use to initialze the script.
Then create numerous functions accessed by other scripts.

MyFunctionsScript Property CallFunction Auto <<<<< is define in all the scripts that need to use the functions in the main script.

if ....
CallFunction.ABC()
endif


Edit: A caveat is that you cannot access non property variables in the main script outside of calling the function.
User avatar
Shelby Huffman
 
Posts: 3454
Joined: Wed Aug 08, 2007 11:06 am

Post » Wed Jun 20, 2012 11:04 pm

Here's an example where a MGEF script accesses a property/function of a quest.

Quest:
Spoiler
ScriptName LightweightPotionsQuestScript extends Quest ConditionalActor Property MaiqTheLiarREF AutoFloat Property fWeight = 0.5 Auto ConditionalFormList Property LightweightPotionsFLST AutoLeveledItem Property LightweightPotionsLVLI AutoPotion Property LightweightPotionsALCH AutoEvent OnInit()	RegisterForSingleUpdate(1)EndEventEvent OnUpdate()	If GetGameLoaded(LightweightPotionsLVLI, LightweightPotionsALCH, MaiqTheLiarREF)		If !Game.GetPlayer().GetItemCount(LightweightPotionsALCH)			Game.GetPlayer().AddItem(LightweightPotionsALCH)		EndIf		If (fWeight != 0.5)			Reweigh(LightweightPotionsFLST)		EndIf	EndIf	RegisterForSingleUpdate(30)EndEventFunction Reweigh(FormList akFormList = None, Int aiListIndex = 0)	aiListIndex = akFormList.GetSize()	While (aiListIndex > -1)		aiListIndex -= 1		akFormList.GetAt(aiListIndex).SetWeight(fWeight)	EndWhileEndFunction Bool Function GetGameLoaded(LeveledItem akLeveledItem = None, Form akForm = None, ObjectReference akContainer = None)	akContainer.AddItem(akLeveledItem, 1, True)	If akContainer.GetItemCount(akForm)		akContainer.RemoveItem(akForm, akContainer.GetItemCount(akForm), True)		Return False	Else		akLeveledItem.AddForm(akForm, 1, 1)		Return True	EndIfEndFunction 
Magic Effect:
Spoiler
ScriptName LightweightPotionsEffectScript extends ActiveMagicEffectFormList Property LightweightPotionsFLST AutoLightweightPotionsQuestScript Property QuestScript AutoMessage Property LightweightPotionsMESG AutoPotion Property LightweightPotionsALCH AutoEvent OnEffectStart(Actor akTarget, Actor akCaster)	Game.DisablePlayerControls(False, False, False, False, False, True)	Game.GetPlayer().AddItem(LightweightPotionsALCH, 1, True)	Utility.Wait(0.01)	Game.EnablePlayerControls(False, False, False, False, False, True)	QuestScript.fWeight = LightweightPotionsMESG.Show()	If (QuestScript.fWeight != -1)		QuestScript.fWeight *= 0.1		QuestScript.Reweigh(LightweightPotionsFLST)	EndIfEndEvent 

If conditionalizing with a messagebox button or whatnot, GetVMQuestVariable will work for any conditional properties.
User avatar
Ruben Bernal
 
Posts: 3364
Joined: Sun Nov 18, 2007 5:58 pm

Post » Wed Jun 20, 2012 5:56 pm

I figured it about 15 minutes ago, but thanks anyway! It's good to have a look at another script to compare and gain deeper understanding.
User avatar
D LOpez
 
Posts: 3434
Joined: Sat Aug 25, 2007 12:30 pm

Post » Thu Jun 21, 2012 3:06 am

Here's an example where a MGEF script accesses a property/function of a quest. Quest:
Spoiler
ScriptName LightweightPotionsQuestScript extends Quest Conditional Actor Property MaiqTheLiarREF Auto Float Property fWeight = 0.5 Auto Conditional FormList Property LightweightPotionsFLST Auto LeveledItem Property LightweightPotionsLVLI Auto Potion Property LightweightPotionsALCH Auto Event OnInit() RegisterForSingleUpdate(1) EndEvent Event OnUpdate() If GetGameLoaded(LightweightPotionsLVLI, LightweightPotionsALCH, MaiqTheLiarREF) If !Game.GetPlayer().GetItemCount(LightweightPotionsALCH) Game.GetPlayer().AddItem(LightweightPotionsALCH) EndIf If (fWeight != 0.5) Reweigh(LightweightPotionsFLST) EndIf EndIf RegisterForSingleUpdate(30) EndEvent Function Reweigh(FormList akFormList = None, Int aiListIndex = 0) aiListIndex = akFormList.GetSize() While (aiListIndex > -1) aiListIndex -= 1 akFormList.GetAt(aiListIndex).SetWeight(fWeight) EndWhile EndFunction Bool Function GetGameLoaded(LeveledItem akLeveledItem = None, Form akForm = None, ObjectReference akContainer = None) akContainer.AddItem(akLeveledItem, 1, True) If akContainer.GetItemCount(akForm) akContainer.RemoveItem(akForm, akContainer.GetItemCount(akForm), True) Return False Else akLeveledItem.AddForm(akForm, 1, 1) Return True EndIf EndFunction 
Magic Effect:
Spoiler
ScriptName LightweightPotionsEffectScript extends ActiveMagicEffect FormList Property LightweightPotionsFLST Auto LightweightPotionsQuestScript Property QuestScript Auto Message Property LightweightPotionsMESG Auto Potion Property LightweightPotionsALCH Auto Event OnEffectStart(Actor akTarget, Actor akCaster) Game.DisablePlayerControls(False, False, False, False, False, True) Game.GetPlayer().AddItem(LightweightPotionsALCH, 1, True) Utility.Wait(0.01) Game.EnablePlayerControls(False, False, False, False, False, True) QuestScript.fWeight = LightweightPotionsMESG.Show() If (QuestScript.fWeight != -1) QuestScript.fWeight *= 0.1 QuestScript.Reweigh(LightweightPotionsFLST) EndIf EndEvent 
If conditionalizing with a messagebox button or whatnot, GetVMQuestVariable will work for any conditional properties.

Can you or someone help me sort this out, please? I tried to follow your example, but I'm not doing something right.
I have 2 scripts, a conditional Quest Script (MyQuestScript) attached to a Quest (MyQuest), and an ObjectReference Script (MyBookScript) attached to a Book (MyBook). The idea being that when the player reads the book, some Messages will ask the player to select some options, and those choices get passed to the Quest Script.
MyQuestScript:
Spoiler

Scriptname MyQuestScript Extends Quest Conditional
Int Property intSetting1 = 0 Auto Conditional
Int Property intSetting2 = 0 Auto Conditional
Int Property intSetting3 = 0 Auto Conditional
Bool Property bAllSet = False Auto Conditional
MyBookScript:
Spoiler

Scriptname MyBookScript Extends ObjectReference
Quest Property MyQuestRef Auto
MyQuestScript Property MyQuestScriptRef Auto
Message Property MyMessage1 Auto
Message Property MyMessage2 Auto
Message Property MyMessage3 Auto

Event OnEquipped(Actor PlayerRef)
ReadMyBook()
EndEvent

Function ReadMyBook()
MyQuestScriptRef.intSetting1 = MyMessage1.Show()
MyQuestScriptRef.intSetting2 = MyMessage2.Show()
MyQuestScriptRef.intSetting3 = MyMessage3.Show()
MyQuestScriptRef.bAllSet = True
End Function

The Messages show up when I read the book. But, the Quest Script never sees the values of it's conditional properties get changed.

In the Creation Kit, when looking at the Properties for a Script, what value does one fill the MyQuestScriptRef Property with? It doesn't Auto-Fill like the Message Properties do. It seems to me that this might be the crux of my issue. If the Book Script doesn't have a good reference set for the Quest Script, it can not set the value of any Property on that Quest Script.
User avatar
Penny Courture
 
Posts: 3438
Joined: Sat Dec 23, 2006 11:59 pm

Post » Wed Jun 20, 2012 11:47 pm

Change:

Quest Property MyQuestRef Auto

To:

MyQuestScript Property MyQuestRef Auto
User avatar
Taylah Haines
 
Posts: 3439
Joined: Tue Feb 13, 2007 3:10 am

Post » Wed Jun 20, 2012 9:05 pm

Thanks for replying. But, Papyrus is still making me feel like an idiot.

This is the script attached to my book:
Spoiler
Scriptname MyBookScript extends ObjectReference
MyQuestScript Property MyQuestScriptRef Auto
Message Property MyMessage1 Auto
Message Property MyMessage2 Auto
Function ReadMyBook()
MyQuestScriptRef.iSetting1 = MyMessage1.Show()
MyQuestScriptRef.iSetting2 = MyMessage2.Show()
MyQuestScriptRef.bAllSet = True
End Function

This is the script attached to the quest:
Spoiler
Scriptname MyQuestScript Extends Quest Conditional
Int Property intSetting1 = 0 Auto Conditional
Int Property intSetting2 = 0 Auto Conditional
Int Property intSetting3 = 0 Auto Conditional
Bool Property bAllSet = False Auto Conditional

Both of the scripts compile fine, all of the Properties are set through the CK, even the Quest script.
When I read the Book, the Messages pop up. But, nothing I've tried has worked, and I've been trying every permutation and variation I can think of. Then starting a new game to test with, to make sure there's no save-game left-overs, a dozen times or more.

But, I am stumped (for now)... What's the secret? Just how the heck are properties passed between scripts in Papyrus?
User avatar
Danii Brown
 
Posts: 3337
Joined: Tue Aug 22, 2006 7:13 am

Post » Thu Jun 21, 2012 5:11 am

Is the MyQuestScript property filled and pointed to the quest the script is attached to?
User avatar
jessica Villacis
 
Posts: 3385
Joined: Tue Jan 23, 2007 2:03 pm

Post » Wed Jun 20, 2012 6:48 pm

Thanks for a quick reply.

I just figured it out. The CK wasn't saving the .bsa archive in the Data folder. Instead it is placing the .bsa and the .bsl in the Skyrim folder. I moved the .bsa to the Data folder and everything started working like it should. Buggy tools can drive a coder bonkers.


Edit: There's a lesson here... The scripts ran fine individually without the .bsa file, but it turns out the .bsa file is essential for passing properties between scripts. Good to know.
User avatar
Casey
 
Posts: 3376
Joined: Mon Nov 12, 2007 8:38 am

Post » Wed Jun 20, 2012 3:40 pm

but it turns out the .bsa file is essential for passing properties between scripts. Good to know.
THe BSA isn't a necessity to cross reference your scripts. Not sure just what happened, but that ain't it.
User avatar
lucile davignon
 
Posts: 3375
Joined: Thu Mar 22, 2007 10:40 pm


Return to V - Skyrim