Using 1 variable in 2 scripts

Post » Sun Nov 18, 2012 9:10 pm

Hi guys,

I'm having some trouble getting my scripts to work correctly. I want to use one variable in both scripts, but I don't get the variable from one script to the other.

Here is what I have so far:

Scriptname ExhaustedOptionsMenu extends ActiveMagicEffectInt Property IntBS AutoInt Property IntH AutoInt Property IntM AutoInt Property IntS Auto

Scriptname Exhausted Extends QuestExhaustedOptionsMenu OptionsMenuEvent OnUpdate()   Int BlackSight = OptionsMenu.IntBS   Int Health = OptionsMenu.IntH   Int Magicka = OptionsMenu.IntM   Int Stamina = OptionsMenu.IntSEndEvent

The unrelevant parts of the script are cuttet out.
Some help would be really nice. :smile:
User avatar
Andy durkan
 
Posts: 3459
Joined: Fri Aug 03, 2007 3:05 pm

Post » Sun Nov 18, 2012 12:15 pm

What happens with your scripts currently? I assume you're pointing your OptionsMenu variable at an object before attempting to access its properties? It looks like you're using the right syntax to access them, but unless OptionsMenu actually points to the right object you won't be able to access that information.

I've written a tutorial on http://cipscis.com/skyrim/tutorials/externalaccess.aspx that you might find interesting.

Cipscis
User avatar
Albert Wesker
 
Posts: 3499
Joined: Fri May 11, 2007 11:17 pm

Post » Sun Nov 18, 2012 12:24 pm

you cant access activemagiceffectscripts remotely.

you can only access remote scripts that are attached to actual objects. active magic effects do not exist until they are successfuly cast (note, an "active magic effect" is different from a magic effect object)

your best bet is to access your quest script FROM your activemagiceffectscript, instead of the other way around
User avatar
The Time Car
 
Posts: 3435
Joined: Sat Oct 27, 2007 7:13 pm

Post » Sun Nov 18, 2012 5:49 pm

You could use global variables (you need to create them in the CK and then create properties for them in both scripts (globalvariable properties). They are not accessed as normal properties though. http://www.creationkit.com/Global http://www.creationkit.com/GlobalVariable_Script
User avatar
Shelby McDonald
 
Posts: 3497
Joined: Sat Jan 13, 2007 2:29 pm

Post » Sun Nov 18, 2012 3:40 pm

Thank you very much! I've used the global method.

@Cipscis: Nice tutorial, I will bookmark it. :thumbsup:
User avatar
yessenia hermosillo
 
Posts: 3545
Joined: Sat Aug 18, 2007 1:31 pm

Post » Sun Nov 18, 2012 5:24 pm

Well, I was raised to think Globals are evil. :smile:

Do they need to be Properties? I haven't actually tested if variables and properties work the same, but in my scripts, I pass data between them like so:

Scriptname ExhaustedOptionsScript extends Quest ; ActiveMagicEffectActor Property PlayerRef; PrivateInt iBlackSightInt iHealthInt iMagickaInt iStaminaEvent OnInit()	; Initialize values here    iHealth = (PlayerRef.GetAV("health") as Int)    ;;; etcEndEvent; Define public gettersInt Function GetBlackSight() ; You could also name it just iBlackSight()	return iBlackSightEndFunctionInt Function GetHealth() ; You could also name it just iHealth()	return iHealthEndFunctionInt Function GetMagicka() ; You could also name it just iMagicka()	return iMagickaEndFunctionInt Function GetStamina() ; You could also name it just iStamina()	return iStaminaEndFunction; Define public settersFunction SetBlackSight(int val)	iBlackSight = valEndFunctionFunction SetHealth(int val)	iHealth = valEndFunctionFunction SetMagicka(int val)	iMagicka = valEndFunctionFunction SetStamina(int val)	iStamina = valEndFunction;;;;;;;;;Scriptname ExhaustedScript Extends QuestExhaustedOptionsScript Property Options AutoEvent OnUpdate()   Int BlackSight = Options.GetBlackSight()   Int Health = Options.GetHealth()   Int Magicka = Options.GetMagicka()   Int Stamina = Options.GetStamina()EndEvent;;;;;;;;;Scriptname ExhaustedOptionsMenuScript Extends activemagiceffect; Do whatever menu-y stuff here 
You didn't really show enough code to get an idea of your usage case, but I would always prefer something like this to globals. I'm not certain how globals work really but both methods are probably susceptible to race conditions.
User avatar
The Time Car
 
Posts: 3435
Joined: Sat Oct 27, 2007 7:13 pm

Post » Sun Nov 18, 2012 3:40 pm



If you want to share variables between scripts, they have to be properties. Normal variables are local only, no other scripts can access them. Properties are global.
User avatar
Ebou Suso
 
Posts: 3604
Joined: Thu May 03, 2007 5:28 am

Post » Sun Nov 18, 2012 2:47 pm

If you want to share variables between scripts, they have to be properties. Normal variables are local only, no other scripts can access them. Properties are global.
Well, my variables somehow magically work despite this. (The example above is an adaption of my working scripts)


I think maybe you're missing that the Functions that set and get the private variables are public. For reference: http://en.wikipedia.org/wiki/Mutator_method
User avatar
Rude_Bitch_420
 
Posts: 3429
Joined: Wed Aug 08, 2007 2:26 pm

Post » Sun Nov 18, 2012 10:16 am

Well, my variables somehow magically work despite this. (The example above is an adaption of my working scripts)


I think maybe you're missing that the Functions that set and get the private variables are public. For reference: http://en.wikipedia.org/wiki/Mutator_method

In that case you are communicating the variables between the scripts via an intermediary, I'm talking about straight-up access (which is what the OP is talking about). You can't directly share the values of variables between scripts, nor can other scripts directly modify the values.
User avatar
yessenia hermosillo
 
Posts: 3545
Joined: Sat Aug 18, 2007 1:31 pm

Post » Sun Nov 18, 2012 11:28 am

Well, my variables somehow magically work despite this.

You have "ExhaustedOptionsScript Property Options Auto"--so it isn't magic, you're using a property to allow access to remote functions that deliver the values of remote variables.

To the OP, while there may be other factors involved with the specifics of what you're trying to do, this is the conceptual issue. When you extend a data type, you create a new child data type. So "Scriptname ExhaustedOptionsMenu extends ActiveMagicEffect" creates a new datatype of "ExhaustedOptionsMenu".

It is only when you attach a script to a game object that you create an instance of that data type, with its own unique set of local values.

So in your second script, when you do

ExhaustedOptionsMenu OptionsMenu

You are creating a new local, empty instance of the ExhaustedOptionsMenu datatype.

If you want to access the values stored in another, already existing instance of that datatype, then you need to declare it as a property and fill it with the specific instance you want in the CK's Properties box.

ExhaustedOptionsMenu Property OptionsMenu Auto

(Everybody uses slightly different terminology for these concepts--what I'm calling data types and instances--but hopefully you get the idea.)

It can be a little confusing because often you only have one instance of the datatype--a script that extends Quest to provide functionality specific to that quest, for example--and so there is the temptation to see the datatype and the instance as the same thing. But they aren't.
User avatar
Taylah Haines
 
Posts: 3439
Joined: Tue Feb 13, 2007 3:10 am

Post » Sun Nov 18, 2012 2:53 pm

I preffer to use properties over variables, but to say the truth glovals can be accessed by variables. As Thomas Kaira says, you can't share variables between scripts without an intermediare. In this case, the same global, is the intermediary as it's an object external to any script.

It's the same as if you use a variable to access an actor value, it will affect the actor value itself, so, any other script using the same as a variable or a property will obtain the changed result when accessing it.
User avatar
Floor Punch
 
Posts: 3568
Joined: Tue May 29, 2007 7:18 am

Post » Sun Nov 18, 2012 8:37 am

Well, my variables somehow magically work despite this. (The example above is an adaption of my working scripts)

I think maybe you're missing that the Functions that set and get the private variables are public.

Well, if you're going to use getters and setters anyway, why not wrap them in a property anyway and take advantage of the syntactic sugar:

scriptname Foo extends ObjectReference conditionalint _ival = -1 conditionalproperty ival	int function get()		return _ival	endfunction	function set(int v)		_ival = v	endfunctionendproperty

That's without benefit of the CK or my notepad++ syntax but it should work.

Since we're wandering off topic anyway: does anyone have any feel for the pros and cons of GlobalVariable vs Properties vs Script variables. My own instinct is to go for script vars as well, but I assume there's a reason for globals still existing.

Is there any efficiency to be gained with a global, or is it just a compatibility hack for the parts of the CK that don't yet understand Papyrus?
User avatar
Lady Shocka
 
Posts: 3452
Joined: Mon Aug 21, 2006 10:59 pm

Post » Sun Nov 18, 2012 11:26 pm

The advantage of the http://www.creationkit.com/Variables_and_Properties#Auto_Properties keyword in creating properties is that it will set up a property to automatically have these getters and setters as well as optimising it so that accessing it is as efficient as accessing a variable.

In comparison, setting these getters and setters up manually (for a property or a variable) will only add extra overhead. It will do exactly the same thing, except slower and less efficiently.

I don't think there's any particular disadvantage to using properties instead of variables, and if the information stored in them should be externally accessible then they really should be properties. If you don't want your properties to be exposed to the Creation Kit, then declare them with the http://www.creationkit.com/Flag_Reference#Property_Flags flag.

Cipscis
User avatar
Josh Sabatini
 
Posts: 3445
Joined: Wed Nov 14, 2007 9:47 pm

Post » Sun Nov 18, 2012 2:07 pm

Well, if you're going to use getters and setters anyway, why not wrap them in a property anyway and take advantage of the syntactic sugar:
Haha, I laughed when you called that "syntactic sugar". Taste sweet that does not... It's harder to interpret. For example, are those private methods? Are there implicit public methods, such as GetValue() or SetValue()? I knew this syntax existed, but unless I look it up again, I don't actually know how to access the property's value. It's also, to me, much less intuitive to type something like Foo.val.Get() (or, again, is that just the private getter?) than it is to type Foo.GetVal(). Maybe this comes from when I learned PHP (and other languages) and always->had->to->type->like.this(). :smile:


I don't think there's any particular disadvantage to using properties instead of variables, and if the information stored in them should be externally accessible then they really should be properties. If you don't want your properties to be exposed to the Creation Kit, then declare them with the http://www.creationkit.com/Flag_Reference#Property_Flags flag.
Well even after reading http://www.creationkit.com/Save_File_Notes_(Papyrus), and forum topic after forum topic, I've still never seen a clear and concise explanation about their differences. To me, it seems like Properties are merely an abstraction of variables, which have ties (very strong ties, seemlngly) back to your plugin. Properties seems to have been made solely to make it easier on plugin designers (level artists, etc), and for this reason I generally steer clear of Properties unless I actually have to use them. I don't like defining every single thing in the CK, as I generally can't do much until it crashes on me. I also just don't like the script manager, properties window, etc. Again, it seems to me like it was made only to keep people from breaking the scripts.

And, after reading and re-reading the examples while writing this, I believe my assumptions about properties were correct, and that's why I avoid them. I read this page before but it was before I actually had gotten used to using Papyrus, and not just reading up on it.

I also don't see any explanation there about these so-called "optimizations" on Properties, which I feel in the best case would bring it up to the same performance as variables. It is an abstraction after all, and one that is more permanently tied to the game/objects/script instances. I would actually guess Properties have more overhead during init / script creation because of the tie-in with the CK, game objects, etc.. In the OP's case, Health, Magicka, and Stamina aren't even game objects, but values stored on a game object. I feel like a Property should be used if you need to fill a reference, alias, etc., but to store ints, floats, bools, I don't see the point. If there is something I'm missing feel free to share.

So lastly, assuming properties -- actually you suggest using hidden properties, which I suspect is just compile-time optimized to be identical to a variable -- and variables are equal, both having custom setters and getters, what is the extra advantage of a Property?

Also, any implementation is still going to suffer from possible race conditions when sharing a variable across multiple scripts, but I'd like to know if GlobalVariables are optimized to be thread safe. I still would never prefer using globals, unless thread safety was guaranteed.
User avatar
Angela
 
Posts: 3492
Joined: Mon Mar 05, 2007 8:33 am

Post » Sun Nov 18, 2012 1:46 pm

There's nothing wrong with globals and they're faster than remote vars, IIRC.

Iterated 10^5 times each...
  • Float fVar = OtherScript.fTestVar
    [08/23/2012 - 04:05:46PM] Start 01: 31.938999[08/23/2012 - 04:05:46PM] Finish 01: 32.911999[08/23/2012 - 04:05:46PM] Time elapsed 01: 0.973000

  • Float fVar = fTestGLOB.GetValue()
    [08/23/2012 - 04:05:54PM] Start 02: 39.616001[08/23/2012 - 04:05:54PM] Finish 02: 40.569000[08/23/2012 - 04:05:54PM] Time elapsed 02: 0.952999
Not much difference, but fTestGLOB was slightly faster. Suffice it to say, there's no reason to avoid using globals as they're so easily accessible.
User avatar
Chloe :)
 
Posts: 3386
Joined: Tue Jun 13, 2006 10:00 am

Post » Sun Nov 18, 2012 11:55 am

I don't know if the information on the optimisation of auto properties is available on the wiki, but I originally got the information from SkmViper, the Bethesda employee who was the mastermind behind designing Papyrus. I can't recall if the post was made in this forum or in the now removed Creation Kit beta forum, but you might be able to find it by searching for his posts.

Cipscis
User avatar
Nicola
 
Posts: 3365
Joined: Wed Jul 19, 2006 7:57 am

Post » Sun Nov 18, 2012 10:07 pm

Here's what I understand about the differences between properties and variables:

The most obvious difference is, of course, that properties are (unless flagged as Hidden) exposed to the Creation Kit. It's worth noting that, as far as I'm aware, flags (like Hidden) don't affect compilation, and are instead used only by the Creation Kit itself.

The other important difference is that properties are accessible from other scripts, whereas variables are not. This is because of the get and set functions for properties which are used behind the scenes (i.e. syntax is the same as for a variable). Functions are always accessible form other scripts, and this includes these two functions possessed by every property.

It's possible to manually define the get and set functions for a property, in which case I believe the performance would be comparable to your setup with variables that have had similar get and set functions defined. However, the more common approach is to use a keyword like Auto", in which case the "default" properties are set up automatically.

The important thing to realise here is that there is a difference in optimisation between a property set up with Auto and a property which has had the same default get and set functions defined manually. This optimisation makes access to the property as quick as direct access to a variable, so it doesn't have the extra overhead of a function call, and because it's a property it's still externally accessible.

This is why it's better to use properties whenever information should be available to other scripts instead of a variable with its own get and set functions. If you don't want the property to be accessible via the Creation Kit, the Hidden keyword can take care of that.



You're right in that properties are usually most useful as an interface to the Creation Kit. The main advantage of them though, as I see it, is abstracting away certain specifics from your script allowing it to be used in different places with a different configuration. For example, the vanilla script for the "Transfiguration" spell (sorry if I'm getting the name wrong - it's been a while since I played Skyrim) is set up such that a similar spell could be created that uses the exact same script but, by manipulating variables in the Creation Kit, works on a different set of items.

I hope that helps clarify things :)

Cipscis
User avatar
Dylan Markese
 
Posts: 3513
Joined: Sat Dec 01, 2007 11:58 am

Post » Sun Nov 18, 2012 9:29 pm

The best/cleanest/easiest way to handle variables/properties is to store them in Quests. Quests are persistent and are loaded at the game start. You can pass stuff between them pretty effortlessly using casting (as) and linking the actual quests via properties of other scripts.
User avatar
Holli Dillon
 
Posts: 3397
Joined: Wed Jun 21, 2006 4:54 am

Post » Sun Nov 18, 2012 9:08 pm

I nuse the lazy way of globals. They are, imo, easier to use and easier to debug and test. :)
User avatar
Gavin Roberts
 
Posts: 3335
Joined: Fri Jun 08, 2007 8:14 pm

Post » Sun Nov 18, 2012 12:43 pm

Haha, I laughed when you called that "syntactic sugar". Taste sweet that does not... It's harder to interpret.

The sugar lies in accessing the value, as opposed to defining it. if you use a property then you can write

	bar.foo = 1

rather than

	bar.SetFooValue(1)

If you want to sweeten the definition of your properties, use the Auto syntax.

int property foo auto

is exactly the same as

int _foo = -1int property foo	int function get()		return _foo	endfunction	function set(int v)		_foo = v	endfunctionendproperty

and functionally the same as writing

int _foo = -1int function GetValueFoo()	return _fooendfunctionfunction SetValueFoo(int v)	_foo = vendfunction

... apart as, Cipscis tells us above, from some optimisation .

The big advantage of hand rolled properties, of course, comes if you want to track the use of a value, or calculate one on the fly ... although then you can't use it in a condition funciton which is a bit of a shame.
User avatar
Michelle Smith
 
Posts: 3417
Joined: Wed Nov 15, 2006 2:03 am


Return to V - Skyrim