What are all the causes for a Global to temporarily read as

Post » Sat Nov 17, 2012 5:41 pm

Its gotten to the point where I am starting to want to give up. I have been fighting this for awhile and I am not sure what is going on. A simple script that should work with no problems at all is completely messing up. Its been days of this trying to get it to work. Sometimes it works fine other times it randomly just self destructs...

So I decided to add this to my script.

if ATHSthirstValue.getvalue() == 0
Debug.Notification("ThirstValue =http://forums.bethsoft.com/topic/1399588-what-are-all-the-causes-for-a-global-to-temporarily-read-as-0/= 0")

else
Debug.Notification("ThirstValue =http://forums.bethsoft.com/topic/1399588-what-are-all-the-causes-for-a-global-to-temporarily-read-as-0/=" + ATHSthirstValue.getvalue())

endif

Sure enough, it became immediately obvious that 3 of my most important global variables will suddenly and randomly become 0. I thought I got away from the problem by separating the script into smaller chunks but I now know it was just random luck. The few times I tested after this happened the variables simply behaved...

Does anyone here know what are the possible causes for global variables to suddenly and temporarily read as 0.00000?
Are there ways around this problem??
User avatar
Claudz
 
Posts: 3484
Joined: Thu Sep 07, 2006 5:33 am

Post » Sat Nov 17, 2012 3:19 pm

I think I experienced similar behaviour because of multiple threads accessing the variable at the same time. Do you use States to make sure there is only one thread at a time? You can also use RegisterForSingleUpdate (also at the bottom of the script) instead of RegisterForUpdate to prevent multiple threads.

If that doesn't work, just switch to using quest Properties instead of Global Variables. Properties can be accessed by any other script and in that regard are the same as Global Variables, so there's no reason why you couldn't use them instead. It's even considered better practice than using Globals.
User avatar
Stephani Silva
 
Posts: 3372
Joined: Wed Jan 17, 2007 10:11 pm

Post » Sat Nov 17, 2012 12:03 pm

i agree with Maegfer, it sounds like a threading issue
User avatar
Alexx Peace
 
Posts: 3432
Joined: Thu Jul 20, 2006 5:55 pm

Post » Sat Nov 17, 2012 8:49 pm

What event are you using that in? I had similar problems, and I discovered that it was the OnPlayerBowShot event that was messing things up (added in 1.6). I switched to OnAnimationEvent and everything has been working fine since.
User avatar
Smokey
 
Posts: 3378
Joined: Mon May 07, 2007 11:35 pm

Post » Sat Nov 17, 2012 10:55 am

hmm whats the syntax for accessing a variable in another script? Its looking a lot like that's what I am going to need to do...
User avatar
Mandi Norton
 
Posts: 3451
Joined: Tue Jan 30, 2007 2:43 pm

Post » Sun Nov 18, 2012 1:34 am

(Objectname as ScriptnameThatIsAttachedToTheObject).PropertyName

ex:
if (DialogueFollower as DialogueFollowerScript).iFollowerDismiss == 0
DoSomething()

EndIf
User avatar
Steve Fallon
 
Posts: 3503
Joined: Thu Aug 23, 2007 12:29 am

Post » Sat Nov 17, 2012 10:23 pm

errr... wait....huh?

So an actor with a magic effect script weapon variable can be accessible like:



Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)

Weapon MyLeftWeap = (akAggressor as MyAbilityMagicScript).WeaponInLeftHand

EndEvent

Would give me their left handed weapon assuming that the MyAbilityMagicScript properly assigned that to the WeaponInLeftHand weapon variable?




(Objectname as ScriptnameThatIsAttachedToTheObject).PropertyName

ex:
if (DialogueFollower as DialogueFollowerScript).iFollowerDismiss == 0
DoSomething()

EndIf
User avatar
!beef
 
Posts: 3497
Joined: Wed Aug 16, 2006 4:41 pm

Post » Sat Nov 17, 2012 10:04 pm

i'm not sure if that will compile. most likely it will throw an error that the types are mismatched (objectreference variable cast as an activemagiceffect script is not gonna work)
User avatar
NO suckers In Here
 
Posts: 3449
Joined: Thu Jul 13, 2006 2:05 am

Post » Sat Nov 17, 2012 4:46 pm

So an actor with a magic effect script weapon variable can be accessible like:



Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)

Weapon MyLeftWeap = (akAggressor as MyAbilityMagicScript).WeaponInLeftHand

EndEvent

Would give me their left handed weapon assuming that the MyAbilityMagicScript properly assigned that to the WeaponInLeftHand weapon variable?

In your particular example it would be easier to just do:

akAggressor.GetEquippedWeapon(True)

But I assume that what you want in general is that the aggressor has a weapon equipped, to that weapon a script is attached and you want to read/write a variable in that script? I'm not sure if that's possible because inventory items (like equipped weapons) don't have a reference (at least that's how I always understood it). Using functions like GetEquippedWeapon returns the base object, to get a variable from a script attached to an object you need the reference to that object in order to get the reference to the script containing the desired variable. I'm not really sure how to get the reference to such a script. I would suggest trying to write the variable from inside the weapon script to a property variable in a script that is attached to the Actor, since the reference to the Actor is easily available. Then it would be done like this:

MyAbilityMagicScript Property myScriptRef Auto
myScriptRef = akAggressor as myAbilityMagicScript
myScriptRef.myRemoveVar = whatever
User avatar
Thema
 
Posts: 3461
Joined: Thu Sep 21, 2006 2:36 am

Post » Sat Nov 17, 2012 12:22 pm

So in my case I need to have 3 variables that are accessed by various other scripts.

So I made float variables in my main script like this
Float Property ATHSThirstValueN Auto

How do I get access to these 3 variables in other quest scripts?

if (ATHSBaseN1QUEST as ATHSBaseN1SCRIPT).ATHSThirstValueN == 1.2
DoSomething()

EndIf

Does not seem to want to compile... Maybe I am just not reading this correctly bleh...
User avatar
kelly thomson
 
Posts: 3380
Joined: Thu Jun 22, 2006 12:18 pm

Post » Sat Nov 17, 2012 4:34 pm

Put this in the other script:

ATHSBaseN1SCRIPT Property myScript AutoEvent OnWhatever   myScript = ATHSBaseN1QUEST as ATHSBaseN1SCRIPT   If myScript.ATHSThirstValueN == 1.2	  ;Do Whatever   EndIfEndEvent
User avatar
Lillian Cawfield
 
Posts: 3387
Joined: Thu Nov 30, 2006 6:22 pm

Post » Sun Nov 18, 2012 12:03 am

I imagine that this can also be done by accessing functions from the base script? I have been meaning to learn more about passing variables through functions so maybe this is a good chance to do that.

import ATHSBaseN1SCRIPT

LocalThirstValue = http://forums.bethsoft.com/topic/1399588-what-are-all-the-causes-for-a-global-to-temporarily-read-as-0/ATHSBaseN1SCRIPT.GetThirstValue()

ATHSBaseN1SCRIPT.SubtractThirstValue( o.1 )
Does this work on magic effects for foods and potions as well? Does this seem like a viable method for me to do this?
User avatar
Katie Louise Ingram
 
Posts: 3437
Joined: Sat Nov 18, 2006 2:10 am

Post » Sun Nov 18, 2012 2:16 am

I don't think you should import your base quest script, since there will be Events in it also I guess? Better make a separate script with your custom functions that you can import, and use function parameters to pass variables from the base quest script if you need that.

Not 100% sure about this, I haven't used importing much yet.
User avatar
Adam
 
Posts: 3446
Joined: Sat Jun 02, 2007 2:56 pm

Post » Sat Nov 17, 2012 7:55 pm

TheCastle,

This has happened to me in the past. It almost always is a result (in my case) of a user upgrading from one mod version to the next. What can occur is that an instance of that global can appear multiple times in someone's save game; they are essentially "orphaned", stuck in the player's savegame. Unused, but still there. I don't understand the exact circumstances where this can happen. Perhaps when they're being read from / written to at save-game time and the .ESP changes? I'm not sure.

The good news is that these orphaned globals always initialize to 0. So, for boolean-style flags, I have made it a personal practice to always use 2 for True and 1 for False, instead of the traditional 1 and 0. I also don't use globals in such a fashion that I rely on them being exactly zero. 0.00001 and -0.00001 is just fine.

Your script's logic will hit on these orphaned globals if they exist, if your condition matches one of them. i.e., if you write two condition functions, "if global.getvalue() == 0" and "global.getvalue() == 1", and you have a "real" global whose value is 1, and an orphan (or multiple orphans) whose value is 0, they will both return True.

I'm not sure if this is applicable to your specific situation but I hope this information helps.

Edit: also I second the suggestion of making these script properties instead of globals, if you can get away with it. The only real issue with doing this is that you can't easily use the value in a condition function, and it makes in-game testing much more difficult (you can't set a script property value at runtime nearly as easily as a global using the "set x to y" console command)
User avatar
Emerald Dreams
 
Posts: 3376
Joined: Sun Jan 07, 2007 2:52 pm

Post » Sat Nov 17, 2012 11:07 am

OMG Chesko! This has been plaguing the hell out of me for more than a week. I have seen all kinds of random crap happening where a single variable can be two values at the same time!!
It has been driving me absolutely insane attempting to understand how its even possible. I have even had some instances where a script would continue to run even after I completely disable the mod and remove all the files from the directory XD
As the the entire mod seemed to be saved to my save game leaving me wonder how impossible this is but actually watching it happen...

Your explanation explains a lot about how this is even possible...
User avatar
Tasha Clifford
 
Posts: 3295
Joined: Fri Jul 21, 2006 7:08 am

Post » Sun Nov 18, 2012 12:38 am

I had no specif goal in mind in my previous example, I am just trying to understand what variables can be read from another script and how to do it with scripts like magic effects that are sometimes temp (not persistent). But the most important thing for me is to be able to pass actor reference's from one temporary script to another.


NOW I do have a specif goal in mind:

say my follower is fighting a dragon with me, the dragon is his combat target reference and a actor ref var is set to that in their magic ability script he is running (ME ability script to make him dodge lets say). How would I transfer his combat ref actor var to the player's same temp ME dodge script?


In your particular example it would be easier to just do:

akAggressor.GetEquippedWeapon(True)

But I assume that what you want in general is that the aggressor has a weapon equipped, to that weapon a script is attached and you want to read/write a variable in that script? I'm not sure if that's possible because inventory items (like equipped weapons) don't have a reference (at least that's how I always understood it). Using functions like GetEquippedWeapon returns the base object, to get a variable from a script attached to an object you need the reference to that object in order to get the reference to the script containing the desired variable. I'm not really sure how to get the reference to such a script. I would suggest trying to write the variable from inside the weapon script to a property variable in a script that is attached to the Actor, since the reference to the Actor is easily available. Then it would be done like this:

MyAbilityMagicScript Property myScriptRef Auto
myScriptRef = akAggressor as myAbilityMagicScript
myScriptRef.myRemoveVar = whatever
User avatar
jess hughes
 
Posts: 3382
Joined: Tue Oct 24, 2006 8:10 pm

Post » Sat Nov 17, 2012 11:10 am

Scriptname FollowerDodgeScript Extends MagicEffectActor Property myCombatTarget

Scriptname PlayerDodgeScript Extends MagicEffectActor Property myFollower AutoActor Property myFollowerCombatTarget AutoFollowerDodgeScript Property myFollowerDodgeScript AutoOnEvent Whatever  myFollowerDodgeScript = myFollower as FollowerDodgeScript  myFollowerCombatTarget = myFollowerDodgeScript.myCombatTargetEndEvent

Note that in this example I assume that the Actor Property myFollower in the player's script is already filled with your follower's reference. I also assume that the Actor Property myCombatTarget in the follower's script is already filled with the combat target of your follower.

The names of the script can be the same (or in other words, both actors can have the same script), I just used different names to make it clearer.

To break it down:

FollowerDodgeScript Property myFollowerDodgeScript Auto
Here we create a new Property variable of type FollowerDodgeScript. Just like a Property variable of type Actor can contain an Actor reference, a Property variable of type FollowerDodgeScript can contain a reference to an instance of the FollowerDodgeScript. This Property variable is called myFollowerDodgeScript.


myFollowerDodgeScript = myFollower as FollowerDodgeScript
Here we fill the currently empty Property myFollowerDodgeScript with a reference to the instance of script FollowerDodgeScript that is attached to the Actor whose reference is stored in the Property myFollower.


myFollowerCombatTarget = myFollowerDodgeScript.myCombatTarget
Here we reference to the FollowerDodgeScript instance that we stored in the previous line and grab the value of the variable myCombatTarget in that script, and store it in myFollowerCombatTarget which belongs to the local script.
User avatar
W E I R D
 
Posts: 3496
Joined: Tue Mar 20, 2007 10:08 am

Post » Sat Nov 17, 2012 1:06 pm

as i've mentioned before, that script is not going to compile.

you cannot cast an actor to a magiceffect script. and i think you mean activemagiceffect, and not magiceffect, but either way an actor property/variable can only be cast as a script that extends actor


as far as i know, you cannot cast an object to an activemagiceffect script. you can only cast it to a script that is physically attached to an object (as in attached via editor, not temporary spell)

however, there is nothing stopping you from pre-empting the system. in other words, send your values OUT of your activemagiceffect script instead of pulling them IN from an external script.




MyAbility extends ActiveMagicEffectQuest Property MyQuestMadeSolelyForTheSakeOfStoringValues AutoEvent OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)   (MyQuestMadeSolelyForTheSakeOfStoringValues as QuestScript).SomeActorProperty = (akAggressor as Actor)EndEvent

you have successfully captured your akAggressor as a manipulatable and externally accessible actor property. of course there still are limitations to using it this way
User avatar
Neko Jenny
 
Posts: 3409
Joined: Thu Jun 22, 2006 4:29 am

Post » Sat Nov 17, 2012 5:22 pm

you cannot cast an actor to a magiceffect script. and i think you mean activemagiceffect, and not magiceffect, but either way an actor property/variable can only be cast as a script that extends actor

Bah, that teaches from talking about magic effect scripts while not having used them yet at all. I thought they would work the same as directly attached scripts. Thanks for the correction.
User avatar
Chris Guerin
 
Posts: 3395
Joined: Thu May 10, 2007 2:44 pm

Post » Sat Nov 17, 2012 6:19 pm

as far as casting as scripts, it works this way for any script, not just activemagiceffect.

you wont ever be able to compile a script if you are using a property cast as a script that is not extending the same type. however, if your proprty is of a type that extends another, you can "dual cast" it successfully. for example, casting an actor first as an objectreference and then casting the objectreference as a script that extends objectreference


the thing with active magic effect scripts specifically, is that the type does not extend anything, and i don't believe that they are castable as objects (i could be wrong about this though), which is why for activemagiceffect scripts, they cannot be used as properties normally like any of the other script types. there is no object type activemaggiceffect, there is magiceffect, but that is not exactly the same thing afaik
User avatar
REVLUTIN
 
Posts: 3498
Joined: Tue Dec 26, 2006 8:44 pm


Return to V - Skyrim