Papyrus theory question

Post » Wed Jun 20, 2012 6:07 am

I'm just trying to get a better understanding of how something works in Papyrus: using a full property to obtain a property from another script.

I've already done this once on my own (using a script written by someone else as a guide to setting it up):

aaTKVersionStorage property fetchVersion    aaTKVersionStorage function get()        if !fetchSet            fetchSet = true            fetchVal = (Self as Quest) as aaTKVersionStorage        endif        return fetchVal    endFunctionendPropertyaaTKVersionStorage fetchValbool fetchSet = false

The purpose is to obtain read-only properties from the given script and pass them to the script this full property resides in.

I'd just like to understand better what is happening here.
User avatar
Jonathan Braz
 
Posts: 3459
Joined: Wed Aug 22, 2007 10:29 pm

Post » Wed Jun 20, 2012 3:33 pm

I'm just trying to get a better understanding of how something works in Papyrus: using a full property to obtain a property from another script.

I've already done this once on my own (using a script written by someone else as a guide to setting it up):

aaTKVersionStorage property fetchVersion	aaTKVersionStorage function get()		if !fetchSet			fetchSet = true			fetchVal = (Self as Quest) as aaTKVersionStorage		endif		return fetchVal	endFunctionendPropertyaaTKVersionStorage fetchValbool fetchSet = false

The purpose is to obtain read-only properties from the given script and pass them to the script this full property resides in.

I'd just like to understand better what is happening here.


Interesting question.

OK: One of the standard techniques of Object Oriented Stuff (to use the technical term) is to have functions that present themselves as data elements. So in this case we have a property value that isn't a constant, but which is calculated on the fly each time it is accessed. I didn't know Papyrus could do this, but it's potentially very useful.

So "aaTKVersionStorage" is the type of the property. "Property" is a keyword, of course. fetchVersion is the name of the property to the external world.

Now the idea here is that we have a local variable that needs initialising, and thereafter holds the property in question. So we have a bool to say if the value has been fetched, and another local variable to hold the value. The property method itself just checks to see if the value variable is set, sets it if not, and sets a flag to say it's been set. It's pretty trivial, but serves as an illustration well enough.
User avatar
Karine laverre
 
Posts: 3439
Joined: Tue Mar 20, 2007 7:50 am

Post » Wed Jun 20, 2012 8:19 am

fetchset starts false, and will correspond to fetchVal == None (so the fetchset bool is not really needed as a test for None could be done)

The first time the fetchVersion property is read, fetchVal is None, so is assigned to the script quest script aaTKVersionStorage (which I'm guessing is *another* script attached to the same quest, not the one this is running in as the caller must already have that.)
Then a ref to that script is returned.
Subsequent reads can skip the assignment, and return the stored value.

That's what it's doing, but I'm wondering why.

Edit: Ninja'd by DocClox
User avatar
Emmie Cate
 
Posts: 3372
Joined: Sun Mar 11, 2007 12:01 am

Post » Wed Jun 20, 2012 12:28 am

I whomped up a commented version, in the hopes of making it clearer.

;; flag to say if the data variable "fetchVal" has in fact been set.; starts out false to show that we need to initialise "fetchVal";bool fetchSet = false;; this is "fetchVal", of type aaTKVersionStorage which would appear to be a; quest subclass from the code that follows. We could have saved the bool by setting; this to None, initially;aaTKVersionStorage fetchVal;; this defines a function that will act as a read-only property called "fetchVersion";aaTKVersionStorage property fetchVersion;;	inside the property definintion there are (potentially) two funcs called "get" and "set";	"get" returns the value of the propery and "set" sets it. By specifying only one of the two;	 you can make a prop read or write-only;;	in this case we only have a get - so its read only;	aaTKVersionStorage function get();;		if the value is already initialised, we can just return it;		if fetchSet			return fetchVal		endif;;		ok - fetchSet is NOT set, so we need to set it and fetchVal;		fetchVal is just the value of the current script (trivial);		fetchVal = (Self as Quest) as aaTKVersionStorage;;		and then set fetchSet to true so we don't do it again;		fetchSet = true;;		lastly, return the value;		return fetchVal	endFunctionendProperty
User avatar
Emily Graham
 
Posts: 3447
Joined: Sat Jul 22, 2006 11:34 am

Post » Wed Jun 20, 2012 11:11 am

That's what it's doing, but I'm wondering why.

I'm wondering that too since there's an easier way to do it.

I think the OP should probably post both scripts including names. It will make things clearer.
User avatar
Bee Baby
 
Posts: 3450
Joined: Sun Jun 18, 2006 4:47 am

Post » Wed Jun 20, 2012 12:04 am

Hm, this seems overall pretty useless to me. All it could accomplish is to save a few keystrokes, which you actually didn't have to type in the first place, if you're using a smart text editor -- auto-completion.
User avatar
joeK
 
Posts: 3370
Joined: Tue Jul 10, 2007 10:22 am

Post » Wed Jun 20, 2012 7:17 am

The script we're looking at can't be the same script being returned. There must be a script called aaTKVersionStorage.psc also attached to this quest.

Maybe there are a few quests scripts like this, and they all return the same aaTKVersionStorage that is attached to this quest? I dunno.


Anyhow this is something to do with version management. So this is a related Q.
To stop the version No. getting baked into savegames I've gone with the globalVariable with the static flag.
I found out a while ago when the compiler cursed at me that autoReadOnly actually means Constant. Anyone know if these autoReadOnly's get baked into savefiles?
User avatar
Cartoon
 
Posts: 3350
Joined: Mon Jun 25, 2007 4:31 pm

Post » Wed Jun 20, 2012 2:50 pm

fetchset starts false, and will correspond to fetchVal == None (so the fetchset bool is not really needed as a test for None could be done)

The first time the fetchVersion property is read, fetchVal is None, so is assigned to the script quest script aaTKVersionStorage (which I'm guessing is *another* script attached to the same quest, not the one this is running in as the caller must already have that.)
Then a ref to that script is returned.
Subsequent reads can skip the assignment, and return the stored value.

That's what it's doing, but I'm wondering why.

Edit: Ninja'd by DocClox

Yes, the aaTKVersionStorage quest is attached to the same quest the script I pulled that property out of is attached to. Using that property allows me to borrow the values of any properties assigned to the script it references (so long as the scripts remain paired to the same object) simply by calling fetchVersion.{Property name as defined in aaTKVersionStorage here}.

Here are the full scripts I am using for this:

Spoiler
scriptname aaTKVersionControl extends Questquest property aaTKEconomicsControl autoMessage property aaTKUpdateMSG autoFloat VersionNumberEvent OnUpdate()	If(VersionNumber == 0)		VersionNumber = FetchVersion.VersionNumber	ElseIf(VersionNumber != fetchVersion.VersionNumber)		UpdateVersion()	EndIf	RegisterForSingleUpdate(15)EndEventaaTKVersionStorage property fetchVersion	aaTKVersionStorage function get()		if !fetchSet			fetchSet = true			fetchVal = (Self as Quest) as aaTKVersionStorage		endif		return fetchVal	endFunctionendPropertyaaTKVersionStorage fetchValbool fetchSet = falseFunction UpdateVersion()	VersionNumber = fetchVersion.VersionNumber	aaTKEconomicsControl.setStage(0)	aaTKUpdateMSG.Show(VersionNumber)EndFunctionFunction VersionCheckStart()	RegisterForSingleUpdate(1)EndFunction

scriptname aaTKVersionStorage extends QuestFloat property VersionNumber = 0.15 autoreadonly

The Quest in question is what sends the initial start-up trigger to my mod, telling the Initialization script to fire, which in turn fires the start-up functions for all of my other scripts. The Version Control script is set up so that by changing the value of the Property in the VersionStorage script, it will signal the quest to revert to Stage 0 and re-fire the initialization script. This allows me to add new scripts into the mod without the users needing to clean-save.
User avatar
Darrell Fawcett
 
Posts: 3336
Joined: Tue May 22, 2007 12:16 am

Post » Wed Jun 20, 2012 11:45 am

Thanks Thomas, and I think that also answers my Q about autoreadonly's not being baked into the saves :)
User avatar
cassy
 
Posts: 3368
Joined: Mon Mar 05, 2007 12:57 am

Post » Wed Jun 20, 2012 4:07 am

Yup, that's exactly why this works at all.

Pretty handy if you have script that needs a bunch of default variables passed to it that you'd like to be able to change in between versions.
User avatar
Manny(BAKE)
 
Posts: 3407
Joined: Thu Oct 25, 2007 9:14 am

Post » Wed Jun 20, 2012 5:44 am

I'm curious why you chose this way ...

aaTKVersionStorage property fetchVersion	aaTKVersionStorage function get()		if !fetchSet			fetchSet = true			fetchVal = (Self as Quest) as aaTKVersionStorage		endif		return fetchVal	endFunctionendPropertyaaTKVersionStorage fetchValbool fetchSet = false

... when a single line of code like this ...

aaTKVersionStorage property fetchVersion auto

should work the same. You then give your property the required value http://www.creationkit.com/Bethesda_Tutorial_Papyrus_Introduction_to_Properties_and_Functions#Hooking_up_the_message_boxes_to_the_properties_in_the_script. Autofill won't work. You need to use the Edit Value button.

So your original question is about the following line only and why it works.

aaTKVersionStorage fetchVal = (Self as Quest) as aaTKVersionStorage
User avatar
Peetay
 
Posts: 3303
Joined: Sun Jul 22, 2007 10:33 am

Post » Wed Jun 20, 2012 2:52 pm

I'm curious why you chose this way ...

aaTKVersionStorage property fetchVersion	aaTKVersionStorage function get()		if !fetchSet			fetchSet = true			fetchVal = (Self as Quest) as aaTKVersionStorage		endif		return fetchVal	endFunctionendPropertyaaTKVersionStorage fetchValbool fetchSet = false

... when a single line of code like this ...

aaTKVersionStorage property fetchVersion auto

should work the same. You then give your property the required value http://www.creationkit.com/Bethesda_Tutorial_Papyrus_Introduction_to_Properties_and_Functions#Hooking_up_the_message_boxes_to_the_properties_in_the_script. Autofill won't work. You need to use the Edit Value button.

So your original question is about the following line only and why it works.

aaTKVersionStorage fetchVal = (Self as Quest) as aaTKVersionStorage

Because doing it that way bakes the value into the save; any changes I make to it won't register if the mod has already been installed by the user (the game will revert the value back to what I first set it to). That is exactly what I don't want to happen.
User avatar
carla
 
Posts: 3345
Joined: Wed Aug 23, 2006 8:36 am

Post » Wed Jun 20, 2012 7:04 am

Because doing it that way bakes the value into the save; any changes I make to it won't register if the mod has already been installed by the user (the game will revert the value back to what I first set it to). That is exactly what I don't want to happen.

So your original question then is why does doing it your way (get reference at runtime) work, when doing it the other way (get reference at compile time) does not?
User avatar
Lauren Graves
 
Posts: 3343
Joined: Fri Aug 04, 2006 6:03 pm

Post » Wed Jun 20, 2012 9:22 am

All this would be solved with a OnGameLoaded () and OnGameRestarted () Events like in OBSE. I've not looked into the SKSE thread but I'm hoping that it would have these.
For the meantime, I've been using my Quest Script "starter" to detect these events.
http://www.gamesas.com/topic/1349590-init-at-game-load-and-init-at-game-restart
User avatar
Andrew Tarango
 
Posts: 3454
Joined: Wed Oct 17, 2007 10:07 am


Return to V - Skyrim